Home » apache-openjpa-1.1.0-source » org.apache.openjpa » enhance » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one
    3    * or more contributor license agreements.  See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership.  The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License.  You may obtain a copy of the License at
    9    *
   10    * http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    * Unless required by applicable law or agreed to in writing,
   13    * software distributed under the License is distributed on an
   14    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   15    * KIND, either express or implied.  See the License for the
   16    * specific language governing permissions and limitations
   17    * under the License.    
   18    */
   19   package org.apache.openjpa.enhance;
   20   
   21   import java.util.Collection;
   22   import java.util.Collections;
   23   import java.util.Iterator;
   24   import java.util.LinkedList;
   25   import java.util.Map;
   26   
   27   import org.apache.openjpa.lib.util.Localizer;
   28   import org.apache.openjpa.lib.util.ReferenceMap;
   29   import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
   30   import org.apache.openjpa.util.UserException;
   31   import org.apache.openjpa.util.InvalidStateException;
   32   
   33   /**
   34    * Tracks registered persistence-capable classes.
   35    *
   36    * @since 0.4.0
   37    * @author Abe White
   38    */
   39   public class PCRegistry {
   40       // DO NOT ADD ADDITIONAL DEPENDENCIES TO THIS CLASS
   41   
   42       private static final Localizer _loc = Localizer.forPackage
   43           (PCRegistry.class);
   44   
   45       // map of pc classes to meta structs; weak so the VM can GC classes
   46       private static final Map _metas = new ConcurrentReferenceHashMap
   47           (ReferenceMap.WEAK, ReferenceMap.HARD);
   48   
   49       // register class listeners
   50       private static final Collection _listeners = new LinkedList();
   51   
   52       /**
   53        * Register a {@link RegisterClassListener}.
   54        */
   55       public static void addRegisterClassListener(RegisterClassListener rcl) {
   56           if (rcl == null)
   57               return;
   58   
   59           // we have to be positive that every listener gets notified for
   60           // every class, so lots of locking
   61           synchronized (_listeners) {
   62               _listeners.add(rcl);
   63           }
   64           synchronized (_metas) {
   65               for (Iterator itr = _metas.keySet().iterator(); itr.hasNext();)
   66                   rcl.register((Class) itr.next());
   67           }
   68       }
   69   
   70       /**
   71        * Removes a {@link RegisterClassListener}.
   72        */
   73       public static void removeRegisterClassListener(RegisterClassListener rcl) {
   74           synchronized (_listeners) {
   75               _listeners.remove(rcl);
   76           }
   77       }
   78   
   79       /**
   80        * Get the field names for a <code>PersistenceCapable</code> class.
   81        */
   82       public static String[] getFieldNames(Class pcClass) {
   83           Meta meta = getMeta(pcClass);
   84           return meta.fieldNames;
   85       }
   86   
   87       /**
   88        * Get the field types for a <code>PersistenceCapable</code> class.
   89        */
   90       public static Class[] getFieldTypes(Class pcClass) {
   91           Meta meta = getMeta(pcClass);
   92           return meta.fieldTypes;
   93       }
   94   
   95       /**
   96        * Return the persistent superclass for a <code>PersistenceCapable</code>
   97        * class, or null if none. The superclass may or may not implement
   98        * {@link PersistenceCapable}, depending on the access type of the class.
   99        */
  100       public static Class getPersistentSuperclass(Class pcClass) {
  101           Meta meta = getMeta(pcClass);
  102           return meta.pcSuper;
  103       }
  104   
  105       /**
  106        * Create a new instance of the class and assign its state manager.
  107        * The new instance has its flags set to <code>LOAD_REQUIRED</code>.
  108        */
  109       public static PersistenceCapable newInstance(Class pcClass,
  110           StateManager sm, boolean clear) {
  111           Meta meta = getMeta(pcClass);
  112           return (meta.pc == null) ? null : meta.pc.pcNewInstance(sm, clear);
  113       }
  114   
  115       /**
  116        * Create a new instance of the class and assign its state manager and oid.
  117        * The new instance has its flags set to <code>LOAD_REQUIRED</code>.
  118        */
  119       public static PersistenceCapable newInstance(Class pcClass,
  120           StateManager sm, Object oid, boolean clear) {
  121           Meta meta = getMeta(pcClass);
  122           return (meta.pc == null) ? null : meta.pc.pcNewInstance(sm, oid, clear);
  123       }
  124   
  125       /**
  126        * Return the persistence-capable type for <code>type</code>. This might
  127        * be a generated subclass of <code>type</code>.
  128        *
  129        * @since 1.1.0
  130        */
  131       public static Class getPCType(Class type) {
  132           Meta meta = getMeta(type);
  133           return (meta.pc == null) ? null : meta.pc.getClass();
  134       }
  135   
  136       /**
  137        * Create a new identity object for the given
  138        * <code>PersistenceCapable</code> class.
  139        */
  140       public static Object newObjectId(Class pcClass) {
  141           Meta meta = getMeta(pcClass);
  142           return (meta.pc == null) ? null : meta.pc.pcNewObjectIdInstance();
  143       }
  144   
  145       /**
  146        * Create a new identity object for the given
  147        * <code>PersistenceCapable</code> class, using the <code>String</code>
  148        * form of the constructor.
  149        */
  150       public static Object newObjectId(Class pcClass, String str) {
  151           Meta meta = getMeta(pcClass);
  152           return (meta.pc == null) ? null : meta.pc.pcNewObjectIdInstance(str);
  153       }
  154   
  155       /**
  156        * Return the alias for the given type.
  157        */
  158       public static String getTypeAlias(Class pcClass) {
  159           return getMeta(pcClass).alias;
  160       }
  161   
  162       /**
  163        * Copy fields from an outside source to the key fields in the identity
  164        * object.
  165        */
  166       public static void copyKeyFieldsToObjectId(Class pcClass, FieldSupplier fm,
  167           Object oid) {
  168           Meta meta = getMeta(pcClass);
  169           if (meta.pc == null)
  170               throw new UserException(_loc.get("copy-no-id", pcClass));
  171   
  172           meta.pc.pcCopyKeyFieldsToObjectId(fm, oid);
  173       }
  174   
  175       /**
  176        * Copy fields to an outside source from the key fields in the identity
  177        * object.
  178        */
  179       public static void copyKeyFieldsFromObjectId(Class pcClass,
  180           FieldConsumer fm, Object oid) {
  181           Meta meta = getMeta(pcClass);
  182           if (meta.pc == null)
  183               throw new UserException(_loc.get("copy-no-id", pcClass));
  184   
  185           meta.pc.pcCopyKeyFieldsFromObjectId(fm, oid);
  186       }
  187   
  188       /**
  189        * Register metadata by class.
  190        *
  191        * @param fieldTypes managed field types
  192        * @param fieldFlags managed field flags
  193        * @param sup the most immediate persistent superclass
  194        * @param pcClass the <code>PersistenceCapable</code> class
  195        * @param fieldNames managed field names
  196        * @param alias the class alias
  197        * @param pc an instance of the class, if not abstract
  198        */
  199       public static void register(Class pcClass, String[] fieldNames,
  200           Class[] fieldTypes, byte[] fieldFlags, Class sup, String alias,
  201           PersistenceCapable pc) {
  202           if (pcClass == null)
  203               throw new NullPointerException();
  204   
  205           // we have to be positive that every listener gets notified for
  206           // every class, so lots of locking
  207           Meta meta = new Meta(pc, fieldNames, fieldTypes, sup, alias);
  208           synchronized (_metas) {
  209               _metas.put(pcClass, meta);
  210           }
  211           synchronized (_listeners) {
  212               for (Iterator i = _listeners.iterator(); i.hasNext();)
  213                   ((RegisterClassListener) i.next()).register(pcClass);
  214           }
  215       }
  216   
  217       /**
  218        * De-Register all metadata associated with the given ClassLoader. 
  219        * Allows ClassLoaders to be garbage collected.
  220        *
  221        * @param cl the ClassLoader
  222        */
  223       public static void deRegister(ClassLoader cl) {
  224           synchronized (_metas) {
  225               for (Iterator i = _metas.keySet().iterator(); i.hasNext();) {
  226                   Class pcClass = (Class) i.next();
  227                   if (pcClass.getClassLoader() == cl) {
  228                       _metas.remove(pcClass);
  229                   }
  230               }
  231           }
  232       }
  233       
  234       /**
  235        * Returns a collection of class objects of the registered
  236        * persistence-capable classes.
  237        */
  238       public static Collection getRegisteredTypes() {
  239           return Collections.unmodifiableCollection(_metas.keySet());
  240       }
  241   
  242       /**
  243        * Returns <code>true</code> if <code>cls</code> is already registered.
  244        */
  245       public static boolean isRegistered(Class cls) {
  246           return _metas.containsKey(cls);
  247       }
  248   
  249       /**
  250        * Look up the metadata for a <code>PersistenceCapable</code> class.
  251        */
  252       private static Meta getMeta(Class pcClass) {
  253           Meta ret = (Meta) _metas.get(pcClass);
  254           if (ret == null)
  255               throw new IllegalStateException(_loc.get("no-meta", pcClass).
  256                   getMessage());
  257           return ret;
  258       }
  259   
  260       /**
  261        * Listener for persistent class registration events.
  262        */
  263       public static interface RegisterClassListener {
  264   
  265           public void register(Class cls);
  266       }
  267   
  268       /**
  269        * This is a helper class to manage metadata per persistence-capable class.
  270        */
  271       private static class Meta {
  272   
  273           public final PersistenceCapable pc;
  274           public final String[] fieldNames;
  275           public final Class[] fieldTypes;
  276           public final Class pcSuper;
  277           public final String alias;
  278   
  279           public Meta(PersistenceCapable pc, String[] fieldNames,
  280               Class[] fieldTypes, Class pcSuper, String alias) {
  281               this.pc = pc;
  282               this.fieldNames = fieldNames;
  283               this.fieldTypes = fieldTypes;
  284               this.pcSuper = pcSuper;
  285   			this.alias = alias;
  286   		}
  287   	}
  288   }

Save This Page
Home » apache-openjpa-1.1.0-source » org.apache.openjpa » enhance » [javadoc | source]