blob: 9359ec07e1ad843256a67f6fa8385cb5470560c2 [file] [log] [blame]
/**
* 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.aries.ejb.openejb.extender;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import org.apache.aries.jpa.container.context.JTAPersistenceContextManager;
import org.apache.aries.util.tracker.SingleServiceTracker;
import org.apache.aries.util.tracker.SingleServiceTracker.SingleServiceListener;
import org.apache.openejb.persistence.EntityManagerTxKey;
import org.apache.openejb.persistence.JtaEntityManagerRegistry;
import org.osgi.framework.BundleContext;
public class AriesPersistenceContextIntegration extends
JtaEntityManagerRegistry {
private static final AtomicReference<AriesPersistenceContextIntegration> INSTANCE =
new AtomicReference<AriesPersistenceContextIntegration>();
private final SingleServiceTracker<JTAPersistenceContextManager> ariesJTARegistry;
private AriesPersistenceContextIntegration(BundleContext ctx) {
super(OSGiTransactionManager.get());
ariesJTARegistry = new SingleServiceTracker<JTAPersistenceContextManager>
(ctx, JTAPersistenceContextManager.class, new DummySingleServiceListener());
ariesJTARegistry.open();
}
public static void init(BundleContext ctx) {
AriesPersistenceContextIntegration apci = new AriesPersistenceContextIntegration(ctx);
if(!!!INSTANCE.compareAndSet(null, apci))
apci.destroy();
}
public static AriesPersistenceContextIntegration get() {
return INSTANCE.get();
}
public void destroy() {
INSTANCE.set(null);
ariesJTARegistry.close();
}
@Override
public EntityManager getEntityManager(EntityManagerFactory emf, Map props,
boolean extended, String unitName) throws IllegalStateException {
if(!!!isTransactionActive())
return super.getEntityManager(emf, props, extended, unitName);
JTAPersistenceContextManager mgr = ariesJTARegistry.getService();
if(mgr == null)
throw new IllegalStateException("No JTAPersistenceContextManager service available");
//Check if we, or OpenEJB, already have a context
EntityManager ariesEM = mgr.getExistingPersistenceContext(emf);
EntityManager openEjbEM = (EntityManager) OSGiTransactionManager.get().
getResource(new EntityManagerTxKey(emf));
if(ariesEM == null) {
if(openEjbEM == null) {
//If both are null then it's easier to let OpenEJB win and push the PC into Aries
openEjbEM = super.getEntityManager(emf, props, extended, unitName);
}
mgr.manageExistingPersistenceContext(emf, openEjbEM);
ariesEM = openEjbEM;
} else {
//We have an Aries EM, if OpenEJB doesn't then sort it out, if it does they should be the same
if(openEjbEM == null){
if(extended) {
throw new IllegalStateException("We already have an active TX scope PersistenceContext, so we can't" +
"create an extended one");
} else {
OSGiTransactionManager.get().putResource(new EntityManagerTxKey(emf), ariesEM);
openEjbEM = ariesEM;
}
} else {
//If both non null and not equal then something bad has happened
if(openEjbEM != ariesEM) {
throw new IllegalStateException("OpenEJB has been cheating. They have a different EntityManager to Aries");
}
}
}
//We could return either ariesEM or openEjbEM at this point
return ariesEM;
}
private static final class DummySingleServiceListener implements SingleServiceListener {
public void serviceFound() {}
public void serviceLost() {}
public void serviceReplaced() {}
}
}