/*******************************************************************************
* Copyright (c) 1998, 2008 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* tware, ssmith = 1.0 - Initialize Persistence in OSGI
******************************************************************************/
package org.eclipse.persistence.internal.jpa.deployment.osgi;
import java.util.Map;
import java.util.HashMap;
import java.util.Collections;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.internal.jpa.deployment.JPAInitializer;
import org.eclipse.persistence.internal.jpa.deployment.PersistenceInitializationHelper;
import org.eclipse.persistence.internal.localization.LoggingLocalization;
import org.eclipse.persistence.exceptions.EntityManagerSetupException;
import org.osgi.framework.Bundle;
/**
* Overrides the default persistence initialization behavior to allow classloaders to be obtained
* from their appropriate bundle
*
* @see PersistenceInitialization helper
*
* @author tware
*
*/
public class OSGiPersistenceInitializationHelper extends PersistenceInitializationHelper {
private String initializerClassName = null;
public static final String EQUINOX_INITIALIZER_NAME = "org.eclipse.persistence.internal.jpa.deployment.osgi.equinox.EquinoxInitializer";
// these maps are used to retrieve the classloader used for different bundles
private static Map<String, Bundle> puToBundle = Collections.synchronizedMap(new HashMap<String,Bundle>());
private static Map<Bundle, String[]> bundleToPUs = Collections.synchronizedMap(new HashMap<Bundle, String[]>());
/**
* Add a bundle to the list of bundles managed by this persistence provider
* The bundle is indexed so it's classloader can be accessed
* @param bundle
* @param persistenceUnitNames
*/
public static void addBundle(Bundle bundle, String[] persistenceUnitNames) {
for (int i = 0; i < persistenceUnitNames.length; i++) {
String name = persistenceUnitNames[i];
puToBundle.put(name, bundle);
}
bundleToPUs.put(bundle, persistenceUnitNames);
}
/**
* Removed a bundle from the list of bundles managed by this persistence provider
* This typically happens on deactivation.
* @param bundle
*/
public static void removeBundle(Bundle bundle) {
String[] persistenceUnitNames = bundleToPUs.remove(bundle);
if (persistenceUnitNames != null) {
for (int i = 0; i < persistenceUnitNames.length; i++) {
String name = persistenceUnitNames[i];
puToBundle.remove(name);
}
}
}
public OSGiPersistenceInitializationHelper(String initializerClassName){
this.initializerClassName = initializerClassName;
}
/**
* Answer the classloader to use to create an EntityManager.
* If a classloader is not found in the properties map then
* attempt to locate one in the bundle registry.
*
* @param emName
* @param properties
* @return ClassLoader
*/
public ClassLoader getClassLoader(String emName, Map properties) {
ClassLoader bundleClassLoader = null;
if (properties != null) {
bundleClassLoader = (ClassLoader)properties.get(PersistenceUnitProperties.CLASSLOADER);
}
if (bundleClassLoader == null) {
Bundle bundle = puToBundle.get(emName);
if (bundle == null) {
throw EntityManagerSetupException.couldNotFindPersistenceUnitBundle(emName);
}
bundleClassLoader = new BundleProxyClassLoader(bundle);
}
return bundleClassLoader;
}
/**
* Get the initializer class
* Here we will attempt to build an EquinoxInitializer. It will only be available if the org.eclipse.persistence.jpa.equinox
* fragment is available. Else, we will return a standard OSGi initializer
*
*/
public JPAInitializer getInitializer(ClassLoader classLoader, Map m){
if (initializerClassName != null){
try{
// try to build the passed-in initializer. If it is available, we will build it otherwise
// we will assume generic OSGI
Class initializerClass = Class.forName(initializerClassName);
Class[] argTypes = new Class[]{ClassLoader.class, Map.class, PersistenceInitializationHelper.class};
Object[] args = new Object[]{classLoader, m, this};
JPAInitializer initializer = (JPAInitializer)initializerClass.getConstructor(argTypes).newInstance(args);
return initializer;
} catch (Exception e){
AbstractSessionLog.getLog().log(SessionLog.FINEST, LoggingLocalization.buildMessage("osgi_initializer_failed", new Object[]{initializerClassName, e}));
};
}
return new OSGiInitializer(classLoader);
}
}