0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one
0003: * or more contributor license agreements. See the NOTICE file
0004: * distributed with this work for additional information
0005: * regarding copyright ownership. The ASF licenses this file
0006: * to you under the Apache License, Version 2.0 (the
0007: * "License"); you may not use this file except in compliance
0008: * with the License. You may obtain a copy of the License at
0009: *
0010: * http://www.apache.org/licenses/LICENSE-2.0
0011: *
0012: * Unless required by applicable law or agreed to in writing,
0013: * software distributed under the License is distributed on an
0014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0015: * KIND, either express or implied. See the License for the
0016: * specific language governing permissions and limitations
0017: * under the License.
0018: */
0019: package org.apache.openjpa.persistence;
0020:
0021: import java.io.ByteArrayInputStream;
0022: import java.io.ByteArrayOutputStream;
0023: import java.io.Externalizable;
0024: import java.io.IOException;
0025: import java.io.ObjectInput;
0026: import java.io.ObjectInputStream;
0027: import java.io.ObjectOutput;
0028: import java.io.ObjectOutputStream;
0029: import java.io.ObjectStreamClass;
0030: import java.lang.reflect.Array;
0031: import java.util.Arrays;
0032: import java.util.Collection;
0033: import java.util.EnumSet;
0034: import javax.persistence.EntityManager;
0035: import javax.persistence.FlushModeType;
0036: import javax.persistence.LockModeType;
0037: import javax.persistence.Query;
0038:
0039: import org.apache.commons.lang.StringUtils;
0040: import org.apache.openjpa.conf.OpenJPAConfiguration;
0041: import org.apache.openjpa.ee.ManagedRuntime;
0042: import org.apache.openjpa.enhance.PCEnhancer;
0043: import org.apache.openjpa.enhance.PCRegistry;
0044: import org.apache.openjpa.kernel.AbstractBrokerFactory;
0045: import org.apache.openjpa.kernel.Broker;
0046: import org.apache.openjpa.kernel.DelegatingBroker;
0047: import org.apache.openjpa.kernel.FindCallbacks;
0048: import org.apache.openjpa.kernel.LockLevels;
0049: import org.apache.openjpa.kernel.OpCallbacks;
0050: import org.apache.openjpa.kernel.OpenJPAStateManager;
0051: import org.apache.openjpa.kernel.QueryFlushModes;
0052: import org.apache.openjpa.kernel.QueryLanguages;
0053: import org.apache.openjpa.kernel.Seq;
0054: import org.apache.openjpa.kernel.jpql.JPQLParser;
0055: import org.apache.openjpa.lib.util.Closeable;
0056: import org.apache.openjpa.lib.util.Localizer;
0057: import org.apache.openjpa.meta.ClassMetaData;
0058: import org.apache.openjpa.meta.FieldMetaData;
0059: import org.apache.openjpa.meta.QueryMetaData;
0060: import org.apache.openjpa.meta.SequenceMetaData;
0061: import org.apache.openjpa.util.Exceptions;
0062: import org.apache.openjpa.util.ImplHelper;
0063: import org.apache.openjpa.util.RuntimeExceptionTranslator;
0064: import org.apache.openjpa.util.UserException;
0065:
0066: /**
0067: * Implementation of {@link EntityManager} interface.
0068: *
0069: * @author Patrick Linskey
0070: * @author Abe White
0071: * @nojavadoc
0072: */
0073: public class EntityManagerImpl implements OpenJPAEntityManagerSPI,
0074: Externalizable, FindCallbacks, OpCallbacks, Closeable,
0075: OpenJPAEntityTransaction {
0076:
0077: private static final Localizer _loc = Localizer
0078: .forPackage(EntityManagerImpl.class);
0079: private static final Object[] EMPTY_OBJECTS = new Object[0];
0080:
0081: private DelegatingBroker _broker;
0082: private EntityManagerFactoryImpl _emf;
0083: private FetchPlan _fetch = null;
0084:
0085: private RuntimeExceptionTranslator ret = PersistenceExceptions
0086: .getRollbackTranslator(this );
0087:
0088: public EntityManagerImpl() {
0089: // for Externalizable
0090: }
0091:
0092: /**
0093: * Constructor; supply factory and delegate.
0094: */
0095: public EntityManagerImpl(EntityManagerFactoryImpl factory,
0096: Broker broker) {
0097: initialize(factory, broker);
0098: }
0099:
0100: private void initialize(EntityManagerFactoryImpl factory,
0101: Broker broker) {
0102: _emf = factory;
0103: _broker = new DelegatingBroker(broker, ret);
0104: _broker.setImplicitBehavior(this , ret);
0105: }
0106:
0107: /**
0108: * Broker delegate.
0109: */
0110: public Broker getBroker() {
0111: return _broker.getDelegate();
0112: }
0113:
0114: public OpenJPAEntityManagerFactory getEntityManagerFactory() {
0115: return _emf;
0116: }
0117:
0118: public OpenJPAConfiguration getConfiguration() {
0119: return _broker.getConfiguration();
0120: }
0121:
0122: public FetchPlan getFetchPlan() {
0123: assertNotCloseInvoked();
0124: _broker.lock();
0125: try {
0126: if (_fetch == null)
0127: _fetch = _emf.toFetchPlan(_broker, _broker
0128: .getFetchConfiguration());
0129: return _fetch;
0130: } finally {
0131: _broker.unlock();
0132: }
0133: }
0134:
0135: public ConnectionRetainMode getConnectionRetainMode() {
0136: return ConnectionRetainMode.fromKernelConstant(_broker
0137: .getConnectionRetainMode());
0138: }
0139:
0140: public boolean isTransactionManaged() {
0141: return _broker.isManaged();
0142: }
0143:
0144: public boolean isManaged() {
0145: return _broker.isManaged();
0146: }
0147:
0148: public ManagedRuntime getManagedRuntime() {
0149: return _broker.getManagedRuntime();
0150: }
0151:
0152: public boolean getSyncWithManagedTransactions() {
0153: return _broker.getSyncWithManagedTransactions();
0154: }
0155:
0156: public void setSyncWithManagedTransactions(boolean sync) {
0157: assertNotCloseInvoked();
0158: _broker.setSyncWithManagedTransactions(sync);
0159: }
0160:
0161: public ClassLoader getClassLoader() {
0162: return _broker.getClassLoader();
0163: }
0164:
0165: public String getConnectionUserName() {
0166: return _broker.getConnectionUserName();
0167: }
0168:
0169: public String getConnectionPassword() {
0170: return _broker.getConnectionPassword();
0171: }
0172:
0173: public boolean getMultithreaded() {
0174: return _broker.getMultithreaded();
0175: }
0176:
0177: public void setMultithreaded(boolean multithreaded) {
0178: assertNotCloseInvoked();
0179: _broker.setMultithreaded(multithreaded);
0180: }
0181:
0182: public boolean getIgnoreChanges() {
0183: return _broker.getIgnoreChanges();
0184: }
0185:
0186: public void setIgnoreChanges(boolean val) {
0187: assertNotCloseInvoked();
0188: _broker.setIgnoreChanges(val);
0189: }
0190:
0191: public boolean getNontransactionalRead() {
0192: return _broker.getNontransactionalRead();
0193: }
0194:
0195: public void setNontransactionalRead(boolean val) {
0196: assertNotCloseInvoked();
0197: _broker.setNontransactionalRead(val);
0198: }
0199:
0200: public boolean getNontransactionalWrite() {
0201: return _broker.getNontransactionalWrite();
0202: }
0203:
0204: public void setNontransactionalWrite(boolean val) {
0205: assertNotCloseInvoked();
0206: _broker.setNontransactionalWrite(val);
0207: }
0208:
0209: public boolean getOptimistic() {
0210: return _broker.getOptimistic();
0211: }
0212:
0213: public void setOptimistic(boolean val) {
0214: assertNotCloseInvoked();
0215: _broker.setOptimistic(val);
0216: }
0217:
0218: public RestoreStateType getRestoreState() {
0219: return RestoreStateType.fromKernelConstant(_broker
0220: .getRestoreState());
0221: }
0222:
0223: public void setRestoreState(RestoreStateType val) {
0224: assertNotCloseInvoked();
0225: _broker.setRestoreState(val.toKernelConstant());
0226: }
0227:
0228: public void setRestoreState(int restore) {
0229: assertNotCloseInvoked();
0230: _broker.setRestoreState(restore);
0231: }
0232:
0233: public boolean getRetainState() {
0234: return _broker.getRetainState();
0235: }
0236:
0237: public void setRetainState(boolean val) {
0238: assertNotCloseInvoked();
0239: _broker.setRetainState(val);
0240: }
0241:
0242: public AutoClearType getAutoClear() {
0243: return AutoClearType.fromKernelConstant(_broker.getAutoClear());
0244: }
0245:
0246: public void setAutoClear(AutoClearType val) {
0247: assertNotCloseInvoked();
0248: _broker.setAutoClear(val.toKernelConstant());
0249: }
0250:
0251: public void setAutoClear(int autoClear) {
0252: assertNotCloseInvoked();
0253: _broker.setAutoClear(autoClear);
0254: }
0255:
0256: public DetachStateType getDetachState() {
0257: return DetachStateType.fromKernelConstant(_broker
0258: .getDetachState());
0259: }
0260:
0261: public void setDetachState(DetachStateType type) {
0262: assertNotCloseInvoked();
0263: _broker.setDetachState(type.toKernelConstant());
0264: }
0265:
0266: public void setDetachState(int detach) {
0267: assertNotCloseInvoked();
0268: _broker.setDetachState(detach);
0269: }
0270:
0271: public EnumSet<AutoDetachType> getAutoDetach() {
0272: return AutoDetachType.toEnumSet(_broker.getAutoDetach());
0273: }
0274:
0275: public void setAutoDetach(AutoDetachType flag) {
0276: assertNotCloseInvoked();
0277: _broker.setAutoDetach(AutoDetachType.fromEnumSet(EnumSet
0278: .of(flag)));
0279: }
0280:
0281: public void setAutoDetach(EnumSet<AutoDetachType> flags) {
0282: assertNotCloseInvoked();
0283: _broker.setAutoDetach(AutoDetachType.fromEnumSet(flags));
0284: }
0285:
0286: public void setAutoDetach(int autoDetachFlags) {
0287: assertNotCloseInvoked();
0288: _broker.setAutoDetach(autoDetachFlags);
0289: }
0290:
0291: public void setAutoDetach(AutoDetachType value, boolean on) {
0292: assertNotCloseInvoked();
0293: _broker.setAutoDetach(AutoDetachType.fromEnumSet(EnumSet
0294: .of(value)), on);
0295: }
0296:
0297: public void setAutoDetach(int flag, boolean on) {
0298: assertNotCloseInvoked();
0299: _broker.setAutoDetach(flag, on);
0300: }
0301:
0302: public boolean getEvictFromStoreCache() {
0303: return _broker.getEvictFromDataCache();
0304: }
0305:
0306: public void setEvictFromStoreCache(boolean evict) {
0307: assertNotCloseInvoked();
0308: _broker.setEvictFromDataCache(evict);
0309: }
0310:
0311: public boolean getPopulateStoreCache() {
0312: return _broker.getPopulateDataCache();
0313: }
0314:
0315: public void setPopulateStoreCache(boolean cache) {
0316: assertNotCloseInvoked();
0317: _broker.setPopulateDataCache(cache);
0318: }
0319:
0320: public boolean isTrackChangesByType() {
0321: return _broker.isTrackChangesByType();
0322: }
0323:
0324: public void setTrackChangesByType(boolean trackByType) {
0325: assertNotCloseInvoked();
0326: _broker.setTrackChangesByType(trackByType);
0327: }
0328:
0329: public boolean isLargeTransaction() {
0330: return isTrackChangesByType();
0331: }
0332:
0333: public void setLargeTransaction(boolean value) {
0334: setTrackChangesByType(value);
0335: }
0336:
0337: public Object getUserObject(Object key) {
0338: return _broker.getUserObject(key);
0339: }
0340:
0341: public Object putUserObject(Object key, Object val) {
0342: assertNotCloseInvoked();
0343: return _broker.putUserObject(key, val);
0344: }
0345:
0346: public void addTransactionListener(Object listener) {
0347: assertNotCloseInvoked();
0348: _broker.addTransactionListener(listener);
0349: }
0350:
0351: public void removeTransactionListener(Object listener) {
0352: assertNotCloseInvoked();
0353: _broker.removeTransactionListener(listener);
0354: }
0355:
0356: public EnumSet<CallbackMode> getTransactionListenerCallbackModes() {
0357: return CallbackMode.toEnumSet(_broker
0358: .getTransactionListenerCallbackMode());
0359: }
0360:
0361: public void setTransactionListenerCallbackMode(CallbackMode mode) {
0362: assertNotCloseInvoked();
0363: _broker.setTransactionListenerCallbackMode(CallbackMode
0364: .fromEnumSet(EnumSet.of(mode)));
0365: }
0366:
0367: public void setTransactionListenerCallbackMode(
0368: EnumSet<CallbackMode> modes) {
0369: assertNotCloseInvoked();
0370: _broker.setTransactionListenerCallbackMode(CallbackMode
0371: .fromEnumSet(modes));
0372: }
0373:
0374: public int getTransactionListenerCallbackMode() {
0375: return _broker.getTransactionListenerCallbackMode();
0376: }
0377:
0378: public void setTransactionListenerCallbackMode(int callbackMode) {
0379: throw new UnsupportedOperationException();
0380: }
0381:
0382: public void addLifecycleListener(Object listener, Class... classes) {
0383: assertNotCloseInvoked();
0384: _broker.addLifecycleListener(listener, classes);
0385: }
0386:
0387: public void removeLifecycleListener(Object listener) {
0388: assertNotCloseInvoked();
0389: _broker.removeLifecycleListener(listener);
0390: }
0391:
0392: public EnumSet<CallbackMode> getLifecycleListenerCallbackModes() {
0393: return CallbackMode.toEnumSet(_broker
0394: .getLifecycleListenerCallbackMode());
0395: }
0396:
0397: public void setLifecycleListenerCallbackMode(CallbackMode mode) {
0398: assertNotCloseInvoked();
0399: _broker.setLifecycleListenerCallbackMode(CallbackMode
0400: .fromEnumSet(EnumSet.of(mode)));
0401: }
0402:
0403: public void setLifecycleListenerCallbackMode(
0404: EnumSet<CallbackMode> modes) {
0405: assertNotCloseInvoked();
0406: _broker.setLifecycleListenerCallbackMode(CallbackMode
0407: .fromEnumSet(modes));
0408: }
0409:
0410: public int getLifecycleListenerCallbackMode() {
0411: return _broker.getLifecycleListenerCallbackMode();
0412: }
0413:
0414: public void setLifecycleListenerCallbackMode(int callbackMode) {
0415: assertNotCloseInvoked();
0416: _broker.setLifecycleListenerCallbackMode(callbackMode);
0417: }
0418:
0419: @SuppressWarnings("unchecked")
0420: public <T> T getReference(Class<T> cls, Object oid) {
0421: assertNotCloseInvoked();
0422: oid = _broker.newObjectId(cls, oid);
0423: return (T) _broker.find(oid, false, this );
0424: }
0425:
0426: @SuppressWarnings("unchecked")
0427: public <T> T find(Class<T> cls, Object oid) {
0428: assertNotCloseInvoked();
0429: oid = _broker.newObjectId(cls, oid);
0430: return (T) _broker.find(oid, true, this );
0431: }
0432:
0433: @SuppressWarnings("unchecked")
0434: public <T> T[] findAll(Class<T> cls, Object... oids) {
0435: if (oids.length == 0)
0436: return (T[]) Array.newInstance(cls, 0);
0437: Collection<T> ret = findAll(cls, Arrays.asList(oids));
0438: return ret.toArray((T[]) Array.newInstance(cls, ret.size()));
0439: }
0440:
0441: @SuppressWarnings("unchecked")
0442: public <T> Collection<T> findAll(final Class<T> cls, Collection oids) {
0443: assertNotCloseInvoked();
0444: Object[] objs = _broker.findAll(oids, true,
0445: new FindCallbacks() {
0446: public Object processArgument(Object oid) {
0447: return _broker.newObjectId(cls, oid);
0448: }
0449:
0450: public Object processReturn(Object oid,
0451: OpenJPAStateManager sm) {
0452: return EntityManagerImpl.this .processReturn(
0453: oid, sm);
0454: }
0455: });
0456: return (Collection<T>) Arrays.asList(objs);
0457: }
0458:
0459: @SuppressWarnings("unchecked")
0460: public <T> T findCached(Class<T> cls, Object oid) {
0461: assertNotCloseInvoked();
0462: return (T) _broker.findCached(_broker.newObjectId(cls, oid),
0463: this );
0464: }
0465:
0466: public Class getObjectIdClass(Class cls) {
0467: assertNotCloseInvoked();
0468: if (cls == null)
0469: return null;
0470: return JPAFacadeHelper.fromOpenJPAObjectIdClass(_broker
0471: .getObjectIdType(cls));
0472: }
0473:
0474: public OpenJPAEntityTransaction getTransaction() {
0475: if (_broker.isManaged())
0476: throw new InvalidStateException(_loc
0477: .get("get-managed-trans"), null, null, false);
0478: return this ;
0479: }
0480:
0481: public void joinTransaction() {
0482: assertNotCloseInvoked();
0483: if (!_broker.syncWithManagedTransaction())
0484: throw new TransactionRequiredException(_loc
0485: .get("no-managed-trans"), null, null, false);
0486: }
0487:
0488: public void begin() {
0489: _broker.begin();
0490: }
0491:
0492: public void commit() {
0493: try {
0494: _broker.commit();
0495: } catch (RollbackException e) {
0496: throw e;
0497: } catch (IllegalStateException e) {
0498: throw e;
0499: } catch (Exception e) {
0500: // RollbackExceptions are special and aren't handled by the
0501: // normal exception translator, since the spec says they
0502: // should be thrown whenever the commit fails for any reason at
0503: // all, wheras the exception translator handles exceptions that
0504: // are caused for specific reasons
0505: throw new RollbackException(e);
0506: }
0507: }
0508:
0509: public void rollback() {
0510: _broker.rollback();
0511: }
0512:
0513: public void commitAndResume() {
0514: _broker.commitAndResume();
0515: }
0516:
0517: public void rollbackAndResume() {
0518: _broker.rollbackAndResume();
0519: }
0520:
0521: public Throwable getRollbackCause() {
0522: if (!isActive())
0523: throw new IllegalStateException(_loc.get("no-transaction")
0524: .getMessage());
0525:
0526: return _broker.getRollbackCause();
0527: }
0528:
0529: public boolean getRollbackOnly() {
0530: if (!isActive())
0531: throw new IllegalStateException(_loc.get("no-transaction")
0532: .getMessage());
0533:
0534: return _broker.getRollbackOnly();
0535: }
0536:
0537: public void setRollbackOnly() {
0538: _broker.setRollbackOnly();
0539: }
0540:
0541: public void setRollbackOnly(Throwable cause) {
0542: _broker.setRollbackOnly(cause);
0543: }
0544:
0545: public void setSavepoint(String name) {
0546: assertNotCloseInvoked();
0547: _broker.setSavepoint(name);
0548: }
0549:
0550: public void rollbackToSavepoint() {
0551: assertNotCloseInvoked();
0552: _broker.rollbackToSavepoint();
0553: }
0554:
0555: public void rollbackToSavepoint(String name) {
0556: assertNotCloseInvoked();
0557: _broker.rollbackToSavepoint(name);
0558: }
0559:
0560: public void releaseSavepoint() {
0561: assertNotCloseInvoked();
0562: _broker.releaseSavepoint();
0563: }
0564:
0565: public void releaseSavepoint(String name) {
0566: assertNotCloseInvoked();
0567: _broker.releaseSavepoint(name);
0568: }
0569:
0570: public void flush() {
0571: assertNotCloseInvoked();
0572: _broker.assertOpen();
0573: _broker.assertActiveTransaction();
0574: _broker.flush();
0575: }
0576:
0577: public void preFlush() {
0578: assertNotCloseInvoked();
0579: _broker.preFlush();
0580: }
0581:
0582: public void validateChanges() {
0583: assertNotCloseInvoked();
0584: _broker.validateChanges();
0585: }
0586:
0587: public boolean isActive() {
0588: return isOpen() && _broker.isActive();
0589: }
0590:
0591: public boolean isStoreActive() {
0592: return _broker.isStoreActive();
0593: }
0594:
0595: public void beginStore() {
0596: _broker.beginStore();
0597: }
0598:
0599: public boolean contains(Object entity) {
0600: assertNotCloseInvoked();
0601: if (entity == null)
0602: return false;
0603: OpenJPAStateManager sm = _broker.getStateManager(entity);
0604: if (sm == null
0605: && !ImplHelper.isManagedType(getConfiguration(), entity
0606: .getClass()))
0607: throw new ArgumentException(_loc.get("not-entity", entity
0608: .getClass()), null, null, true);
0609: return sm != null && !sm.isDeleted();
0610: }
0611:
0612: public boolean containsAll(Object... entities) {
0613: for (Object entity : entities)
0614: if (!contains(entity))
0615: return false;
0616: return true;
0617: }
0618:
0619: public boolean containsAll(Collection entities) {
0620: for (Object entity : entities)
0621: if (!contains(entity))
0622: return false;
0623: return true;
0624: }
0625:
0626: public void persist(Object entity) {
0627: assertNotCloseInvoked();
0628: _broker.persist(entity, this );
0629: }
0630:
0631: public void persistAll(Object... entities) {
0632: persistAll(Arrays.asList(entities));
0633: }
0634:
0635: public void persistAll(Collection entities) {
0636: assertNotCloseInvoked();
0637: _broker.persistAll(entities, this );
0638: }
0639:
0640: public void remove(Object entity) {
0641: assertNotCloseInvoked();
0642: _broker.delete(entity, this );
0643: }
0644:
0645: public void removeAll(Object... entities) {
0646: removeAll(Arrays.asList(entities));
0647: }
0648:
0649: public void removeAll(Collection entities) {
0650: assertNotCloseInvoked();
0651: _broker.deleteAll(entities, this );
0652: }
0653:
0654: public void release(Object entity) {
0655: assertNotCloseInvoked();
0656: _broker.release(entity, this );
0657: }
0658:
0659: public void releaseAll(Collection entities) {
0660: assertNotCloseInvoked();
0661: _broker.releaseAll(entities, this );
0662: }
0663:
0664: public void releaseAll(Object... entities) {
0665: releaseAll(Arrays.asList(entities));
0666: }
0667:
0668: public void refresh(Object entity) {
0669: assertNotCloseInvoked();
0670: _broker.assertWriteOperation();
0671: _broker.refresh(entity, this );
0672: }
0673:
0674: public void refreshAll() {
0675: assertNotCloseInvoked();
0676: _broker.assertWriteOperation();
0677: _broker.refreshAll(_broker.getTransactionalObjects(), this );
0678: }
0679:
0680: public void refreshAll(Collection entities) {
0681: assertNotCloseInvoked();
0682: _broker.assertWriteOperation();
0683: _broker.refreshAll(entities, this );
0684: }
0685:
0686: public void refreshAll(Object... entities) {
0687: refreshAll(Arrays.asList(entities));
0688: }
0689:
0690: public void retrieve(Object entity) {
0691: assertNotCloseInvoked();
0692: _broker.retrieve(entity, true, this );
0693: }
0694:
0695: public void retrieveAll(Collection entities) {
0696: assertNotCloseInvoked();
0697: _broker.retrieveAll(entities, true, this );
0698: }
0699:
0700: public void retrieveAll(Object... entities) {
0701: retrieveAll(Arrays.asList(entities));
0702: }
0703:
0704: public void evict(Object entity) {
0705: assertNotCloseInvoked();
0706: _broker.evict(entity, this );
0707: }
0708:
0709: public void evictAll(Collection entities) {
0710: assertNotCloseInvoked();
0711: _broker.evictAll(entities, this );
0712: }
0713:
0714: public void evictAll(Object... entities) {
0715: evictAll(Arrays.asList(entities));
0716: }
0717:
0718: public void evictAll() {
0719: assertNotCloseInvoked();
0720: _broker.evictAll(this );
0721: }
0722:
0723: public void evictAll(Class cls) {
0724: assertNotCloseInvoked();
0725: _broker.evictAll(_broker.newExtent(cls, true), this );
0726: }
0727:
0728: public void evictAll(Extent extent) {
0729: assertNotCloseInvoked();
0730: _broker.evictAll(((ExtentImpl) extent).getDelegate(), this );
0731: }
0732:
0733: @SuppressWarnings("unchecked")
0734: public <T> T detach(T entity) {
0735: assertNotCloseInvoked();
0736: return (T) _broker.detach(entity, this );
0737: }
0738:
0739: public Object[] detachAll(Object... entities) {
0740: assertNotCloseInvoked();
0741: return _broker.detachAll(Arrays.asList(entities), this );
0742: }
0743:
0744: public Collection detachAll(Collection entities) {
0745: assertNotCloseInvoked();
0746: return Arrays.asList(_broker.detachAll(entities, this ));
0747: }
0748:
0749: @SuppressWarnings("unchecked")
0750: public <T> T merge(T entity) {
0751: assertNotCloseInvoked();
0752: return (T) _broker.attach(entity, true, this );
0753: }
0754:
0755: public Object[] mergeAll(Object... entities) {
0756: if (entities.length == 0)
0757: return EMPTY_OBJECTS;
0758: return mergeAll(Arrays.asList(entities)).toArray();
0759: }
0760:
0761: public Collection mergeAll(Collection entities) {
0762: assertNotCloseInvoked();
0763: return Arrays.asList(_broker.attachAll(entities, true, this ));
0764: }
0765:
0766: public void transactional(Object entity, boolean updateVersion) {
0767: assertNotCloseInvoked();
0768: _broker.transactional(entity, updateVersion, this );
0769: }
0770:
0771: public void transactionalAll(Collection objs, boolean updateVersion) {
0772: assertNotCloseInvoked();
0773: _broker.transactionalAll(objs, updateVersion, this );
0774: }
0775:
0776: public void transactionalAll(Object[] objs, boolean updateVersion) {
0777: assertNotCloseInvoked();
0778: _broker.transactionalAll(Arrays.asList(objs), updateVersion,
0779: this );
0780: }
0781:
0782: public void nontransactional(Object entity) {
0783: assertNotCloseInvoked();
0784: _broker.nontransactional(entity, this );
0785: }
0786:
0787: public void nontransactionalAll(Collection objs) {
0788: assertNotCloseInvoked();
0789: _broker.nontransactionalAll(objs, this );
0790: }
0791:
0792: public void nontransactionalAll(Object[] objs) {
0793: assertNotCloseInvoked();
0794: _broker.nontransactionalAll(Arrays.asList(objs), this );
0795: }
0796:
0797: public Generator getNamedGenerator(String name) {
0798: assertNotCloseInvoked();
0799: try {
0800: SequenceMetaData meta = _broker.getConfiguration()
0801: .getMetaDataRepositoryInstance()
0802: .getSequenceMetaData(name,
0803: _broker.getClassLoader(), true);
0804: Seq seq = meta.getInstance(_broker.getClassLoader());
0805: return new GeneratorImpl(seq, name, _broker, null);
0806: } catch (RuntimeException re) {
0807: throw PersistenceExceptions.toPersistenceException(re);
0808: }
0809: }
0810:
0811: public Generator getIdGenerator(Class forClass) {
0812: assertNotCloseInvoked();
0813: try {
0814: ClassMetaData meta = _broker.getConfiguration()
0815: .getMetaDataRepositoryInstance().getMetaData(
0816: forClass, _broker.getClassLoader(), true);
0817: Seq seq = _broker.getIdentitySequence(meta);
0818: return (seq == null) ? null : new GeneratorImpl(seq, null,
0819: _broker, meta);
0820: } catch (Exception e) {
0821: throw PersistenceExceptions.toPersistenceException(e);
0822: }
0823: }
0824:
0825: public Generator getFieldGenerator(Class forClass, String fieldName) {
0826: assertNotCloseInvoked();
0827: try {
0828: ClassMetaData meta = _broker.getConfiguration()
0829: .getMetaDataRepositoryInstance().getMetaData(
0830: forClass, _broker.getClassLoader(), true);
0831: FieldMetaData fmd = meta.getField(fieldName);
0832: if (fmd == null)
0833: throw new ArgumentException(_loc.get("no-named-field",
0834: forClass, fieldName), null, null, false);
0835:
0836: Seq seq = _broker.getValueSequence(fmd);
0837: return (seq == null) ? null : new GeneratorImpl(seq, null,
0838: _broker, meta);
0839: } catch (Exception e) {
0840: throw PersistenceExceptions.toPersistenceException(e);
0841: }
0842: }
0843:
0844: public <T> Extent<T> createExtent(Class<T> cls, boolean subclasses) {
0845: assertNotCloseInvoked();
0846: return new ExtentImpl<T>(this , _broker.newExtent(cls,
0847: subclasses));
0848: }
0849:
0850: public OpenJPAQuery createQuery(String query) {
0851: return createQuery(JPQLParser.LANG_JPQL, query);
0852: }
0853:
0854: public OpenJPAQuery createQuery(String language, String query) {
0855: assertNotCloseInvoked();
0856: return new QueryImpl(this , ret, _broker.newQuery(language,
0857: query));
0858: }
0859:
0860: public OpenJPAQuery createQuery(Query query) {
0861: if (query == null)
0862: return createQuery((String) null);
0863: assertNotCloseInvoked();
0864: org.apache.openjpa.kernel.Query q = ((QueryImpl) query)
0865: .getDelegate();
0866: return new QueryImpl(this , ret, _broker.newQuery(q
0867: .getLanguage(), q));
0868: }
0869:
0870: public OpenJPAQuery createNamedQuery(String name) {
0871: assertNotCloseInvoked();
0872: _broker.assertOpen();
0873: try {
0874: QueryMetaData meta = _broker.getConfiguration()
0875: .getMetaDataRepositoryInstance().getQueryMetaData(
0876: null, name, _broker.getClassLoader(), true);
0877: org.apache.openjpa.kernel.Query del = _broker.newQuery(meta
0878: .getLanguage(), null);
0879: meta.setInto(del);
0880: del.compile();
0881:
0882: OpenJPAQuery q = new QueryImpl(this , ret, del);
0883: String[] hints = meta.getHintKeys();
0884: Object[] values = meta.getHintValues();
0885: for (int i = 0; i < hints.length; i++)
0886: q.setHint(hints[i], values[i]);
0887: return q;
0888: } catch (RuntimeException re) {
0889: throw PersistenceExceptions.toPersistenceException(re);
0890: }
0891: }
0892:
0893: public OpenJPAQuery createNativeQuery(String query) {
0894: validateSQL(query);
0895: return createQuery(QueryLanguages.LANG_SQL, query);
0896: }
0897:
0898: public OpenJPAQuery createNativeQuery(String query, Class cls) {
0899: return createNativeQuery(query).setResultClass(cls);
0900: }
0901:
0902: public OpenJPAQuery createNativeQuery(String query,
0903: String mappingName) {
0904: assertNotCloseInvoked();
0905: validateSQL(query);
0906: org.apache.openjpa.kernel.Query kernelQuery = _broker.newQuery(
0907: QueryLanguages.LANG_SQL, query);
0908: kernelQuery.setResultMapping(null, mappingName);
0909: return new QueryImpl(this , ret, kernelQuery);
0910: }
0911:
0912: /**
0913: * Validate that the user provided SQL.
0914: */
0915: private static void validateSQL(String query) {
0916: if (StringUtils.trimToNull(query) == null)
0917: throw new ArgumentException(_loc.get("no-sql"), null, null,
0918: false);
0919: }
0920:
0921: public void setFlushMode(FlushModeType flushMode) {
0922: assertNotCloseInvoked();
0923: _broker.assertOpen();
0924: _broker.getFetchConfiguration().setFlushBeforeQueries(
0925: toFlushBeforeQueries(flushMode));
0926: }
0927:
0928: public FlushModeType getFlushMode() {
0929: assertNotCloseInvoked();
0930: _broker.assertOpen();
0931: return fromFlushBeforeQueries(_broker.getFetchConfiguration()
0932: .getFlushBeforeQueries());
0933: }
0934:
0935: /**
0936: * Translate our internal flush constant to a flush mode enum value.
0937: */
0938: static FlushModeType fromFlushBeforeQueries(int flush) {
0939: switch (flush) {
0940: case QueryFlushModes.FLUSH_TRUE:
0941: return FlushModeType.AUTO;
0942: case QueryFlushModes.FLUSH_FALSE:
0943: return FlushModeType.COMMIT;
0944: default:
0945: return null;
0946: }
0947: }
0948:
0949: /**
0950: * Translate a flush mode enum value to our internal flush constant.
0951: */
0952: static int toFlushBeforeQueries(FlushModeType flushMode) {
0953: // choose default for null
0954: if (flushMode == null)
0955: return QueryFlushModes.FLUSH_WITH_CONNECTION;
0956: if (flushMode == FlushModeType.AUTO)
0957: return QueryFlushModes.FLUSH_TRUE;
0958: if (flushMode == FlushModeType.COMMIT)
0959: return QueryFlushModes.FLUSH_FALSE;
0960: throw new ArgumentException(flushMode.toString(), null, null,
0961: false);
0962: }
0963:
0964: public void clear() {
0965: assertNotCloseInvoked();
0966: _broker.detachAll(this , false);
0967: }
0968:
0969: public Object getDelegate() {
0970: _broker.assertOpen();
0971: assertNotCloseInvoked();
0972: return this ;
0973: }
0974:
0975: public LockModeType getLockMode(Object entity) {
0976: assertNotCloseInvoked();
0977: return fromLockLevel(_broker.getLockLevel(entity));
0978: }
0979:
0980: public void lock(Object entity, LockModeType mode) {
0981: assertNotCloseInvoked();
0982: _broker.lock(entity, toLockLevel(mode), -1, this );
0983: }
0984:
0985: public void lock(Object entity) {
0986: assertNotCloseInvoked();
0987: _broker.lock(entity, this );
0988: }
0989:
0990: public void lock(Object entity, LockModeType mode, int timeout) {
0991: assertNotCloseInvoked();
0992: _broker.lock(entity, toLockLevel(mode), timeout, this );
0993: }
0994:
0995: public void lockAll(Collection entities) {
0996: assertNotCloseInvoked();
0997: _broker.lockAll(entities, this );
0998: }
0999:
1000: public void lockAll(Collection entities, LockModeType mode,
1001: int timeout) {
1002: assertNotCloseInvoked();
1003: _broker.lockAll(entities, toLockLevel(mode), timeout, this );
1004: }
1005:
1006: public void lockAll(Object... entities) {
1007: lockAll(Arrays.asList(entities));
1008: }
1009:
1010: public void lockAll(Object[] entities, LockModeType mode,
1011: int timeout) {
1012: lockAll(Arrays.asList(entities), mode, timeout);
1013: }
1014:
1015: /**
1016: * Translate our internal lock level to a javax.persistence enum value.
1017: */
1018: static LockModeType fromLockLevel(int level) {
1019: if (level < LockLevels.LOCK_READ)
1020: return null;
1021: if (level < LockLevels.LOCK_WRITE)
1022: return LockModeType.READ;
1023: return LockModeType.WRITE;
1024: }
1025:
1026: /**
1027: * Translate the javax.persistence enum value to our internal lock level.
1028: */
1029: static int toLockLevel(LockModeType mode) {
1030: if (mode == null)
1031: return LockLevels.LOCK_NONE;
1032: if (mode == LockModeType.READ)
1033: return LockLevels.LOCK_READ;
1034: if (mode == LockModeType.WRITE)
1035: return LockLevels.LOCK_WRITE;
1036: throw new ArgumentException(mode.toString(), null, null, true);
1037: }
1038:
1039: public boolean cancelAll() {
1040: return _broker.cancelAll();
1041: }
1042:
1043: public Object getConnection() {
1044: return _broker.getConnection();
1045: }
1046:
1047: public Collection getManagedObjects() {
1048: return _broker.getManagedObjects();
1049: }
1050:
1051: public Collection getTransactionalObjects() {
1052: return _broker.getTransactionalObjects();
1053: }
1054:
1055: public Collection getPendingTransactionalObjects() {
1056: return _broker.getPendingTransactionalObjects();
1057: }
1058:
1059: public Collection getDirtyObjects() {
1060: return _broker.getDirtyObjects();
1061: }
1062:
1063: public boolean getOrderDirtyObjects() {
1064: return _broker.getOrderDirtyObjects();
1065: }
1066:
1067: public void setOrderDirtyObjects(boolean order) {
1068: assertNotCloseInvoked();
1069: _broker.setOrderDirtyObjects(order);
1070: }
1071:
1072: public void dirtyClass(Class cls) {
1073: assertNotCloseInvoked();
1074: _broker.dirtyType(cls);
1075: }
1076:
1077: @SuppressWarnings("unchecked")
1078: public Collection<Class> getPersistedClasses() {
1079: return (Collection<Class>) _broker.getPersistedTypes();
1080: }
1081:
1082: @SuppressWarnings("unchecked")
1083: public Collection<Class> getUpdatedClasses() {
1084: return (Collection<Class>) _broker.getUpdatedTypes();
1085: }
1086:
1087: @SuppressWarnings("unchecked")
1088: public Collection<Class> getRemovedClasses() {
1089: return (Collection<Class>) _broker.getDeletedTypes();
1090: }
1091:
1092: public <T> T createInstance(Class<T> cls) {
1093: assertNotCloseInvoked();
1094: return (T) _broker.newInstance(cls);
1095: }
1096:
1097: public void close() {
1098: assertNotCloseInvoked();
1099: _broker.close();
1100: }
1101:
1102: public boolean isOpen() {
1103: return !_broker.isCloseInvoked();
1104: }
1105:
1106: public void dirty(Object o, String field) {
1107: assertNotCloseInvoked();
1108: OpenJPAStateManager sm = _broker.getStateManager(o);
1109: try {
1110: if (sm != null)
1111: sm.dirty(field);
1112: } catch (Exception e) {
1113: throw PersistenceExceptions.toPersistenceException(e);
1114: }
1115: }
1116:
1117: public Object getObjectId(Object o) {
1118: assertNotCloseInvoked();
1119: return JPAFacadeHelper.fromOpenJPAObjectId(_broker
1120: .getObjectId(o));
1121: }
1122:
1123: public boolean isDirty(Object o) {
1124: assertNotCloseInvoked();
1125: return _broker.isDirty(o);
1126: }
1127:
1128: public boolean isTransactional(Object o) {
1129: assertNotCloseInvoked();
1130: return _broker.isTransactional(o);
1131: }
1132:
1133: public boolean isPersistent(Object o) {
1134: assertNotCloseInvoked();
1135: return _broker.isPersistent(o);
1136: }
1137:
1138: public boolean isNewlyPersistent(Object o) {
1139: assertNotCloseInvoked();
1140: return _broker.isNew(o);
1141: }
1142:
1143: public boolean isRemoved(Object o) {
1144: assertNotCloseInvoked();
1145: return _broker.isDeleted(o);
1146: }
1147:
1148: public boolean isDetached(Object entity) {
1149: assertNotCloseInvoked();
1150: return _broker.isDetached(entity);
1151: }
1152:
1153: public Object getVersion(Object o) {
1154: assertNotCloseInvoked();
1155: return _broker.getVersion(o);
1156: }
1157:
1158: /**
1159: * Throw appropriate exception if close has been invoked but the broker
1160: * is still open. We test only for this because if the broker is already
1161: * closed, it will throw its own more informative exception when we
1162: * delegate the pending operation to it.
1163: */
1164: void assertNotCloseInvoked() {
1165: if (!_broker.isClosed() && _broker.isCloseInvoked())
1166: throw new InvalidStateException(_loc.get("close-invoked"),
1167: null, null, true);
1168: }
1169:
1170: ////////////////////////////////
1171: // FindCallbacks implementation
1172: ////////////////////////////////
1173:
1174: public Object processArgument(Object arg) {
1175: return arg;
1176: }
1177:
1178: public Object processReturn(Object oid, OpenJPAStateManager sm) {
1179: return (sm == null || sm.isDeleted()) ? null : sm
1180: .getManagedInstance();
1181: }
1182:
1183: //////////////////////////////
1184: // OpCallbacks implementation
1185: //////////////////////////////
1186:
1187: public int processArgument(int op, Object obj,
1188: OpenJPAStateManager sm) {
1189: switch (op) {
1190: case OP_DELETE:
1191: // cascade through non-persistent non-detached instances
1192: if (sm == null && !_broker.isDetached(obj))
1193: return ACT_CASCADE;
1194: if (sm != null && !sm.isDetached() && !sm.isPersistent())
1195: return ACT_CASCADE;
1196: // ignore deleted instances
1197: if (sm != null && sm.isDeleted())
1198: return ACT_NONE;
1199: break;
1200: case OP_ATTACH:
1201: // die on removed
1202: if (sm != null && sm.isDeleted())
1203: throw new UserException(_loc.get("removed", Exceptions
1204: .toString(obj))).setFailedObject(obj);
1205: // cascade through managed instances
1206: if (sm != null && !sm.isDetached())
1207: return ACT_CASCADE;
1208: break;
1209: case OP_REFRESH:
1210: // die on unmanaged instances
1211: if (sm == null)
1212: throw new UserException(_loc.get("not-managed",
1213: Exceptions.toString(obj))).setFailedObject(obj);
1214: break;
1215: }
1216: return ACT_RUN | ACT_CASCADE;
1217: }
1218:
1219: public int hashCode() {
1220: return _broker.hashCode();
1221: }
1222:
1223: public boolean equals(Object other) {
1224: if (other == this )
1225: return true;
1226: if (!(other instanceof EntityManagerImpl))
1227: return false;
1228: return _broker.equals(((EntityManagerImpl) other)._broker);
1229: }
1230:
1231: public void readExternal(ObjectInput in) throws IOException,
1232: ClassNotFoundException {
1233: try {
1234: ret = PersistenceExceptions.getRollbackTranslator(this );
1235:
1236: // this assumes that serialized Brokers are from something
1237: // that extends AbstractBrokerFactory.
1238: Object factoryKey = in.readObject();
1239: AbstractBrokerFactory factory = AbstractBrokerFactory
1240: .getPooledFactoryForKey(factoryKey);
1241: byte[] brokerBytes = (byte[]) in.readObject();
1242: ObjectInputStream innerIn = new BrokerBytesInputStream(
1243: brokerBytes, factory.getConfiguration());
1244:
1245: Broker broker = (Broker) innerIn.readObject();
1246: EntityManagerFactoryImpl emf = (EntityManagerFactoryImpl) JPAFacadeHelper
1247: .toEntityManagerFactory(broker.getBrokerFactory());
1248: broker.putUserObject(JPAFacadeHelper.EM_KEY, this );
1249: initialize(emf, broker);
1250: } catch (RuntimeException re) {
1251: try {
1252: re = ret.translate(re);
1253: } catch (Exception e) {
1254: // ignore
1255: }
1256: throw re;
1257: }
1258: }
1259:
1260: public void writeExternal(ObjectOutput out) throws IOException {
1261: try {
1262: // this requires that only AbstractBrokerFactory-sourced
1263: // brokers can be serialized
1264: Object factoryKey = ((AbstractBrokerFactory) _broker
1265: .getBrokerFactory()).getPoolKey();
1266: out.writeObject(factoryKey);
1267: ByteArrayOutputStream baos = new ByteArrayOutputStream();
1268: ObjectOutputStream innerOut = new ObjectOutputStream(baos);
1269: innerOut.writeObject(_broker.getDelegate());
1270: innerOut.flush();
1271: out.writeObject(baos.toByteArray());
1272: } catch (RuntimeException re) {
1273: try {
1274: re = ret.translate(re);
1275: } catch (Exception e) {
1276: // ignore
1277: }
1278: throw re;
1279: }
1280: }
1281:
1282: private static class BrokerBytesInputStream extends
1283: ObjectInputStream {
1284:
1285: private OpenJPAConfiguration conf;
1286:
1287: BrokerBytesInputStream(byte[] bytes, OpenJPAConfiguration conf)
1288: throws IOException {
1289: super (new ByteArrayInputStream(bytes));
1290: if (conf == null)
1291: throw new IllegalArgumentException(
1292: "Illegal null argument to ObjectInputStreamWithLoader");
1293: this .conf = conf;
1294: }
1295:
1296: /**
1297: * Make a primitive array class
1298: */
1299: private Class primitiveType(char type) {
1300: switch (type) {
1301: case 'B':
1302: return byte.class;
1303: case 'C':
1304: return char.class;
1305: case 'D':
1306: return double.class;
1307: case 'F':
1308: return float.class;
1309: case 'I':
1310: return int.class;
1311: case 'J':
1312: return long.class;
1313: case 'S':
1314: return short.class;
1315: case 'Z':
1316: return boolean.class;
1317: default:
1318: return null;
1319: }
1320: }
1321:
1322: protected Class resolveClass(ObjectStreamClass classDesc)
1323: throws IOException, ClassNotFoundException {
1324:
1325: String cname = classDesc.getName();
1326: if (cname.startsWith("[")) {
1327: // An array
1328: Class component; // component class
1329: int dcount; // dimension
1330: for (dcount = 1; cname.charAt(dcount) == '['; dcount++)
1331: ;
1332: if (cname.charAt(dcount) == 'L') {
1333: component = lookupClass(cname.substring(dcount + 1,
1334: cname.length() - 1));
1335: } else {
1336: if (cname.length() != dcount + 1) {
1337: throw new ClassNotFoundException(cname);// malformed
1338: }
1339: component = primitiveType(cname.charAt(dcount));
1340: }
1341: int dim[] = new int[dcount];
1342: for (int i = 0; i < dcount; i++) {
1343: dim[i] = 0;
1344: }
1345: return Array.newInstance(component, dim).getClass();
1346: } else {
1347: return lookupClass(cname);
1348: }
1349: }
1350:
1351: /**
1352: * If this is a generated subclass, look up the corresponding Class
1353: * object via metadata.
1354: */
1355: private Class lookupClass(String className)
1356: throws ClassNotFoundException {
1357: try {
1358: return Class.forName(className);
1359: } catch (ClassNotFoundException e) {
1360: if (PCEnhancer.isPCSubclassName(className)) {
1361: String super Name = PCEnhancer
1362: .toManagedTypeName(className);
1363: ClassMetaData[] metas = conf
1364: .getMetaDataRepositoryInstance()
1365: .getMetaDatas();
1366: for (int i = 0; i < metas.length; i++) {
1367: if (super Name.equals(metas[i]
1368: .getDescribedType().getName())) {
1369: return PCRegistry.getPCType(metas[i]
1370: .getDescribedType());
1371: }
1372: }
1373:
1374: // if it's not found, try to look for it anyways
1375: return Class.forName(className);
1376: } else {
1377: throw e;
1378: }
1379: }
1380: }
1381: }
1382: }
|