Home » apache-openjpa-1.1.0-source » org.apache.openjpa » util » [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.util;
   20   
   21   import java.util.ArrayList;
   22   import java.util.BitSet;
   23   import java.util.Collection;
   24   import java.util.Collections;
   25   import java.util.Iterator;
   26   import java.util.Map;
   27   
   28   import org.apache.openjpa.enhance.PersistenceCapable;
   29   import org.apache.openjpa.enhance.PCRegistry;
   30   import org.apache.openjpa.enhance.StateManager;
   31   import org.apache.openjpa.enhance.ManagedInstanceProvider;
   32   import org.apache.openjpa.enhance.ReflectingPersistenceCapable;
   33   import org.apache.openjpa.enhance.RuntimeUnenhancedClasssesModes;
   34   import org.apache.openjpa.kernel.FetchConfiguration;
   35   import org.apache.openjpa.kernel.LockManager;
   36   import org.apache.openjpa.kernel.OpenJPAStateManager;
   37   import org.apache.openjpa.kernel.PCState;
   38   import org.apache.openjpa.kernel.StoreContext;
   39   import org.apache.openjpa.kernel.StoreManager;
   40   import org.apache.openjpa.lib.util.Closeable;
   41   import org.apache.openjpa.lib.util.ReferenceMap;
   42   import org.apache.openjpa.lib.util.UUIDGenerator;
   43   import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
   44   import org.apache.openjpa.meta.ClassMetaData;
   45   import org.apache.openjpa.meta.FieldMetaData;
   46   import org.apache.openjpa.meta.JavaTypes;
   47   import org.apache.openjpa.meta.SequenceMetaData;
   48   import org.apache.openjpa.meta.ValueStrategies;
   49   import org.apache.openjpa.conf.OpenJPAConfiguration;
   50   
   51   /**
   52    * Helper for OpenJPA back-ends.
   53    *
   54    * @since 0.3.0
   55    * @author Abe White
   56    * @nojavadoc
   57    */
   58   public class ImplHelper {
   59   
   60       // Cache for from/to type assignments
   61       private static final Map _assignableTypes =
   62           new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD);
   63   
   64       // map of all new unenhanced instances active in this classloader
   65       public static final Map _unenhancedInstanceMap =
   66           new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD) {
   67   
   68               protected boolean eq(Object x, Object y) {
   69                   // the Entries in ConcurrentReferenceHashMap delegate back to
   70                   // eq() in their equals() impls
   71                   if (x instanceof Map.Entry)
   72                       return super.eq(x, y);
   73                   else
   74                       return x == y;
   75               }
   76   
   77               protected int hc(Object o) {
   78                   // the Entries in ConcurrentReferenceHashMap delegate back to
   79                   // hc() in their hashCode() impls
   80                   if (o instanceof Map.Entry)
   81                       return super.hc(o);
   82                   else
   83                       return System.identityHashCode(o);
   84               }
   85           };
   86   
   87       /**
   88        * Helper for store manager implementations. This method simply delegates
   89        * to the proper singular method for each state manager.
   90        *
   91        * @see StoreManager#loadAll
   92        * @since 0.4.0
   93        */
   94       public static Collection loadAll(Collection sms, StoreManager store,
   95           PCState state, int load, FetchConfiguration fetch, Object context) {
   96           Collection failed = null;
   97           OpenJPAStateManager sm;
   98           LockManager lm;
   99           for (Iterator itr = sms.iterator(); itr.hasNext();) {
  100               sm = (OpenJPAStateManager) itr.next();
  101               if (sm.getManagedInstance() == null) {
  102                   if (!store.initialize(sm, state, fetch, context))
  103                       failed = addFailedId(sm, failed);
  104               } else if (load != StoreManager.FORCE_LOAD_NONE
  105                   || sm.getPCState() == PCState.HOLLOW) {
  106                   lm = sm.getContext().getLockManager();
  107                   if (!store.load(sm, sm.getUnloaded(fetch), fetch, 
  108                       lm.getLockLevel(sm), context))
  109                       failed = addFailedId(sm, failed);
  110               } else if (!store.exists(sm, context))
  111                   failed = addFailedId(sm, failed);
  112           }
  113           return (failed == null) ? Collections.EMPTY_LIST : failed;
  114       }
  115   
  116       /**
  117        * Add identity of given instance to collection.
  118        */
  119       private static Collection addFailedId(OpenJPAStateManager sm,
  120           Collection failed) {
  121           if (failed == null)
  122               failed = new ArrayList();
  123           failed.add(sm.getId());
  124           return failed;
  125       }
  126   
  127       /**
  128        * Generate a value for the given metadata, or return null. Generates
  129        * values for hte following strategies: {@link ValueStrategies#SEQUENCE},
  130        * {@link ValueStrategies#UUID_STRING}, {@link ValueStrategies#UUID_HEX}
  131        */
  132       public static Object generateIdentityValue(StoreContext ctx,
  133           ClassMetaData meta, int typeCode) {
  134           return generateValue(ctx, meta, null, typeCode);
  135       }
  136   
  137       /**
  138        * Generate a value for the given metadata, or return null. Generates
  139        * values for hte following strategies: {@link ValueStrategies#SEQUENCE},
  140        * {@link ValueStrategies#UUID_STRING}, {@link ValueStrategies#UUID_HEX}
  141        */
  142       public static Object generateFieldValue(StoreContext ctx,
  143           FieldMetaData fmd) {
  144           return generateValue(ctx, fmd.getDefiningMetaData(), fmd, 
  145               fmd.getDeclaredTypeCode());
  146       }
  147   
  148       /**
  149        * Generate a value for the given metadaa.
  150        */
  151       private static Object generateValue(StoreContext ctx,
  152           ClassMetaData meta, FieldMetaData fmd, int typeCode) {
  153           int strategy = (fmd == null) ? meta.getIdentityStrategy()
  154               : fmd.getValueStrategy();
  155           switch (strategy) {
  156               case ValueStrategies.SEQUENCE:
  157                   SequenceMetaData smd = (fmd == null)
  158                       ? meta.getIdentitySequenceMetaData()
  159                       : fmd.getValueSequenceMetaData();
  160                   return JavaTypes.convert(smd.getInstance(ctx.getClassLoader()).
  161                       next(ctx, meta), typeCode);
  162               case ValueStrategies.UUID_STRING:
  163                   return UUIDGenerator.nextString();
  164               case ValueStrategies.UUID_HEX:
  165                   return UUIDGenerator.nextHex();
  166               default:
  167                   return null;
  168           }
  169       }
  170   
  171       /**
  172        * Returns the fields of the state that require an update.
  173        *
  174        * @param  sm  the state to check
  175        * @return the BitSet of fields that need update, or null if none
  176        */
  177       public static BitSet getUpdateFields(OpenJPAStateManager sm) {
  178           if ((sm.getPCState() == PCState.PDIRTY
  179               && (!sm.isFlushed() || sm.isFlushedDirty()))
  180               || (sm.getPCState() == PCState.PNEW && sm.isFlushedDirty())) {
  181               BitSet dirty = sm.getDirty();
  182               if (sm.isFlushed()) {
  183                   dirty = (BitSet) dirty.clone();
  184                   dirty.andNot(sm.getFlushed());
  185               }
  186               if (dirty.length() > 0)
  187                   return dirty;
  188           }
  189           return null;
  190       }
  191   
  192       /**
  193        * Close the given resource. The resource can be an extent iterator,
  194        * query result, large result set relation, or any closeable OpenJPA
  195        * component.
  196        */
  197       public static void close(Object o) {
  198           try {
  199               if (o instanceof Closeable)
  200                   ((Closeable) o).close();
  201           } catch (RuntimeException re) {
  202               throw re;
  203           } catch (Exception e) {
  204               throw new GeneralException(e);
  205           }
  206       }
  207   
  208       /**
  209        * Returns true if the specified class is a type that can be managed by
  210        * OpenJPA.
  211        *
  212        * @param type the class to test
  213        * @return true if the class is manageable.
  214        *
  215        * @since 1.0.0
  216        */
  217       public static boolean isManagedType(OpenJPAConfiguration conf, Class type) {
  218           return (PersistenceCapable.class.isAssignableFrom(type)
  219               || (type != null
  220                   && (conf == null || conf.getRuntimeUnenhancedClassesConstant()
  221                       == RuntimeUnenhancedClasssesModes.SUPPORTED)
  222                   && PCRegistry.isRegistered(type)));
  223       }
  224   
  225       /**
  226        * Returns true if the specified instance is manageable.
  227        *
  228        * @param instance the object to check
  229        * @return true if the instance is a persistent type, false otherwise
  230        */
  231       public static boolean isManageable(Object instance) {
  232           return instance instanceof PersistenceCapable
  233               || instance != null && PCRegistry.isRegistered(instance.getClass());
  234       }
  235   
  236       /**
  237        * Returns true if the referenced "to" class is assignable to the "from"
  238        * class.  This helper method utilizes a cache to help avoid the overhead
  239        * of the Class.isAssignableFrom() method.
  240        *
  241        * @param from target class instance to be checked for assignability
  242        * @param to second class instance to be checked for assignability
  243        * @return true if the "to" class is assignable to the "from" class
  244        */
  245       public static boolean isAssignable(Class from, Class to) {
  246           if (from == null || to == null)
  247               return false;
  248   
  249           Boolean isAssignable = null;
  250           Map assignableTo = (Map) _assignableTypes.get(from);
  251           if (assignableTo == null) { // "to" cache doesn't exist, so create it...
  252               assignableTo = new ConcurrentReferenceHashMap(ReferenceMap.WEAK,
  253                       ReferenceMap.HARD);
  254               _assignableTypes.put(from, assignableTo);
  255           } else { // "to" cache exists...
  256               isAssignable = (Boolean) assignableTo.get(to);
  257           }
  258   
  259           if (isAssignable == null) {// we don't have a record of this pair...
  260               isAssignable = Boolean.valueOf(from.isAssignableFrom(to));
  261               assignableTo.put(to, isAssignable);
  262           }
  263   
  264           return isAssignable.booleanValue();
  265       }
  266   
  267       /**
  268        * @return the persistence-capable instance responsible for managing
  269        * <code>o</code>, or <code>null</code> if <code>o</code> is not manageable.
  270        * @since 1.0.0
  271        */
  272       public static PersistenceCapable toPersistenceCapable(Object o, Object ctx){
  273           if (o instanceof PersistenceCapable)
  274               return (PersistenceCapable) o;
  275   
  276           OpenJPAConfiguration conf = null;
  277           if (ctx instanceof OpenJPAConfiguration)
  278               conf = (OpenJPAConfiguration) ctx;
  279           else if (ctx instanceof StateManager
  280               && ((StateManager) ctx).getGenericContext() instanceof StoreContext)
  281               conf = ((StoreContext) ((StateManager) ctx).getGenericContext())
  282                   .getConfiguration();
  283   
  284           if (!isManageable(o))
  285               return null;
  286   
  287           // if we had a putIfAbsent() method, we wouldn't need to sync here
  288           synchronized (o) {
  289               PersistenceCapable pc = (PersistenceCapable)
  290                   _unenhancedInstanceMap.get(o);
  291   
  292               if (pc != null)
  293                   return pc;
  294   
  295               // if we don't have a conf passed in, then we can't create a new
  296               // ReflectingPC; this will only be the case when invoked from a
  297               // context outside of OpenJPA.
  298               if (conf == null)
  299                   return null;
  300   
  301               pc = new ReflectingPersistenceCapable(o, conf);
  302               _unenhancedInstanceMap.put(o, pc);
  303               return pc;
  304           }
  305       }
  306   
  307       public static void registerPersistenceCapable(
  308           ReflectingPersistenceCapable pc) {
  309           _unenhancedInstanceMap.put(pc.getManagedInstance(), pc);
  310       }
  311   
  312       /**
  313        * @return the user-visible representation of <code>o</code>.
  314        * @since 1.0.0
  315        */
  316       public static Object getManagedInstance(Object o) {
  317           if (o instanceof ManagedInstanceProvider)
  318               return ((ManagedInstanceProvider) o).getManagedInstance();
  319           else
  320               return o;
  321       }
  322   }

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