/*
* Copyright 2004-2009 the original author or authors.
*
* Licensed 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.compass.gps.device.jpa.extractor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.compass.core.util.ClassUtils;
import org.compass.gps.device.jpa.JpaGpsDeviceException;
/**
* @author kimchy
*/
public abstract class NativeJpaHelper {
private static final Log log = LogFactory.getLog(NativeJpaHelper.class);
private static final NativeJpaExtractor[] extractors;
static {
ArrayList<NativeJpaExtractor> extractorsList = new ArrayList<NativeJpaExtractor>();
try {
ClassUtils.forName("org.springframework.orm.jpa.EntityManagerFactoryInfo", NativeJpaHelper.class.getClassLoader());
extractorsList.add(new SpringNativeJpaExtractor());
} catch (ClassNotFoundException e) {
// not in classpath
} catch (Throwable t) {
log.warn("Faiiled to regsiter Spring native JPA extractor", t);
}
try {
ClassUtils.forName("org.apache.openejb.persistence.JtaEntityManager", NativeJpaHelper.class.getClassLoader());
extractorsList.add(new OpenEjbNativeJpaExtractor());
} catch (ClassNotFoundException e) {
// not in classpath
} catch (Throwable t) {
log.warn("Faiiled to regsiter OpenEJB native JPA extractor", t);
}
try {
ClassUtils.forName("org.jboss.ejb3.entity.InjectedEntityManagerFactory", NativeJpaHelper.class.getClassLoader());
extractorsList.add(new JBossNativeJpaExtractor());
} catch (ClassNotFoundException e) {
// not in classpath
} catch (Throwable t) {
log.warn("Faiiled to regsiter JBoss native JPA extractor", t);
}
try {
ClassUtils.forName("com.sun.enterprise.util.EntityManagerFactoryWrapper", NativeJpaHelper.class.getClassLoader());
extractorsList.add(new GlassfishNativeHibernateJpaExtractor());
} catch (ClassNotFoundException e) {
// not in classpath
} catch (Throwable t) {
log.warn("Faiiled to regsiter Glassfish native JPA extractor", t);
}
extractors = extractorsList.toArray(new NativeJpaExtractor[extractorsList.size()]);
if (log.isDebugEnabled()) {
log.debug("Using native JPA extractors " + Arrays.toString(extractors));
}
}
public static interface NativeJpaCallback<T> {
T onHibernate();
T onTopLinkEssentials();
T onOpenJPA();
T onEclipseLink();
T onUnknown();
}
public static <T> T detectNativeJpa(EntityManagerFactory emf, NativeJpaCallback<T> callback) throws JpaGpsDeviceException {
EntityManagerFactory nativeEmf = extractNativeJpa(emf);
Set interfaces = ClassUtils.getAllInterfacesAsSet(nativeEmf);
Set<String> interfacesAsStrings = new HashSet<String>();
for (Object anInterface : interfaces) {
interfacesAsStrings.add(((Class) anInterface).getName());
}
interfacesAsStrings.add(nativeEmf.getClass().getName());
T retVal;
if (interfacesAsStrings.contains("org.hibernate.ejb.HibernateEntityManagerFactory")) {
retVal = callback.onHibernate();
} else if (interfacesAsStrings.contains("oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerFactoryImpl")) {
retVal = callback.onTopLinkEssentials();
} else if (interfacesAsStrings.contains("org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl")) {
retVal = callback.onEclipseLink();
} else if (interfacesAsStrings.contains("org.apache.openjpa.persistence.OpenJPAEntityManagerFactory")) {
retVal = callback.onOpenJPA();
} else {
retVal = callback.onUnknown();
}
return retVal;
}
public static EntityManagerFactory extractNativeJpa(EntityManagerFactory emf) {
if (extractors.length == 0) {
return emf;
}
EntityManagerFactory nativeEmf = emf;
do {
emf = nativeEmf;
for (NativeJpaExtractor extractor : extractors) {
nativeEmf = extractor.extractNative(nativeEmf);
}
} while (nativeEmf != emf);
return nativeEmf;
}
public static EntityManager extractNativeJpa(EntityManager em) {
if (extractors.length == 0) {
return em;
}
EntityManager nativeEm = em;
do {
while (true) {
// even though getDelegate should return the actual underlying implementation (Hibernate Session for example)
// some app servers that wrap the EM, actually return the wrapped EM, and not the wrapped EM # getDelegate()
Object delegate = nativeEm.getDelegate();
if (delegate == nativeEm) {
break;
}
if (delegate instanceof EntityManager) {
nativeEm = (EntityManager) delegate;
} else {
break;
}
}
em = nativeEm;
for (NativeJpaExtractor extractor : extractors) {
nativeEm = extractor.extractNative(nativeEm);
}
} while (nativeEm != em);
return nativeEm;
}
}