All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.openjpa.persistence.EntityManagerImpl Maven / Gradle / Ivy

There is a newer version: 4.0.1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openjpa.persistence;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.CacheRetrieveMode;
import javax.persistence.CacheStoreMode;
import javax.persistence.EntityGraph;
import javax.persistence.EntityManager;
import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
import javax.persistence.PessimisticLockScope;
import javax.persistence.Query;
import javax.persistence.StoredProcedureQuery;
import javax.persistence.Tuple;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaDelete;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.CriteriaUpdate;
import javax.persistence.criteria.ParameterExpression;
import javax.persistence.metamodel.Metamodel;

import org.apache.openjpa.conf.Compatibility;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.ee.ManagedRuntime;
import org.apache.openjpa.enhance.PCEnhancer;
import org.apache.openjpa.enhance.PCRegistry;
import org.apache.openjpa.enhance.Reflection;
import org.apache.openjpa.kernel.AbstractBrokerFactory;
import org.apache.openjpa.kernel.Broker;
import org.apache.openjpa.kernel.DataCacheRetrieveMode;
import org.apache.openjpa.kernel.DataCacheStoreMode;
import org.apache.openjpa.kernel.DelegatingBroker;
import org.apache.openjpa.kernel.FetchConfiguration;
import org.apache.openjpa.kernel.FindCallbacks;
import org.apache.openjpa.kernel.OpCallbacks;
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.kernel.PreparedQuery;
import org.apache.openjpa.kernel.PreparedQueryCache;
import org.apache.openjpa.kernel.QueryFlushModes;
import org.apache.openjpa.kernel.QueryLanguages;
import org.apache.openjpa.kernel.Seq;
import org.apache.openjpa.kernel.jpql.JPQLParser;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.Closeable;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.StringUtil;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.meta.MetaDataRepository;
import org.apache.openjpa.meta.MultiQueryMetaData;
import org.apache.openjpa.meta.QueryMetaData;
import org.apache.openjpa.meta.SequenceMetaData;
import org.apache.openjpa.persistence.criteria.OpenJPACriteriaBuilder;
import org.apache.openjpa.persistence.criteria.OpenJPACriteriaQuery;
import org.apache.openjpa.persistence.validation.ValidationUtils;
import org.apache.openjpa.util.BlacklistClassResolver;
import org.apache.openjpa.util.ExceptionInfo;
import org.apache.openjpa.util.Exceptions;
import org.apache.openjpa.util.ImplHelper;
import org.apache.openjpa.util.RuntimeExceptionTranslator;
import org.apache.openjpa.util.UserException;


/**
 * Implementation of {@link EntityManager} interface.
 *
 * @author Patrick Linskey
 * @author Abe White
 */
public class EntityManagerImpl
    implements OpenJPAEntityManagerSPI, Externalizable,
    FindCallbacks, OpCallbacks, Closeable, OpenJPAEntityTransaction {

    private static final Localizer _loc = Localizer.forPackage(EntityManagerImpl.class);
    private static final Object[] EMPTY_OBJECTS = new Object[0];

    private static final String GET_LOCK_MODE = "getLockMode";
    private static final String LOCK = "lock";
    private static final String REFRESH = "refresh";

    private DelegatingBroker _broker;
    private EntityManagerFactoryImpl _emf;
    private Map _plans = new IdentityHashMap<>(1);
    protected RuntimeExceptionTranslator _ret = PersistenceExceptions.getRollbackTranslator(this);
    private boolean _convertPositionalParams = false;
    private boolean _isJoinedToTransaction;
    private Map properties;

    public EntityManagerImpl() {
        // for Externalizable
    }

    /**
     * Constructor; supply factory and delegate.
     */
    public EntityManagerImpl(EntityManagerFactoryImpl factory, Broker broker) {
        initialize(factory, broker);
    }

    private void initialize(EntityManagerFactoryImpl factory, Broker broker) {
        _emf = factory;
        _broker = new DelegatingBroker(broker, _ret);
        _broker.setImplicitBehavior(this, _ret);
        _broker.putUserObject(JPAFacadeHelper.EM_KEY, this);
        _convertPositionalParams =
            factory.getConfiguration().getCompatibilityInstance().getConvertPositionalParametersToNamed();
    }

    /**
     * Broker delegate.
     */
    public Broker getBroker() {
        return _broker.getDelegate();
    }

    @Override
    public OpenJPAEntityManagerFactory getEntityManagerFactory() {
        return _emf;
    }

    @Override
    public OpenJPAConfiguration getConfiguration() {
        return _broker.getConfiguration();
    }

    @Override
    public FetchPlan getFetchPlan() {
        assertNotCloseInvoked();
        _broker.lock();
        try {
            FetchConfiguration fc = _broker.getFetchConfiguration();
            FetchPlan fp = _plans.get(fc);
            if (fp == null) {
                fp = _emf.toFetchPlan(_broker, fc);
                _plans.put(fc, fp);
            }
            return fp;
        } finally {
            _broker.unlock();
        }
    }

    @Override
    public FetchPlan pushFetchPlan() {
		return pushFetchPlan(null);
    }

    public FetchPlan pushFetchPlan(FetchConfiguration fc) {
        assertNotCloseInvoked();
        _broker.lock();
        try {
            _broker.pushFetchConfiguration(fc);
            return getFetchPlan();
        } finally {
            _broker.unlock();
        }
    }

    @Override
    public void popFetchPlan() {
        assertNotCloseInvoked();
        _broker.lock();
        try {
            _plans.remove(_broker.getFetchConfiguration());
            _broker.popFetchConfiguration();
        } finally {
            _broker.unlock();
        }
    }

    @Override
    public ConnectionRetainMode getConnectionRetainMode() {
        return ConnectionRetainMode.fromKernelConstant(
            _broker.getConnectionRetainMode());
    }

    @Override
    public boolean isTransactionManaged() {
        return _broker.isManaged();
    }

    @Override
    public boolean isManaged() {
        return _broker.isManaged();
    }

    @Override
    public ManagedRuntime getManagedRuntime() {
        return _broker.getManagedRuntime();
    }

    @Override
    public boolean getSyncWithManagedTransactions() {
        return _broker.getSyncWithManagedTransactions();
    }

    @Override
    public void setSyncWithManagedTransactions(boolean sync) {
        assertNotCloseInvoked();
        _broker.setSyncWithManagedTransactions(sync);
    }

    @Override
    public ClassLoader getClassLoader() {
        return _broker.getClassLoader();
    }

    @Override
    public String getConnectionUserName() {
        return _broker.getConnectionUserName();
    }

    @Override
    public String getConnectionPassword() {
        return _broker.getConnectionPassword();
    }

    @Override
    public boolean getMultithreaded() {
        return _broker.getMultithreaded();
    }

    @Override
    public void setMultithreaded(boolean multithreaded) {
        assertNotCloseInvoked();
        _broker.setMultithreaded(multithreaded);
        properties = null;
    }

    @Override
    public boolean getIgnoreChanges() {
        return _broker.getIgnoreChanges();
    }

    @Override
    public void setIgnoreChanges(boolean val) {
        assertNotCloseInvoked();
        _broker.setIgnoreChanges(val);
        properties = null;
    }

    @Override
    public boolean getNontransactionalRead() {
        return _broker.getNontransactionalRead();
    }

    @Override
    public void setNontransactionalRead(boolean val) {
        assertNotCloseInvoked();
        _broker.setNontransactionalRead(val);
        properties = null;
    }

    @Override
    public boolean getNontransactionalWrite() {
        return _broker.getNontransactionalWrite();
    }

    @Override
    public void setNontransactionalWrite(boolean val) {
        assertNotCloseInvoked();
        _broker.setNontransactionalWrite(val);
        properties = null;
    }

    @Override
    public boolean getOptimistic() {
        return _broker.getOptimistic();
    }

    @Override
    public void setOptimistic(boolean val) {
        assertNotCloseInvoked();
        _broker.setOptimistic(val);
        properties = null;
    }

    @Override
    public RestoreStateType getRestoreState() {
        return RestoreStateType.fromKernelConstant(_broker.getRestoreState());
    }

    @Override
    public void setRestoreState(RestoreStateType val) {
        assertNotCloseInvoked();
        _broker.setRestoreState(val.toKernelConstant());
        properties = null;
    }

    @Override
    public void setRestoreState(int restore) {
        assertNotCloseInvoked();
        _broker.setRestoreState(restore);
        properties = null;
    }

    @Override
    public boolean getRetainState() {
        return _broker.getRetainState();
    }

    @Override
    public void setRetainState(boolean val) {
        assertNotCloseInvoked();
        _broker.setRetainState(val);
        properties = null;
    }

    @Override
    public AutoClearType getAutoClear() {
        return AutoClearType.fromKernelConstant(_broker.getAutoClear());
    }

    @Override
    public void setAutoClear(AutoClearType val) {
        assertNotCloseInvoked();
        _broker.setAutoClear(val.toKernelConstant());
        properties = null;
    }

    @Override
    public void setAutoClear(int autoClear) {
        assertNotCloseInvoked();
        _broker.setAutoClear(autoClear);
        properties = null;
    }

    @Override
    public DetachStateType getDetachState() {
        return DetachStateType.fromKernelConstant(_broker.getDetachState());
    }

    @Override
    public void setDetachState(DetachStateType type) {
        assertNotCloseInvoked();
        _broker.setDetachState(type.toKernelConstant());
        properties = null;
    }

    @Override
    public void setDetachState(int detach) {
        assertNotCloseInvoked();
        _broker.setDetachState(detach);
        properties = null;
    }

    @Override
    public EnumSet getAutoDetach() {
        return AutoDetachType.toEnumSet(_broker.getAutoDetach());
    }

    @Override
    public void setAutoDetach(AutoDetachType flag) {
        assertNotCloseInvoked();
        _broker.setAutoDetach(AutoDetachType.fromEnumSet(EnumSet.of(flag)));
        properties = null;
    }

    @Override
    public void setAutoDetach(EnumSet flags) {
        assertNotCloseInvoked();
        _broker.setAutoDetach(AutoDetachType.fromEnumSet(flags));
        properties = null;
    }

    @Override
    public void setAutoDetach(int autoDetachFlags) {
        assertNotCloseInvoked();
        _broker.setAutoDetach(autoDetachFlags);
        properties = null;
    }

    @Override
    public void setAutoDetach(AutoDetachType value, boolean on) {
        assertNotCloseInvoked();
        _broker.setAutoDetach(AutoDetachType.fromEnumSet(EnumSet.of(value)),on);
        properties = null;
    }

    @Override
    public void setAutoDetach(int flag, boolean on) {
        assertNotCloseInvoked();
        _broker.setAutoDetach(flag, on);
        properties = null;
    }

    @Override
    public boolean getEvictFromStoreCache() {
        return _broker.getEvictFromDataCache();
    }

    @Override
    public void setEvictFromStoreCache(boolean evict) {
        assertNotCloseInvoked();
        _broker.setEvictFromDataCache(evict);
        properties = null;
    }

    @Override
    public boolean getPopulateStoreCache() {
        return _broker.getPopulateDataCache();
    }

    @Override
    public void setPopulateStoreCache(boolean cache) {
        assertNotCloseInvoked();
        _broker.setPopulateDataCache(cache);
        properties = null;
    }

    @Override
    public boolean isTrackChangesByType() {
        return _broker.isTrackChangesByType();
    }

    @Override
    public void setTrackChangesByType(boolean trackByType) {
        assertNotCloseInvoked();
        _broker.setTrackChangesByType(trackByType);
        properties = null;
    }

    @Override
    public boolean isLargeTransaction() {
        return isTrackChangesByType();
    }

    @Override
    public void setLargeTransaction(boolean value) {
        setTrackChangesByType(value);
    }

    @Override
    public Object getUserObject(Object key) {
        return _broker.getUserObject(key);
    }

    @Override
    public Object putUserObject(Object key, Object val) {
        assertNotCloseInvoked();
        return _broker.putUserObject(key, val);
    }

    @Override
    public void addTransactionListener(Object listener) {
        assertNotCloseInvoked();
        _broker.addTransactionListener(listener);
    }

    @Override
    public void removeTransactionListener(Object listener) {
        assertNotCloseInvoked();
        _broker.removeTransactionListener(listener);
    }

    @Override
    public EnumSet getTransactionListenerCallbackModes() {
        return CallbackMode.toEnumSet(
            _broker.getTransactionListenerCallbackMode());
    }

    @Override
    public void setTransactionListenerCallbackMode(CallbackMode mode) {
        assertNotCloseInvoked();
        _broker.setTransactionListenerCallbackMode(
            CallbackMode.fromEnumSet(EnumSet.of(mode)));
    }

    @Override
    public void setTransactionListenerCallbackMode(EnumSet modes){
        assertNotCloseInvoked();
        _broker.setTransactionListenerCallbackMode(
            CallbackMode.fromEnumSet(modes));
    }

    @Override
    public int getTransactionListenerCallbackMode() {
        return _broker.getTransactionListenerCallbackMode();
    }

    @Override
    public void setTransactionListenerCallbackMode(int callbackMode) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void addLifecycleListener(Object listener, Class... classes) {
        assertNotCloseInvoked();
        _broker.addLifecycleListener(listener, classes);
    }

    @Override
    public void removeLifecycleListener(Object listener) {
        assertNotCloseInvoked();
        _broker.removeLifecycleListener(listener);
    }

    @Override
    public EnumSet getLifecycleListenerCallbackModes() {
        return CallbackMode.toEnumSet(
            _broker.getLifecycleListenerCallbackMode());
    }

    @Override
    public void setLifecycleListenerCallbackMode(CallbackMode mode) {
        assertNotCloseInvoked();
        _broker.setLifecycleListenerCallbackMode(
            CallbackMode.fromEnumSet(EnumSet.of(mode)));
    }

    @Override
    public void setLifecycleListenerCallbackMode(EnumSet modes) {
        assertNotCloseInvoked();
        _broker.setLifecycleListenerCallbackMode(
            CallbackMode.fromEnumSet(modes));
    }

    @Override
    public int getLifecycleListenerCallbackMode() {
        return _broker.getLifecycleListenerCallbackMode();
    }

    @Override
    public void setLifecycleListenerCallbackMode(int callbackMode) {
        assertNotCloseInvoked();
        _broker.setLifecycleListenerCallbackMode(callbackMode);
    }

    @Override
    @SuppressWarnings("unchecked")
    public  T getReference(Class cls, Object oid) {
        assertNotCloseInvoked();
        oid = _broker.newObjectId(cls, oid);
        return (T) _broker.find(oid, false, this);
    }

    @Override
    @SuppressWarnings("unchecked")
    public  T find(Class cls, Object oid) {
        assertNotCloseInvoked();
        if (oid == null)
        	return null;
        oid = _broker.newObjectId(cls, oid);
        return (T) _broker.find(oid, true, this);
    }

    @Override
    public  T find(Class cls, Object oid, LockModeType mode) {
        return find(cls, oid, mode, null);
    }

    @Override
    public  T find(Class cls, Object oid,
        Map properties){
        return find(cls, oid, null, properties);
    }

    @Override
    @SuppressWarnings("unchecked")
    public  T find(Class cls, Object oid, LockModeType mode, Map properties) {
        assertNotCloseInvoked();
        properties = cloneProperties(properties);
        configureCurrentCacheModes(pushFetchPlan(), properties);
        configureCurrentFetchPlan(getFetchPlan(), properties, mode, true);
        try {
            oid = _broker.newObjectId(cls, oid);
            return (T) _broker.find(oid, true, this);
        } finally {
            popFetchPlan();
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public  T[] findAll(Class cls, Object... oids) {
        if (oids.length == 0)
            return (T[]) Array.newInstance(cls, 0);
        Collection ret = findAll(cls, Arrays.asList(oids));
        return ret.toArray((T[]) Array.newInstance(cls, ret.size()));
    }

    @Override
    @SuppressWarnings("unchecked")
    public  Collection findAll(final Class cls, Collection oids) {
        assertNotCloseInvoked();
        Object[] objs = _broker.findAll(oids, true, new FindCallbacks() {
            @Override
            public Object processArgument(Object oid) {
                return _broker.newObjectId(cls, oid);
            }

            @Override
            public Object processReturn(Object oid, OpenJPAStateManager sm) {
                return EntityManagerImpl.this.processReturn(oid, sm);
            }
        });
        return (Collection) Arrays.asList(objs);
    }

    @Override
    @SuppressWarnings("unchecked")
    public  T findCached(Class cls, Object oid) {
        assertNotCloseInvoked();
        return (T) _broker.findCached(_broker.newObjectId(cls, oid), this);
    }

    @Override
    public Class getObjectIdClass(Class cls) {
        assertNotCloseInvoked();
        if (cls == null)
            return null;
        return JPAFacadeHelper.fromOpenJPAObjectIdClass
                (_broker.getObjectIdType(cls));
    }

    @Override
    public OpenJPAEntityTransaction getTransaction() {
        if (_broker.isManaged())
            throw new InvalidStateException(_loc.get("get-managed-trans"),
                null, null, false);
        return this;
    }

    @Override
    public void joinTransaction() {
        if (!_broker.syncWithManagedTransaction()) {
            throw new TransactionRequiredException(_loc.get
                    ("no-managed-trans"), null, null, false);
        } else {
            _isJoinedToTransaction = true;
        }

        assertNotCloseInvoked();
        if (!_broker.syncWithManagedTransaction())
            throw new TransactionRequiredException(_loc.get
                ("no-managed-trans"), null, null, false);
    }

    @Override
    public boolean isJoinedToTransaction() {
        return isActive() && _isJoinedToTransaction;
    }

    @Override
    public void begin() {
        _broker.begin();
    }

    @Override
    public void commit() {
        try {
            _broker.commit();
        } catch (RollbackException | IllegalStateException e) {
            throw e;
        }
        catch (Exception e) {
        	// Per JPA 2.0 spec, if the exception was due to a JSR-303
            // constraint violation, the ConstraintViolationException should be
            // thrown.  Since JSR-303 is optional, the cast to RuntimeException
            // prevents the introduction of a runtime dependency on the BV API.
            if (ValidationUtils.isConstraintViolationException(e))
                throw (RuntimeException)e;
            // RollbackExceptions are special and aren't handled by the
            // normal exception translator, since the spec says they
            // should be thrown whenever the commit fails for any reason at
            // all, wheras the exception translator handles exceptions that
            // are caused for specific reasons

            // pass along the failed object if one is available.
            Object failedObject = null;
            if (e instanceof ExceptionInfo){
            	failedObject = ((ExceptionInfo)e).getFailedObject();
            }

            throw new RollbackException(e).setFailedObject(failedObject);
        }
    }

    @Override
    public void rollback() {
        _broker.rollback();
    }

    @Override
    public void commitAndResume() {
        _broker.commitAndResume();
    }

    @Override
    public void rollbackAndResume() {
        _broker.rollbackAndResume();
    }

    @Override
    public Throwable getRollbackCause() {
        if (!isActive())
            throw new IllegalStateException(_loc.get("no-transaction")
                .getMessage());

        return _broker.getRollbackCause();
    }

    @Override
    public boolean getRollbackOnly() {
        if (!isActive())
            throw new IllegalStateException(_loc.get("no-transaction")
                .getMessage());

        return _broker.getRollbackOnly();
    }

    @Override
    public void setRollbackOnly() {
        _broker.setRollbackOnly();
    }

    @Override
    public void setRollbackOnly(Throwable cause) {
        _broker.setRollbackOnly(cause);
    }

    @Override
    public void setSavepoint(String name) {
        assertNotCloseInvoked();
        _broker.setSavepoint(name);
    }

    @Override
    public void rollbackToSavepoint() {
        assertNotCloseInvoked();
        _broker.rollbackToSavepoint();
    }

    @Override
    public void rollbackToSavepoint(String name) {
        assertNotCloseInvoked();
        _broker.rollbackToSavepoint(name);
    }

    @Override
    public void releaseSavepoint() {
        assertNotCloseInvoked();
        _broker.releaseSavepoint();
    }

    @Override
    public void releaseSavepoint(String name) {
        assertNotCloseInvoked();
        _broker.releaseSavepoint(name);
    }

    @Override
    public void flush() {
        assertNotCloseInvoked();
        _broker.assertOpen();
        _broker.assertActiveTransaction();
        _broker.flush();
    }

    @Override
    public void preFlush() {
        assertNotCloseInvoked();
        _broker.preFlush();
    }

    @Override
    public void validateChanges() {
        assertNotCloseInvoked();
        _broker.validateChanges();
    }

    @Override
    public boolean isActive() {
        return isOpen() && _broker.isActive();
    }

    @Override
    public boolean isStoreActive() {
        return _broker.isStoreActive();
    }

    @Override
    public void beginStore() {
        _broker.beginStore();
    }

    @Override
    public boolean contains(Object entity) {
        assertNotCloseInvoked();
        if (entity == null)
            return false;
        OpenJPAStateManager sm = _broker.getStateManager(entity);
        if (sm == null
            && !ImplHelper.isManagedType(getConfiguration(), entity.getClass()))
            throw new ArgumentException(_loc.get("not-entity",
                entity.getClass()), null, null, true);
        return sm != null && !sm.isDeleted();
    }

    @Override
    public boolean containsAll(Object... entities) {
        for (Object entity : entities)
            if (!contains(entity))
                return false;
        return true;
    }

    @Override
    public boolean containsAll(Collection entities) {
        for (Object entity : entities)
            if (!contains(entity))
                return false;
        return true;
    }

    @Override
    public void persist(Object entity) {
        assertNotCloseInvoked();
        _broker.persist(entity, this);
    }

    @Override
    public void persistAll(Object... entities) {
        persistAll(Arrays.asList(entities));
    }

    @Override
    public void persistAll(Collection entities) {
        assertNotCloseInvoked();
        _broker.persistAll(entities, this);
    }

    @Override
    public void remove(Object entity) {
        assertNotCloseInvoked();
        _broker.delete(entity, this);
    }

    @Override
    public void removeAll(Object... entities) {
        removeAll(Arrays.asList(entities));
    }

    @Override
    public void removeAll(Collection entities) {
        assertNotCloseInvoked();
        _broker.deleteAll(entities, this);
    }

    @Override
    public void release(Object entity) {
        assertNotCloseInvoked();
        _broker.release(entity, this);
    }

    @Override
    public void releaseAll(Collection entities) {
        assertNotCloseInvoked();
        _broker.releaseAll(entities, this);
    }

    @Override
    public void releaseAll(Object... entities) {
        releaseAll(Arrays.asList(entities));
    }

    @Override
    public void refresh(Object entity) {
        refresh(entity, null, null);
    }

    @Override
    public void refresh(Object entity, LockModeType mode) {
        refresh(entity, mode, null);
    }

    @Override
    public void refresh(Object entity, Map properties) {
        refresh(entity, null, properties);
    }

    @Override
    public void refresh(Object entity, LockModeType mode, Map properties) {
        assertNotCloseInvoked();
        assertValidAttchedEntity(REFRESH, entity);

        _broker.assertWriteOperation();
        configureCurrentCacheModes(pushFetchPlan(), properties);
        configureCurrentFetchPlan(getFetchPlan(), properties, mode, true);
        DataCacheRetrieveMode rmode = getFetchPlan().getCacheRetrieveMode();
        if (DataCacheRetrieveMode.USE.equals(rmode) || rmode == null) {
            getFetchPlan().setCacheRetrieveMode(DataCacheRetrieveMode.BYPASS);
        }
        try {
            _broker.refresh(entity, this);
        } finally {
            popFetchPlan();
        }
    }

    @Override
    public void refreshAll() {
        assertNotCloseInvoked();
        _broker.assertWriteOperation();
        _broker.refreshAll(_broker.getTransactionalObjects(), this);
    }

    @Override
    public void refreshAll(Collection entities) {
        assertNotCloseInvoked();
        _broker.assertWriteOperation();
        _broker.refreshAll(entities, this);
    }

    @Override
    public void refreshAll(Object... entities) {
        refreshAll(Arrays.asList(entities));
    }

    @Override
    public void retrieve(Object entity) {
        assertNotCloseInvoked();
        _broker.retrieve(entity, true, this);
    }

    @Override
    public void retrieveAll(Collection entities) {
        assertNotCloseInvoked();
        _broker.retrieveAll(entities, true, this);
    }

    @Override
    public void retrieveAll(Object... entities) {
        retrieveAll(Arrays.asList(entities));
    }

    @Override
    public void evict(Object entity) {
        assertNotCloseInvoked();
        _broker.evict(entity, this);
    }

    @Override
    public void evictAll(Collection entities) {
        assertNotCloseInvoked();
        _broker.evictAll(entities, this);
    }

    @Override
    public void evictAll(Object... entities) {
        evictAll(Arrays.asList(entities));
    }

    @Override
    public void evictAll() {
        assertNotCloseInvoked();
        _broker.evictAll(this);
    }

    @Override
    public void evictAll(Class cls) {
        assertNotCloseInvoked();
        _broker.evictAll(_broker.newExtent(cls, true), this);
    }

    @Override
    public void evictAll(Extent extent) {
        assertNotCloseInvoked();
        _broker.evictAll(((ExtentImpl) extent).getDelegate(), this);
    }

    @Override
    @SuppressWarnings("unchecked")
    public  T detachCopy(T entity) {
        assertNotCloseInvoked();
        Compatibility compat = this.getConfiguration().
            getCompatibilityInstance();
        boolean copyOnDetach = compat.getCopyOnDetach();
        boolean cascadeWithDetach = compat.getCascadeWithDetach();
        // Set compatibility options to get 1.x detach behavior
        compat.setCopyOnDetach(true);
        compat.setCascadeWithDetach(true);
        try {
            T t = (T)_broker.detach(entity, this);
            return t;
        } finally {
            // Reset compatibility options
            compat.setCopyOnDetach(copyOnDetach);
            compat.setCascadeWithDetach(cascadeWithDetach);
        }
    }

    @Override
    public Object[] detachAll(Object... entities) {
        assertNotCloseInvoked();
        return _broker.detachAll(Arrays.asList(entities), this);
    }

    @Override
    public Collection detachAll(Collection entities) {
        assertNotCloseInvoked();
        return Arrays.asList(_broker.detachAll(entities, this));
    }

    @Override
    @SuppressWarnings("unchecked")
    public  T merge(T entity) {
        assertNotCloseInvoked();
        return (T) _broker.attach(entity, true, this);
    }

    @Override
    public Object[] mergeAll(Object... entities) {
        if (entities.length == 0)
            return EMPTY_OBJECTS;
        return mergeAll(Arrays.asList(entities)).toArray();
    }

    @Override
    public Collection mergeAll(Collection entities) {
        assertNotCloseInvoked();
        return Arrays.asList(_broker.attachAll(entities, true, this));
    }

    @Override
    public void transactional(Object entity, boolean updateVersion) {
        assertNotCloseInvoked();
        _broker.transactional(entity, updateVersion, this);
    }

    @Override
    public void transactionalAll(Collection objs, boolean updateVersion) {
        assertNotCloseInvoked();
        _broker.transactionalAll(objs, updateVersion, this);
    }

    @Override
    public void transactionalAll(Object[] objs, boolean updateVersion) {
        assertNotCloseInvoked();
        _broker.transactionalAll(Arrays.asList(objs), updateVersion, this);
    }

    @Override
    public void nontransactional(Object entity) {
        assertNotCloseInvoked();
        _broker.nontransactional(entity, this);
    }

    @Override
    public void nontransactionalAll(Collection objs) {
        assertNotCloseInvoked();
        _broker.nontransactionalAll(objs, this);
    }

    @Override
    public void nontransactionalAll(Object[] objs) {
        assertNotCloseInvoked();
        _broker.nontransactionalAll(Arrays.asList(objs), this);
    }

    @Override
    public Generator getNamedGenerator(String name) {
        assertNotCloseInvoked();
        try {
            SequenceMetaData meta = _broker.getConfiguration().
                getMetaDataRepositoryInstance().getSequenceMetaData(name,
                _broker.getClassLoader(), true);
            Seq seq = meta.getInstance(_broker.getClassLoader());
            return new GeneratorImpl(seq, name, _broker, null);
        } catch (RuntimeException re) {
            throw PersistenceExceptions.toPersistenceException(re);
        }
    }

    @Override
    public Generator getIdGenerator(Class forClass) {
        assertNotCloseInvoked();
        try {
            ClassMetaData meta = _broker.getConfiguration().
                getMetaDataRepositoryInstance().getMetaData(forClass,
                _broker.getClassLoader(), true);
            Seq seq = _broker.getIdentitySequence(meta);
            return (seq == null) ? null : new GeneratorImpl(seq, null, _broker,
                meta);
        } catch (Exception e) {
            throw PersistenceExceptions.toPersistenceException(e);
        }
    }

    @Override
    public Generator getFieldGenerator(Class forClass, String fieldName) {
        assertNotCloseInvoked();
        try {
            ClassMetaData meta = _broker.getConfiguration().
                getMetaDataRepositoryInstance().getMetaData(forClass,
                _broker.getClassLoader(), true);
            FieldMetaData fmd = meta.getField(fieldName);
            if (fmd == null)
                throw new ArgumentException(_loc.get("no-named-field",
                    forClass, fieldName), null, null, false);

            Seq seq = _broker.getValueSequence(fmd);
            return (seq == null) ? null : new GeneratorImpl(seq, null, _broker,
                meta);
        } catch (Exception e) {
            throw PersistenceExceptions.toPersistenceException(e);
        }
    }

    @Override
    public  Extent createExtent(Class cls, boolean subclasses) {
        assertNotCloseInvoked();
        return new ExtentImpl(this, _broker.newExtent(cls, subclasses));
    }

    @Override
    @SuppressWarnings("unchecked")
    public  TypedQuery createQuery(String query, Class resultClass) {
        checkTuple(resultClass);
        return createQuery(query).setResultClass(resultClass);
    }

    private  void checkTuple(Class resultClass) {
        if (Tuple.class == resultClass) {
            throw new PersistenceException("Tuple is not a valid type", null, null, true);
        }
    }

    @Override
    public OpenJPAQuery createQuery(String query) {
        return createQuery(JPQLParser.LANG_JPQL, query);
    }

    @Override
    public OpenJPAQuery createQuery(String language, String query) {
        assertNotCloseInvoked();
        try {
            // We need
            if (query != null && _convertPositionalParams && JPQLParser.LANG_JPQL.equals(language)) {
                query = query.replaceAll("[\\?]", "\\:_");
            }
            String qid = query;
            PreparedQuery pq = JPQLParser.LANG_JPQL.equals(language)
                ? getPreparedQuery(qid) : null;
            org.apache.openjpa.kernel.Query q = (pq == null || !pq.isInitialized())
                ? _broker.newQuery(language, query)
                : _broker.newQuery(pq.getLanguage(), pq);
            // have to validate JPQL according to spec
            if (pq == null && JPQLParser.LANG_JPQL.equals(language))
                q.compile();
            if (pq != null) {
                pq.setInto(q);
            }
            return newQueryImpl(q, null).setId(qid);
        } catch (RuntimeException re) {
            throw PersistenceExceptions.toPersistenceException(re);
        }
    }

    @Override
    public OpenJPAQuery createQuery(Query query) {
        if (query == null)
            return createQuery((String) null);
        assertNotCloseInvoked();
        org.apache.openjpa.kernel.Query q = ((QueryImpl) query).getDelegate();
        return newQueryImpl(_broker.newQuery(q.getLanguage(), q), null);
    }

    @Override
    @SuppressWarnings("unchecked")
    public  TypedQuery createNamedQuery(String name, Class resultClass) {
        checkTuple(resultClass);
        return createNamedQuery(name).setResultClass(resultClass);
    }

    @Override
    public OpenJPAQuery createNamedQuery(String name) {
        assertNotCloseInvoked();
        _broker.assertOpen();
        try {
            QueryMetaData meta = _broker.getConfiguration().
                getMetaDataRepositoryInstance().getQueryMetaData(null, name,
                _broker.getClassLoader(), true);
            String qid = meta.getQueryString();

            PreparedQuery pq = JPQLParser.LANG_JPQL.equals(meta.getLanguage()) ? getPreparedQuery(qid) : null;
            org.apache.openjpa.kernel.Query del =
                (pq == null || !pq.isInitialized()) ? _broker.newQuery(meta.getLanguage(), meta.getQueryString())
                    : _broker.newQuery(pq.getLanguage(), pq);

            if (pq != null) {
                pq.setInto(del);
            } else {
                meta.setInto(del);
                del.compile();
            }

            OpenJPAQuery q = newQueryImpl(del, meta).setId(qid);
            String[] hints = meta.getHintKeys();
            Object[] values = meta.getHintValues();
            for (int i = 0; i < hints.length; i++)
                q.setHint(hints[i], values[i]);
            return q;
        } catch (RuntimeException re) {
            throw PersistenceExceptions.toPersistenceException(re);
        }
    }

    @Override
    public OpenJPAQuery createNativeQuery(String query) {
        validateSQL(query);
        return createQuery(QueryLanguages.LANG_SQL, query);
    }

    @Override
    public OpenJPAQuery createNativeQuery(String query, Class cls) {
        checkTuple(cls);
        return createNativeQuery(query).setResultClass(cls);
    }

    @Override
    public OpenJPAQuery createNativeQuery(String query, String mappingName) {
        assertNotCloseInvoked();
        validateSQL(query);
        org.apache.openjpa.kernel.Query kernelQuery = _broker.newQuery(
            QueryLanguages.LANG_SQL, query);
        kernelQuery.setResultMapping(null, mappingName);
        return newQueryImpl(kernelQuery, null);
    }

    @Override
    public StoredProcedureQuery createNamedStoredProcedureQuery(String name) {
        QueryMetaData meta = getQueryMetadata(name);
        if (!MultiQueryMetaData.class.isInstance(meta)) {
            throw new RuntimeException(name + " is not an identifier for a Stored Procedure Query");
        }
        return newProcedure(((MultiQueryMetaData)meta).getProcedureName(), (MultiQueryMetaData)meta);
    }

    @Override
    public StoredProcedureQuery createStoredProcedureQuery(String procedureName) {
        return newProcedure(procedureName, null);
    }

    @Override
    public StoredProcedureQuery createStoredProcedureQuery(String procedureName, Class... resultClasses) {
        String tempName = "StoredProcedure-"+System.nanoTime();
        MultiQueryMetaData meta = new MultiQueryMetaData(null, tempName, procedureName, true);
        for (Class res : resultClasses) {
            meta.addComponent(res);
        }
        return newProcedure(procedureName, meta);
    }

    @Override
    public StoredProcedureQuery createStoredProcedureQuery(String procedureName, String... resultSetMappings) {
        String tempName = "StoredProcedure-"+System.nanoTime();
        MultiQueryMetaData meta = new MultiQueryMetaData(null, tempName, procedureName, true);
        for (String mapping : resultSetMappings) {
            meta.addComponent(mapping);
        }
        return newProcedure(procedureName, meta);
    }

    /**
     * Creates a query to execute a Stored Procedure.
     * 
* Construction of a {@link StoredProcedureQuery} object is a three step process *
  • *
  • a {@link org.apache.openjpa.kernel.Query kernel query} {@code kQ} is created for * {@link QueryLanguages#LANG_SQL SQL} language with the string {@code S} *
  • a {@link QueryImpl facade query} {@code fQ} is created that delegates to the kernel query {@code kQ} *
  • a {@link StoredProcedureQueryImpl stored procedure query} is created that delegates to the facade query * {@code fQ}. *
    * */ private StoredProcedureQuery newProcedure(String procedureName, MultiQueryMetaData meta) { org.apache.openjpa.kernel.QueryImpl kernelQuery = (org.apache.openjpa.kernel.QueryImpl) _broker.newQuery(QueryLanguages.LANG_STORED_PROC, procedureName); kernelQuery.getStoreQuery().setQuery(meta); if (meta != null) { getConfiguration().getMetaDataRepositoryInstance().addQueryMetaData(meta); kernelQuery.setResultMapping(null, meta.getResultSetMappingName()); } return new StoredProcedureQueryImpl(procedureName, meta, new QueryImpl(this, _ret, kernelQuery, meta)); } protected QueryImpl newQueryImpl(org.apache.openjpa.kernel.Query kernelQuery, QueryMetaData qmd) { return new QueryImpl<>(this, _ret, kernelQuery, qmd); } /** * @Deprecated -- Use org.apache.openjpa.persistence.EntityManagerImpl.newQueryImpl(Query kernelQuery, QueryMetaData * qmd) *
    * Leave this method here as extenders of OpenJPA might depend on this hook to allow interception of * query creation */ protected QueryImpl newQueryImpl(org.apache.openjpa.kernel.Query kernelQuery) { return new QueryImpl<>(this, _ret, kernelQuery, null); } /** * Validate that the user provided SQL. */ protected void validateSQL(String query) { if (StringUtil.trimToNull(query) == null) throw new ArgumentException(_loc.get("no-sql"), null, null, false); } PreparedQueryCache getPreparedQueryCache() { return _broker.getCachePreparedQuery() ? getConfiguration().getQuerySQLCacheInstance() : null; } /** * Gets the prepared query cached by the given key. * * @return the cached PreparedQuery or null if none exists. */ PreparedQuery getPreparedQuery(String id) { PreparedQueryCache cache = getPreparedQueryCache(); return (cache == null) ? null : cache.get(id); } @Override public void setFlushMode(FlushModeType flushMode) { assertNotCloseInvoked(); _broker.assertOpen(); _broker.getFetchConfiguration().setFlushBeforeQueries (toFlushBeforeQueries(flushMode)); properties = null; } @Override public FlushModeType getFlushMode() { assertNotCloseInvoked(); _broker.assertOpen(); return fromFlushBeforeQueries(_broker.getFetchConfiguration(). getFlushBeforeQueries()); } /** * Translate our internal flush constant to a flush mode enum value. */ static FlushModeType fromFlushBeforeQueries(int flush) { switch (flush) { case QueryFlushModes.FLUSH_TRUE: return FlushModeType.AUTO; case QueryFlushModes.FLUSH_FALSE: return FlushModeType.COMMIT; default: return null; } } /** * Translate a flush mode enum value to our internal flush constant. */ static int toFlushBeforeQueries(FlushModeType flushMode) { // choose default for null if (flushMode == null) return QueryFlushModes.FLUSH_WITH_CONNECTION; if (flushMode == FlushModeType.AUTO) return QueryFlushModes.FLUSH_TRUE; if (flushMode == FlushModeType.COMMIT) return QueryFlushModes.FLUSH_FALSE; throw new ArgumentException(flushMode.toString(), null, null, false); } /** * Used by Java EE Containers that wish to pool OpenJPA EntityManagers. The specification * doesn't allow the closing of connections with the clear() method. By introducing this * new method, we can do additional processing (and maybe more efficient processing) to * properly prepare an EM for pooling. * * @deprecated - use {@link clear()} instead. */ @Deprecated public void prepareForPooling() { assertNotCloseInvoked(); clear(); // Do not close connection if ConnectionRetainMode is set to Always... if (getConnectionRetainMode() != ConnectionRetainMode.ALWAYS) { _broker.lock(); // since this direct close path is not protected... try { _broker.getStoreManager().close(); } finally { _broker.unlock(); } } } @Override public void clear() { assertNotCloseInvoked(); _broker.detachAll(this, false); _plans.clear(); } @Override public Object getDelegate() { _broker.assertOpen(); assertNotCloseInvoked(); return this; } @Override public LockModeType getLockMode(Object entity) { assertNotCloseInvoked(); _broker.assertActiveTransaction(); assertValidAttchedEntity(GET_LOCK_MODE, entity); return MixedLockLevelsHelper.fromLockLevel( _broker.getLockLevel(entity)); } @Override public void lock(Object entity, LockModeType mode) { lock(entity, mode, -1); } @Override public void lock(Object entity) { assertNotCloseInvoked(); assertValidAttchedEntity(LOCK, entity); _broker.lock(entity, this); } @Override public void lock(Object entity, LockModeType mode, int timeout) { assertNotCloseInvoked(); assertValidAttchedEntity(LOCK, entity); configureCurrentFetchPlan(pushFetchPlan(), null, mode, false); try { _broker.lock(entity, MixedLockLevelsHelper.toLockLevel(mode), timeout, this); } finally { popFetchPlan(); } } @Override public void lock(Object entity, LockModeType mode, Map properties) { assertNotCloseInvoked(); assertValidAttchedEntity(LOCK, entity); _broker.assertActiveTransaction(); properties = cloneProperties(properties); configureCurrentCacheModes(pushFetchPlan(), properties); configureCurrentFetchPlan(getFetchPlan(), properties, mode, false); try { _broker.lock(entity, MixedLockLevelsHelper.toLockLevel(mode), _broker.getFetchConfiguration().getLockTimeout(), this); } finally { popFetchPlan(); } } @Override public void lockAll(Collection entities) { assertNotCloseInvoked(); _broker.lockAll(entities, this); } @Override public void lockAll(Collection entities, LockModeType mode, int timeout) { assertNotCloseInvoked(); _broker.lockAll(entities, MixedLockLevelsHelper.toLockLevel(mode), timeout, this); } @Override public void lockAll(Object... entities) { lockAll(Arrays.asList(entities)); } @Override public void lockAll(Object[] entities, LockModeType mode, int timeout) { lockAll(Arrays.asList(entities), mode, timeout); } @Override public boolean cancelAll() { return _broker.cancelAll(); } @Override public Object getConnection() { return _broker.getConnection(); } @Override public Collection getManagedObjects() { return _broker.getManagedObjects(); } @Override public Collection getTransactionalObjects() { return _broker.getTransactionalObjects(); } @Override public Collection getPendingTransactionalObjects() { return _broker.getPendingTransactionalObjects(); } @Override public Collection getDirtyObjects() { return _broker.getDirtyObjects(); } @Override public boolean getOrderDirtyObjects() { return _broker.getOrderDirtyObjects(); } @Override public void setOrderDirtyObjects(boolean order) { assertNotCloseInvoked(); _broker.setOrderDirtyObjects(order); } @Override public void dirtyClass(Class cls) { assertNotCloseInvoked(); _broker.dirtyType(cls); } @Override @SuppressWarnings("unchecked") public Collection getPersistedClasses() { return (Collection) _broker.getPersistedTypes(); } @Override @SuppressWarnings("unchecked") public Collection getUpdatedClasses() { return (Collection) _broker.getUpdatedTypes(); } @Override @SuppressWarnings("unchecked") public Collection getRemovedClasses() { return (Collection) _broker.getDeletedTypes(); } @Override public T createInstance(Class cls) { assertNotCloseInvoked(); return (T) _broker.newInstance(cls); } @Override public void close() { assertNotCloseInvoked(); Log log = _emf.getConfiguration().getLog(OpenJPAConfiguration.LOG_RUNTIME); if (log.isTraceEnabled()) { log.trace(this + ".close() invoked."); } _broker.close(); _plans.clear(); } @Override public boolean isOpen() { return !_broker.isCloseInvoked(); } @Override public void dirty(Object o, String field) { assertNotCloseInvoked(); OpenJPAStateManager sm = _broker.getStateManager(o); try { if (sm != null) sm.dirty(field); } catch (Exception e) { throw PersistenceExceptions.toPersistenceException(e); } } @Override public Object getObjectId(Object o) { assertNotCloseInvoked(); return JPAFacadeHelper.fromOpenJPAObjectId(_broker.getObjectId(o)); } @Override public boolean isDirty(Object o) { assertNotCloseInvoked(); return _broker.isDirty(o); } @Override public boolean isTransactional(Object o) { assertNotCloseInvoked(); return _broker.isTransactional(o); } @Override public boolean isPersistent(Object o) { assertNotCloseInvoked(); return _broker.isPersistent(o); } @Override public boolean isNewlyPersistent(Object o) { assertNotCloseInvoked(); return _broker.isNew(o); } @Override public boolean isRemoved(Object o) { assertNotCloseInvoked(); return _broker.isDeleted(o); } @Override public boolean isDetached(Object entity) { assertNotCloseInvoked(); return _broker.isDetached(entity); } @Override public Object getVersion(Object o) { assertNotCloseInvoked(); return _broker.getVersion(o); } /** * Throw appropriate exception if close has been invoked but the broker * is still open. We test only for this because if the broker is already * closed, it will throw its own more informative exception when we * delegate the pending operation to it. */ protected void assertNotCloseInvoked() { if (!_broker.isClosed() && _broker.isCloseInvoked()) throw new InvalidStateException(_loc.get("close-invoked"), null, null, true); } /** * Throw IllegalArgumentExceptionif if entity is not a valid entity or * if it is detached. */ void assertValidAttchedEntity(String call, Object entity) { OpenJPAStateManager sm = _broker.getStateManager(entity); if (sm == null || !sm.isPersistent() || sm.isDetached() || (call.equals(REFRESH) && sm.isDeleted())) { throw new IllegalArgumentException(_loc.get("invalid_entity_argument", call, entity == null ? "null" : Exceptions.toString(entity)).getMessage()); } } //////////////////////////////// // FindCallbacks implementation //////////////////////////////// @Override public Object processArgument(Object arg) { return arg; } @Override public Object processReturn(Object oid, OpenJPAStateManager sm) { return (sm == null || sm.isDeleted()) ? null : sm.getManagedInstance(); } ////////////////////////////// // OpCallbacks implementation ////////////////////////////// @Override public int processArgument(int op, Object obj, OpenJPAStateManager sm) { switch (op) { case OP_DELETE: // cascade through non-persistent non-detached instances if (sm == null && !_broker.isDetached(obj)) return ACT_CASCADE; if (sm != null && !sm.isDetached() && !sm.isPersistent()) return ACT_CASCADE; // ignore deleted instances if (sm != null && sm.isDeleted()) return ACT_NONE; break; case OP_ATTACH: // die on removed if (sm != null && sm.isDeleted()) throw new UserException(_loc.get("removed", Exceptions.toString(obj))).setFailedObject(obj); // cascade through managed instances if (sm != null && !sm.isDetached()) return ACT_CASCADE; break; case OP_REFRESH: // die on unmanaged instances if (sm == null) throw new UserException(_loc.get("not-managed", Exceptions.toString(obj))).setFailedObject(obj); break; case OP_DETACH: if (sm == null || !sm.isPersistent() || sm.isDetached()) return ACT_NONE; break; } return ACT_RUN | ACT_CASCADE; } @Override public int hashCode() { return (_broker == null) ? 0 : _broker.hashCode(); } @Override public boolean equals(Object other) { if (other == this) return true; if ((other == null) || (other.getClass() != this.getClass())) return false; if (_broker == null) return false; return _broker.equals(((EntityManagerImpl) other)._broker); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { try { _ret = PersistenceExceptions.getRollbackTranslator(this); // this assumes that serialized Brokers are from something // that extends AbstractBrokerFactory. Object factoryKey = in.readObject(); AbstractBrokerFactory factory = AbstractBrokerFactory.getPooledFactoryForKey(factoryKey); byte[] brokerBytes = (byte[]) in.readObject(); ObjectInputStream innerIn = new BrokerBytesInputStream(brokerBytes, factory.getConfiguration()); Broker broker = (Broker) innerIn.readObject(); EntityManagerFactoryImpl emf = (EntityManagerFactoryImpl) JPAFacadeHelper.toEntityManagerFactory( broker.getBrokerFactory()); broker.putUserObject(JPAFacadeHelper.EM_KEY, this); initialize(emf, broker); } catch (RuntimeException re) { try { re = _ret.translate(re); } catch (Exception e) { // ignore } throw re; } } @Override public void writeExternal(ObjectOutput out) throws IOException { try { // this requires that only AbstractBrokerFactory-sourced // brokers can be serialized Object factoryKey = ((AbstractBrokerFactory) _broker .getBrokerFactory()).getPoolKey(); out.writeObject(factoryKey); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream innerOut = new ObjectOutputStream(baos); _broker.getDelegate().putUserObject(JPAFacadeHelper.EM_KEY, null); innerOut.writeObject(_broker.getDelegate()); innerOut.flush(); out.writeObject(baos.toByteArray()); } catch (RuntimeException re) { try { re = _ret.translate(re); } catch (Exception e) { // ignore } throw re; } } public void setProperties(final Map emEmptyPropsProperties) { this.properties = emEmptyPropsProperties; } private static class BrokerBytesInputStream extends ObjectInputStream { private OpenJPAConfiguration conf; BrokerBytesInputStream(byte[] bytes, OpenJPAConfiguration conf) throws IOException { super(new ByteArrayInputStream(bytes)); if (conf == null) throw new IllegalArgumentException( "Illegal null argument to ObjectInputStreamWithLoader"); this.conf = conf; } /** * Make a primitive array class */ private Class primitiveType(char type) { switch (type) { case 'B': return byte.class; case 'C': return char.class; case 'D': return double.class; case 'F': return float.class; case 'I': return int.class; case 'J': return long.class; case 'S': return short.class; case 'Z': return boolean.class; default: return null; } } @Override protected Class resolveClass(ObjectStreamClass classDesc) throws IOException, ClassNotFoundException { String cname = BlacklistClassResolver.DEFAULT.check(classDesc.getName()); if (cname.startsWith("[")) { // An array Class component; // component class int dcount; // dimension for (dcount=1; cname.charAt(dcount)=='['; dcount++) ; if (cname.charAt(dcount) == 'L') { component = lookupClass(cname.substring(dcount+1, cname.length()-1)); } else { if (cname.length() != dcount+1) { throw new ClassNotFoundException(cname);// malformed } component = primitiveType(cname.charAt(dcount)); } int dim[] = new int[dcount]; for (int i=0; i lookupClass(String className) throws ClassNotFoundException { try { return Class.forName(className); } catch (ClassNotFoundException e) { if (PCEnhancer.isPCSubclassName(className)) { String superName = PCEnhancer.toManagedTypeName(className); ClassMetaData[] metas = conf.getMetaDataRepositoryInstance() .getMetaDatas(); for (ClassMetaData meta : metas) { if (superName.equals( meta.getDescribedType().getName())) { return PCRegistry.getPCType( meta.getDescribedType()); } } // if it's not found, try to look for it anyways return Class.forName(className); } else { throw e; } } } } @Override public void detach(Object entity) { if (entity == null) throw new IllegalArgumentException(_loc.get("null-detach").getMessage()); assertNotCloseInvoked(); _broker.detach(entity, this); } /** * Create a query from the given CritriaQuery. * Compile to register the parameters in this query. */ @Override public TypedQuery createQuery(CriteriaQuery criteriaQuery) { ((OpenJPACriteriaQuery)criteriaQuery).compile(); org.apache.openjpa.kernel.Query kernelQuery =_broker.newQuery(OpenJPACriteriaBuilder.LANG_CRITERIA, criteriaQuery); QueryImpl facadeQuery = newQueryImpl(kernelQuery, null).setId(criteriaQuery.toString()); Set> params = criteriaQuery.getParameters(); for (ParameterExpression param : params) { facadeQuery.declareParameter(param, param); } return facadeQuery; } @Override public Query createQuery(CriteriaUpdate updateQuery) { throw new UnsupportedOperationException("JPA 2.1"); } @Override public Query createQuery(CriteriaDelete deleteQuery) { throw new UnsupportedOperationException("JPA 2.1"); } @Override public OpenJPAQuery createDynamicQuery( org.apache.openjpa.persistence.query.QueryDefinition qdef) { String jpql = _emf.getDynamicQueryBuilder().toJPQL(qdef); return createQuery(jpql); } /** * Get the properties used currently by this entity manager. * The property keys and their values are harvested from kernel artifacts namely * the Broker and FetchPlan by reflection. * These property keys and values that denote the bean properties/values of the kernel artifacts * are converted to the original keys/values that user used to set the properties. * */ @Override public Map getProperties() { if (properties != null) { return properties; } Map props = _broker.getProperties(); for (String s : _broker.getSupportedProperties()) { String kernelKey = getBeanPropertyName(s); Method getter = Reflection.findGetter(this.getClass(), kernelKey, false); if (getter != null) { String userKey = JPAProperties.getUserName(kernelKey); Object kvalue = Reflection.get(this, getter); props.put(userKey.equals(kernelKey) ? s : userKey, JPAProperties.convertToUserValue(userKey, kvalue)); } } FetchPlan fetch = getFetchPlan(); Class fetchType = fetch.getClass(); Set fProperties = Reflection.getBeanStylePropertyNames(fetchType); for (String s : fProperties) { String kernelKey = getBeanPropertyName(s); Method getter = Reflection.findGetter(fetchType, kernelKey, false); if (getter != null) { String userKey = JPAProperties.getUserName(kernelKey); Object kvalue = Reflection.get(fetch, getter); props.put(userKey.equals(kernelKey) ? s : userKey, JPAProperties.convertToUserValue(userKey, kvalue)); } } properties = props; // no need to synchronize, we don't care of the actual ref, we just want it as value return props; } @Override public OpenJPACriteriaBuilder getCriteriaBuilder() { return _emf.getCriteriaBuilder(); } @Override public Set getSupportedProperties() { return _broker.getSupportedProperties(); } /** * Unwraps this receiver to an instance of the given class, if possible. * * @exception if the given class is null, generic Object.class or a class * that is not wrapped by this receiver. */ @Override @SuppressWarnings("unchecked") public T unwrap(Class cls) { if (cls != null && cls != Object.class) { Object[] delegates = new Object[] { _broker.getInnermostDelegate(), _broker.getDelegate(), _broker, this }; for (Object o : delegates) { if (cls.isInstance(o)) return (T) o; } // Only call getConnection() once we are certain that is the type that we need to unwrap. if (cls.isAssignableFrom(Connection.class)) { Object o = getConnection(); if(Connection.class.isInstance(o)){ return (T) o; }else{ // Try and cleanup if aren't going to return the connection back to the caller. ImplHelper.close(o); } } } // Set this transaction to rollback only (as per spec) here because the raised exception // does not go through normal exception translation pathways RuntimeException ex = new PersistenceException(_loc.get("unwrap-em-invalid", cls).toString(), null, this, false); if (isActive()) setRollbackOnly(ex); throw ex; } @Override public void setQuerySQLCache(boolean flag) { _broker.setCachePreparedQuery(flag); } @Override public boolean getQuerySQLCache() { return _broker.getCachePreparedQuery(); } RuntimeExceptionTranslator getExceptionTranslator() { return _ret; } /** * Populate the given FetchPlan with the given properties. * Optionally overrides the given lock mode. */ private void configureCurrentFetchPlan(FetchPlan fetch, Map properties, LockModeType lock, boolean requiresTxn) { // handle properties in map first if (properties != null) { for (Map.Entry entry : properties.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); if (key.equals("javax.persistence.lock.scope")) { fetch.setLockScope((PessimisticLockScope)value); } else fetch.setHint(key, value); } } // override with the specific lockMode, if needed. if (lock != null && lock != LockModeType.NONE) { if (requiresTxn) { _broker.assertActiveTransaction(); } // Override read lock level LockModeType curReadLockMode = fetch.getReadLockMode(); if (lock != curReadLockMode) fetch.setReadLockMode(lock); } } /** * Populate the fetch configuration with specified cache mode properties. * The cache mode properties modify the fetch configuration and remove those * properties. This method should be called before the fetch configuration of the current * context has been pushed. * @param fetch the fetch configuration of the current context. Not the * new configuration pushed (and later popped) during a single operation. * * @param properties */ private void configureCurrentCacheModes(FetchPlan fetch, Map properties) { if (properties == null) return; CacheRetrieveMode rMode = JPAProperties.getEnumValue(CacheRetrieveMode.class, JPAProperties.CACHE_RETRIEVE_MODE, properties); if (rMode != null) { fetch.setCacheRetrieveMode(JPAProperties.convertToKernelValue(DataCacheRetrieveMode.class, JPAProperties.CACHE_RETRIEVE_MODE, rMode)); properties.remove(JPAProperties.CACHE_RETRIEVE_MODE); } CacheStoreMode sMode = JPAProperties.getEnumValue(CacheStoreMode.class, JPAProperties.CACHE_STORE_MODE, properties); if (sMode != null) { fetch.setCacheStoreMode(JPAProperties.convertToKernelValue(DataCacheStoreMode.class, JPAProperties.CACHE_STORE_MODE, sMode)); properties.remove(JPAProperties.CACHE_STORE_MODE); } } @Override public Metamodel getMetamodel() { return _emf.getMetamodel(); } @Override public EntityGraph createEntityGraph(Class rootType) { throw new UnsupportedOperationException("JPA 2.1"); } @Override public EntityGraph createEntityGraph(String graphName) { throw new UnsupportedOperationException("JPA 2.1"); } @Override public EntityGraph getEntityGraph(String graphName) { throw new UnsupportedOperationException("JPA 2.1"); } @Override public List> getEntityGraphs(Class entityClass) { throw new UnsupportedOperationException("JPA 2.1"); } /** * Sets the given property to the given value, reflectively. * * The property key is transposed to a bean-style property. * The value is converted to a type consumable by the kernel. * After requisite transformation, if the value can not be set * on either this instance or its fetch plan by reflection, * then an warning message (not an exception as per JPA specification) is issued. */ @Override public void setProperty(String prop, Object value) { properties = null; if (!setKernelProperty(this, prop, value)) { if (!setKernelProperty(this.getFetchPlan(), prop, value)) { Log log = getConfiguration().getLog(OpenJPAConfiguration.LOG_RUNTIME); if (log.isWarnEnabled()) { log.warn(_loc.get("ignored-em-prop", prop, value == null ? "" : value.getClass()+":" + value)); } } } } /** * Attempt to set the given property and value to the given target instance. * The original property is transposed to a bean-style property name. * The original value is transformed to a type consumable by the target. * * @return if the property can be set to the given target. */ private boolean setKernelProperty(Object target, String original, Object value) { String beanProp = getBeanPropertyName(original); JPAProperties.record(beanProp, original); Class kType = null; Object kValue = null; Method setter = Reflection.findSetter(target.getClass(), beanProp, false); if (setter != null) { kType = setter.getParameterTypes()[0]; kValue = convertUserValue(original, value, kType); Reflection.set(target, setter, kValue); properties = null; return true; } else { Field field = Reflection.findField(target.getClass(), beanProp, false); if (field != null) { kType = field.getType(); kValue = convertUserValue(original, value, kType); Reflection.set(target, field, kValue); properties = null; return true; } } return false; } /** * Extract a bean-style property name from the given string. * If the given string is "a.b.xyz" then returns "xyz" */ String getBeanPropertyName(String user) { String result = user; if (JPAProperties.isValidKey(user)) { result = JPAProperties.getBeanProperty(user); } else { int dot = user.lastIndexOf('.'); if (dot != -1) result = user.substring(dot+1); } return result; } /** * Convert the given value to a value consumable by OpenJPA kernel constructs. */ Object convertUserValue(String key, Object value, Class targetType) { if (JPAProperties.isValidKey(key)) return JPAProperties.convertToKernelValue(targetType, key, value); if (value instanceof String) { if ("null".equals(value)) { return null; } else { String val = (String) value; int parenIndex = val.indexOf('('); if (!String.class.equals(targetType) && (parenIndex > 0)) { val = val.substring(0, parenIndex); } return StringUtil.parse(val, targetType); } } else if (value instanceof AutoDetachType) { EnumSet autoDetachFlags = EnumSet.noneOf(AutoDetachType.class); autoDetachFlags.add((AutoDetachType)value); return autoDetachFlags; } else if (value instanceof AutoDetachType[]) { EnumSet autoDetachFlags = EnumSet.noneOf(AutoDetachType.class); autoDetachFlags.addAll(Arrays.asList((AutoDetachType[])value)); return autoDetachFlags; } return value; } private Map cloneProperties(Map properties) { if (properties != null) { properties = new HashMap<>(properties); } return properties; } private QueryMetaData getQueryMetadata(String name) { MetaDataRepository repos = _broker.getConfiguration().getMetaDataRepositoryInstance(); QueryMetaData meta = repos.getQueryMetaData(null, name, _broker.getClassLoader(), true); if (meta == null) { throw new RuntimeException("No query named [" + name + "]"); } return meta; } }




  • © 2015 - 2024 Weber Informatics LLC | Privacy Policy