You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by cs...@apache.org on 2015/05/19 11:47:53 UTC
svn commit: r1680218 [4/5] - in /aries/trunk/jpa: ./ examples/
examples/tasklist-blueprint/ examples/tasklist-blueprint/src/
examples/tasklist-blueprint/src/main/
examples/tasklist-blueprint/src/main/java/
examples/tasklist-blueprint/src/main/java/org/...
Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/DSFTracker.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/DSFTracker.java?rev=1680218&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/DSFTracker.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/DSFTracker.java Tue May 19 09:47:49 2015
@@ -0,0 +1,125 @@
+/*
+ * 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 WARRANTIESOR 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.jpa.container.impl;
+
+import java.sql.SQLException;
+import java.util.Properties;
+
+import javax.persistence.spi.PersistenceProvider;
+import javax.persistence.spi.PersistenceUnitTransactionType;
+import javax.sql.DataSource;
+
+import org.apache.aries.jpa.container.parser.impl.PersistenceUnit;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.jdbc.DataSourceFactory;
+import org.osgi.util.tracker.ServiceTracker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DSFTracker extends ServiceTracker<DataSourceFactory, ManagedEMF>{
+ private static final String JDBC_DRIVER = "javax.persistence.jdbc.driver";
+ private static final String JDBC_URL = "javax.persistence.jdbc.url";
+ private static final String JDBC_USER = "javax.persistence.jdbc.user";
+ private static final String JDBC_PASSWORD = "javax.persistence.jdbc.password";
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DSFTracker.class);
+
+
+ private PersistenceProvider provider;
+ private PersistenceUnit punit;
+
+ public DSFTracker(BundleContext context, PersistenceProvider provider, PersistenceUnit punit) {
+ super(context, createFilter(context, punit), null);
+ this.provider = provider;
+ this.punit = punit;
+ }
+
+ static Filter createFilter(BundleContext context, PersistenceUnit punit) {
+ String driverName = getDriverName(punit);
+ if (driverName == null) {
+ throw new IllegalArgumentException("No javax.persistence.jdbc.driver supplied in persistence.xml");
+ }
+ String filter = String.format("(&(objectClass=%s)(%s=%s))",
+ DataSourceFactory.class.getName(),
+ DataSourceFactory.OSGI_JDBC_DRIVER_CLASS,
+ driverName);
+ LOGGER.info("Tracking DataSourceFactory for punit " + punit.getPersistenceUnitName() + " with filter " + filter);
+ try {
+ return context.createFilter(filter);
+ } catch (InvalidSyntaxException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ public static String getDriverName(PersistenceUnit punit) {
+ return (String)punit.getProperties().get(JDBC_DRIVER);
+ }
+
+ @Override
+ public ManagedEMF addingService(ServiceReference<DataSourceFactory> reference) {
+ LOGGER.info("Found DataSourceFactory for " + punit.getPersistenceUnitName() + " "
+ + getDriverName(punit));
+ try {
+ DataSourceFactory dsf = context.getService(reference);
+ DataSource ds = createDataSource(dsf);
+ if (punit.getTransactionType() == PersistenceUnitTransactionType.JTA) {
+ punit.setJtaDataSource(ds);
+ } else {
+ punit.setNonJtaDataSource(ds);
+ }
+ BundleContext containerContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+ return new ManagedEMF(containerContext, punit.getBundle(), provider, punit);
+ } catch (Exception e) {
+ LOGGER.error("Error creating DataSource for punit " + punit.getPersistenceUnitName(), e);
+ return null;
+ }
+ }
+
+ private DataSource createDataSource(DataSourceFactory dsf) {
+ try {
+ Properties props = new Properties();
+ put(props, DataSourceFactory.JDBC_URL, punit, JDBC_URL);
+ put(props, DataSourceFactory.JDBC_USER, punit, JDBC_USER);
+ put(props, DataSourceFactory.JDBC_PASSWORD, punit, JDBC_PASSWORD);
+ DataSource ds = dsf.createDataSource(props);
+ return ds;
+ } catch (SQLException e) {
+ throw new RuntimeException("Error creating DataSource for persistence unit " + punit + "."
+ + e.getMessage(), e);
+ }
+ }
+
+ private static void put(Properties props, String destKey, PersistenceUnit punit, String sourceKey) {
+ Object value = punit.getProperties().get(sourceKey);
+ if (value != null) {
+ props.put(destKey, value);
+ }
+ }
+
+ @Override
+ public void removedService(ServiceReference<DataSourceFactory> reference, ManagedEMF managedEMF) {
+ LOGGER.info("Lost DataSourceFactory for " + punit.getPersistenceUnitName() + " " + getDriverName(punit));
+ managedEMF.close();
+ super.removedService(reference, managedEMF);
+ }
+}
Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/DataSourceTracker.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/DataSourceTracker.java?rev=1680218&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/DataSourceTracker.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/DataSourceTracker.java Tue May 19 09:47:49 2015
@@ -0,0 +1,103 @@
+/*
+ * 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 WARRANTIESOR 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.jpa.container.impl;
+
+import static javax.persistence.spi.PersistenceUnitTransactionType.JTA;
+
+import javax.persistence.spi.PersistenceProvider;
+import javax.persistence.spi.PersistenceUnitTransactionType;
+import javax.sql.DataSource;
+
+import org.apache.aries.jpa.container.parser.impl.PersistenceUnit;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DataSourceTracker extends ServiceTracker<DataSource, ManagedEMF>{
+ private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceTracker.class);
+
+ private PersistenceProvider provider;
+ private PersistenceUnit punit;
+
+ static final String DS_PREFIX = "osgi:service/javax.sql.DataSource";
+
+ public DataSourceTracker(BundleContext context, PersistenceProvider provider, PersistenceUnit punit) {
+ super(context, createFilter(context, punit), null);
+ this.provider = provider;
+ this.punit = punit;
+ }
+
+ static Filter createFilter(BundleContext context, PersistenceUnit punit) {
+ String dsName = getDsName(punit);
+ if (dsName == null) {
+ throw new IllegalArgumentException("No DataSource supplied in persistence.xml");
+ }
+ String subFilter = getSubFilter(dsName);
+ String filter = String.format("(&(objectClass=%s)%s)",
+ DataSource.class.getName(),
+ subFilter);
+ LOGGER.info("Tracking DataSource for punit " + punit.getPersistenceUnitName() + " with filter " + filter);
+ try {
+ return context.createFilter(filter);
+ } catch (InvalidSyntaxException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ private static String getSubFilter(String dsName) {
+ if (dsName.startsWith(DS_PREFIX)) {
+ return (dsName.length() > DS_PREFIX.length() +1)
+ ? dsName.substring(DS_PREFIX.length()+1)
+ : "(osgi.jndi.service.name=*)";
+ } else {
+ return "(osgi.jndi.service.name=" + dsName + ")";
+ }
+ }
+
+ private static String getDsName(PersistenceUnit punit) {
+ return punit.getTransactionType() == JTA ? punit.getJtaDataSourceName() : punit.getNonJtaDataSourceName();
+ }
+
+ @Override
+ public ManagedEMF addingService(ServiceReference<DataSource> reference) {
+ LOGGER.info("Found DataSource for " + punit.getPersistenceUnitName() + " " + getDsName(punit));
+ DataSource ds = context.getService(reference);
+ if (punit.getTransactionType() == PersistenceUnitTransactionType.JTA) {
+ punit.setJtaDataSource(ds);
+ } else {
+ punit.setNonJtaDataSource(ds);
+ }
+ BundleContext containerContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+ return new ManagedEMF(containerContext, punit.getBundle(), provider, punit);
+ }
+
+
+ @Override
+ public void removedService(ServiceReference<DataSource> reference, ManagedEMF managedEMF) {
+ LOGGER.info("Lost DataSource for " + punit.getPersistenceUnitName() + " " + getDsName(punit));
+ managedEMF.close();
+ super.removedService(reference, managedEMF);
+ }
+
+}
Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/ManagedEMF.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/ManagedEMF.java?rev=1680218&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/ManagedEMF.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/ManagedEMF.java Tue May 19 09:47:49 2015
@@ -0,0 +1,133 @@
+/*
+ * 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 WARRANTIESOR 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.jpa.container.impl;
+
+import static org.osgi.service.jpa.EntityManagerFactoryBuilder.JPA_UNIT_NAME;
+import static org.osgi.service.jpa.EntityManagerFactoryBuilder.JPA_UNIT_PROVIDER;
+import static org.osgi.service.jpa.EntityManagerFactoryBuilder.JPA_UNIT_VERSION;
+
+import java.io.Closeable;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.spi.PersistenceProvider;
+import javax.persistence.spi.PersistenceUnitInfo;
+import javax.persistence.spi.PersistenceUnitTransactionType;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.jpa.EntityManagerFactoryBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Creates an EntityManagerFactory(EMF) for a persistence unit and publishes it as a service.
+ * Custom properties can be configured by supplying a config admin configuriation named like
+ * the JPA_CONFIGURATION_PREFIX.<persistence unit name>.
+ */
+public class ManagedEMF implements Closeable, ManagedService {
+ private static final Logger LOGGER = LoggerFactory.getLogger(ManagedEMF.class);
+
+ private static String JPA_CONFIGURATION_PREFIX = "org.apache.aries.jpa.";
+
+ private EntityManagerFactory emf;
+ private ServiceRegistration<EntityManagerFactory> reg;
+ private ServiceRegistration<EntityManagerFactoryBuilder> regBuilder;
+ private PersistenceProvider provider;
+ private PersistenceUnitInfo persistenceUnit;
+ private Bundle bundle;
+
+ public ManagedEMF(BundleContext containerContext, Bundle bundle, PersistenceProvider provider, PersistenceUnitInfo persistenceUnit) {
+ this.provider = provider;
+ this.persistenceUnit = persistenceUnit;
+ this.bundle = bundle;
+
+ Dictionary<String, Object> configuration = new Hashtable<String, Object>();
+ configuration.put(Constants.SERVICE_PID,
+ JPA_CONFIGURATION_PREFIX + persistenceUnit.getPersistenceUnitName());
+ containerContext.registerService(ManagedService.class.getName(), this, configuration);
+ }
+
+ public void close() {
+ try {
+ reg.unregister();
+ } catch (Exception e) {
+ // Ignore. May happen if persistence unit bundle is unloaded/updated
+ }
+ try {
+ regBuilder.unregister();
+ } catch (Exception e) {
+ // Ignore. May happen if persistence unit bundle is unloaded/updated
+ }
+ if (emf != null) {
+ try {
+ emf.close();
+ } catch (Exception e) {
+ LOGGER.warn("EntityManagerFactory for " + persistenceUnit.getPersistenceUnitName() + " already close", e);
+ }
+ }
+ reg = null;
+ emf = null;
+ }
+
+ @Override
+ public void updated(Dictionary<String, ?> properties) throws ConfigurationException {
+ if (emf != null) {
+ close();
+ }
+ Map<String, Object> overrides = (properties != null) ? asMap(properties) : null;
+ LOGGER.info("Registering EntityManagerFactory for persistence unit " + persistenceUnit.getPersistenceUnitName());
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Using properties override " + overrides);
+ }
+ emf = provider.createContainerEntityManagerFactory(persistenceUnit, overrides);
+ Dictionary<String, String> props = createProperties(persistenceUnit, bundle);
+ BundleContext uctx = bundle.getBundleContext();
+ reg = uctx.registerService(EntityManagerFactory.class, emf, props);
+ }
+
+ public static Dictionary<String, String> createProperties(PersistenceUnitInfo persistenceUnit, Bundle puBundle) {
+ Dictionary<String, String> props = new Hashtable<>();
+ props.put(JPA_UNIT_NAME, persistenceUnit.getPersistenceUnitName());
+ if (persistenceUnit.getPersistenceProviderClassName() != null) {
+ props.put(JPA_UNIT_PROVIDER, persistenceUnit.getPersistenceProviderClassName());
+ }
+ props.put(JPA_UNIT_VERSION, puBundle.getVersion().toString());
+ return props;
+ }
+
+ private Map<String, Object> asMap(Dictionary<String, ?> dict) {
+ Map<String, Object> map = new HashMap<String, Object>();
+ map.put(PersistenceUnitTransactionType.class.getName(), persistenceUnit.getTransactionType());
+ for (Enumeration<String> e = dict.keys(); e.hasMoreElements();) {
+ String key = e.nextElement();
+ map.put(key, dict.get(key));
+ }
+ return map;
+ }
+
+}
Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/PersistenceBundleTracker.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/PersistenceBundleTracker.java?rev=1680218&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/PersistenceBundleTracker.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/PersistenceBundleTracker.java Tue May 19 09:47:49 2015
@@ -0,0 +1,136 @@
+/*
+ * 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 WARRANTIESOR 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.jpa.container.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.aries.jpa.container.parser.impl.PersistenceUnit;
+import org.apache.aries.jpa.container.parser.impl.PersistenceUnitParser;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Looks for bundles containing a persistence.xml. For each persistence unit
+ * found a PersistenceProviderTracker is installed that tracks matching providers.
+ */
+@SuppressWarnings("deprecation")
+public class PersistenceBundleTracker implements BundleTrackerCustomizer<Bundle> {
+ private static final Logger LOGGER = LoggerFactory.getLogger(PersistenceBundleTracker.class);
+ Map<Bundle, Collection<PersistenceProviderTracker>> trackers;
+ private BundleContext context;
+
+ public PersistenceBundleTracker(BundleContext context) {
+ this.context = context;
+ trackers = new HashMap<Bundle, Collection<PersistenceProviderTracker>>();
+ }
+
+ public Bundle addingBundle(Bundle bundle, BundleEvent event) {
+ if (getTrackers(bundle).size() == 0) {
+ findPersistenceUnits(bundle);
+ }
+ return bundle;
+ }
+
+ public void removedBundle(Bundle bundle, BundleEvent event, Bundle object) {
+ Collection<PersistenceProviderTracker> providerTrackers = trackers.get(bundle);
+ if (providerTrackers != null) {
+ if (providerTrackers.size() > 0) {
+ LOGGER.info("removing persistence units for " + bundle.getSymbolicName() + " " + getType(event));
+ }
+ for (PersistenceProviderTracker providerTracker : providerTrackers) {
+ providerTracker.close();
+ }
+ providerTrackers.clear();
+ trackers.remove(bundle);
+ }
+ }
+
+ private void findPersistenceUnits(Bundle bundle) {
+ ServiceReference<PackageAdmin> ref = context.getServiceReference(PackageAdmin.class);
+ PackageAdmin packageAdmin = context.getService(ref);
+ for (PersistenceUnit punit : PersistenceUnitParser.getPersistenceUnits(bundle)) {
+ punit.addAnnotated(packageAdmin);
+ trackProvider(bundle, punit);
+ }
+ context.ungetService(ref);
+ }
+
+ private void trackProvider(Bundle bundle,
+ PersistenceUnit punit) {
+ LOGGER.info(String.format("Found persistence unit %s in bundle %s with provider %s.",
+ punit.getPersistenceUnitName(), bundle.getSymbolicName(),
+ punit.getPersistenceProviderClassName()));
+ PersistenceProviderTracker tracker = new PersistenceProviderTracker(context, punit);
+ tracker.open();
+ getTrackers(bundle).add(tracker);
+ }
+
+ @Override
+ public void modifiedBundle(Bundle bundle, BundleEvent event, Bundle object) {
+ }
+
+ private static String getType(BundleEvent event) {
+ if (event == null) {
+ return "null";
+ }
+ int type = event.getType();
+ switch (type) {
+ case BundleEvent.INSTALLED:
+ return "INSTALLED";
+ case BundleEvent.LAZY_ACTIVATION:
+ return "LAZY_ACTIVATION";
+ case BundleEvent.RESOLVED:
+ return "RESOLVED";
+ case BundleEvent.STARTED:
+ return "STARTED";
+ case BundleEvent.STARTING:
+ return "Starting";
+ case BundleEvent.STOPPED:
+ return "STOPPED";
+ case BundleEvent.UNINSTALLED:
+ return "UNINSTALLED";
+ case BundleEvent.UNRESOLVED:
+ return "UNRESOLVED";
+ case BundleEvent.UPDATED:
+ return "UPDATED";
+ default:
+ return "unknown event type: " + type;
+ }
+ }
+
+ private Collection<PersistenceProviderTracker> getTrackers(Bundle bundle) {
+ Collection<PersistenceProviderTracker> providerTrackers = trackers.get(bundle);
+ if (providerTrackers == null) {
+ providerTrackers = new ArrayList<>();
+ trackers.put(bundle, providerTrackers);
+ }
+ return providerTrackers;
+ }
+
+}
Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/PersistenceProviderTracker.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/PersistenceProviderTracker.java?rev=1680218&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/PersistenceProviderTracker.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/PersistenceProviderTracker.java Tue May 19 09:47:49 2015
@@ -0,0 +1,156 @@
+/*
+ * 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 WARRANTIESOR 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.jpa.container.impl;
+
+import java.util.Dictionary;
+
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.spi.PersistenceProvider;
+import javax.sql.DataSource;
+
+import org.apache.aries.jpa.container.parser.impl.PersistenceUnit;
+import org.apache.aries.jpa.container.weaving.impl.DummyDataSource;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.jpa.EntityManagerFactoryBuilder;
+import org.osgi.util.tracker.ServiceTracker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Tracks matching persistence providers for a persistence unit.
+ * If a provider is found:
+ * - an EntityManagerFactoryBuilder is installed
+ * - A DataSourceTracker is installed if the JtaDataSource refers to an OSGi service
+ */
+public class PersistenceProviderTracker extends ServiceTracker<PersistenceProvider, StoredPerProvider> {
+ private static final String JAVAX_PERSISTENCE_PROVIDER = "javax.persistence.provider";
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(PersistenceProviderTracker.class);
+
+ private PersistenceUnit punit;
+
+ public PersistenceProviderTracker(BundleContext context, PersistenceUnit punit) {
+ super(context, createFilter(context, punit), null);
+ this.punit = punit;
+ }
+
+ private static Filter createFilter(BundleContext context, PersistenceUnit punit) {
+ String filter = null;
+ if (punit.getPersistenceProviderClassName() != null) {
+ filter = String.format("(&(objectClass=%s)(%s=%s))",
+ PersistenceProvider.class.getName(),
+ JAVAX_PERSISTENCE_PROVIDER,
+ punit.getPersistenceProviderClassName());
+ } else {
+ filter = String.format("(objectClass=%s)", PersistenceProvider.class.getName());
+ }
+
+ try {
+ return context.createFilter(filter);
+ } catch (InvalidSyntaxException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ @Override
+ public StoredPerProvider addingService(ServiceReference<PersistenceProvider> reference) {
+ String providerName = (String)reference.getProperty(JAVAX_PERSISTENCE_PROVIDER);
+ // FIXME should be set when creating the EMF was successful
+ if (punit.getPersistenceProviderClassName() == null) {
+ punit.setProviderClassName(providerName);
+ }
+ StoredPerProvider stored = new StoredPerProvider();
+ LOGGER.info("Found provider for " + punit.getPersistenceUnitName() + " " + punit.getPersistenceProviderClassName());
+ PersistenceProvider provider = context.getService(reference);
+
+ createAndCloseDummyEMF(provider);
+
+ stored.dsTracker = createDataSourceTracker(stored, provider, providerName);
+ EntityManagerFactoryBuilder emfBuilder = new AriesEntityManagerFactoryBuilder(provider, punit);
+ Dictionary<String, ?> props = ManagedEMF.createProperties(punit, punit.getBundle());
+ stored.reg = context.registerService(EntityManagerFactoryBuilder.class, emfBuilder , props);
+ return stored;
+ }
+
+ /**
+ * Create and close a dummy EMF to give the PersistenceProvider a chance to call
+ * punit.addTransformer(). This has to occur as early as possible as weaving needs
+ * to be done before the first entity class is loaded. So we can not wait till the
+ * real DataSource is found.
+ */
+ private void createAndCloseDummyEMF(PersistenceProvider provider) {
+ DataSource dummyDataSource = new DummyDataSource();
+ punit.setJtaDataSource(dummyDataSource);
+ punit.setNonJtaDataSource(dummyDataSource);
+ try {
+ EntityManagerFactory emf = provider.createContainerEntityManagerFactory(punit, null);
+ emf.close();
+ } catch (Exception e) {
+ LOGGER.warn(e.getMessage(), e);
+ }
+ punit.setJtaDataSource(null);
+ punit.setNonJtaDataSource(null);
+ }
+
+ private ServiceTracker<?, ?> createDataSourceTracker(StoredPerProvider stored, PersistenceProvider provider, String providerName) {
+ if (usesDataSource()) {
+ if (!usesDataSourceService()) {
+ LOGGER.warn("Persistence unit " + punit.getPersistenceUnitName() + " refers to a non OSGi service DataSource");
+ return null;
+ }
+ DataSourceTracker dsTracker = new DataSourceTracker(context, provider, punit);
+ dsTracker.open();
+ return dsTracker;
+ } else if (usesDSF()) {
+ DSFTracker dsfTracker = new DSFTracker(context, provider, punit);
+ dsfTracker.open();
+ return dsfTracker;
+ } else {
+ LOGGER.debug("Persistence unit " + punit.getPersistenceUnitName() + " does not refer a DataSource. "
+ +"It can only be used with EntityManagerFactoryBuilder.");
+ return null;
+ }
+ }
+
+ private boolean usesDataSource() {
+ return punit.getJtaDataSourceName() != null || punit.getNonJtaDataSourceName() != null;
+ }
+
+ private boolean usesDSF() {
+ return DSFTracker.getDriverName(punit) != null;
+ }
+
+ private boolean usesDataSourceService() {
+ return punit.getJtaDataSourceName() != null && punit.getJtaDataSourceName().startsWith(DataSourceTracker.DS_PREFIX)
+ || punit.getNonJtaDataSourceName() != null && punit.getNonJtaDataSourceName().startsWith(DataSourceTracker.DS_PREFIX);
+ }
+
+ @Override
+ public void removedService(ServiceReference<PersistenceProvider> reference, StoredPerProvider stored) {
+ LOGGER.info("Lost provider for " + punit.getPersistenceUnitName() + " " + punit.getPersistenceProviderClassName());
+ if (stored.dsTracker != null) {
+ stored.dsTracker.close();
+ }
+ stored.reg.unregister();
+ super.removedService(reference, stored);
+ }
+}
Copied: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/StoredPerProvider.java (from r1680054, aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/InvalidPersistenceUnitException.java)
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/StoredPerProvider.java?p2=aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/StoredPerProvider.java&p1=aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/InvalidPersistenceUnitException.java&r1=1680054&r2=1680218&rev=1680218&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/InvalidPersistenceUnitException.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/StoredPerProvider.java Tue May 19 09:47:49 2015
@@ -18,22 +18,11 @@
*/
package org.apache.aries.jpa.container.impl;
-/**
- * This exception is thrown if an {@link EntityManagerFactoryManager} has
- * entered an invalid state and needs to be destroyed
- */
-public class InvalidPersistenceUnitException extends Exception {
-
- /**
- * For serialization
- */
- private static final long serialVersionUID = 6523462131213055375L;
-
- public InvalidPersistenceUnitException(Exception e) {
- super(e);
- }
-
- public InvalidPersistenceUnitException() {
- }
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.jpa.EntityManagerFactoryBuilder;
+import org.osgi.util.tracker.ServiceTracker;
-}
+public class StoredPerProvider {
+ ServiceTracker<?, ?> dsTracker;
+ ServiceRegistration<EntityManagerFactoryBuilder> reg;
+}
\ No newline at end of file
Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/JPAAnnotationScanner.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/JPAAnnotationScanner.java?rev=1680218&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/JPAAnnotationScanner.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/JPAAnnotationScanner.java Tue May 19 09:47:49 2015
@@ -0,0 +1,59 @@
+/*
+ * 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 WARRANTIESOR 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.jpa.container.parser.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javax.persistence.Embeddable;
+import javax.persistence.Entity;
+import javax.persistence.MappedSuperclass;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.wiring.BundleWiring;
+
+@SuppressWarnings("deprecation")
+class JPAAnnotationScanner {
+ public static Collection<String> findJPAAnnotatedClasses(Bundle b) {
+ BundleWiring bw = b.adapt(BundleWiring.class);
+ Collection<String> resources = bw.listResources("/", "*.class",
+ BundleWiring.LISTRESOURCES_LOCAL | BundleWiring.LISTRESOURCES_RECURSE);
+
+ Collection<String> classes = new ArrayList<String>();
+ ClassLoader cl = new TempBundleDelegatingClassLoader(b, JPAAnnotationScanner.class.getClassLoader());
+ for(String s : resources) {
+ s = s.replace('/', '.').substring(0, s.length() - 6);
+ try {
+ Class<?> clazz = Class.forName(s, false, cl);
+
+ if(clazz.isAnnotationPresent(Entity.class) ||
+ clazz.isAnnotationPresent(MappedSuperclass.class) ||
+ clazz.isAnnotationPresent(Embeddable.class)) {
+ classes.add(s);
+ }
+
+ } catch (ClassNotFoundException cnfe) {
+
+ } catch (NoClassDefFoundError ncdfe) {
+
+ }
+ }
+ return classes;
+ }
+}
Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/JPAAnnotationScannerXbean.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/JPAAnnotationScannerXbean.java?rev=1680218&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/JPAAnnotationScannerXbean.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/JPAAnnotationScannerXbean.java Tue May 19 09:47:49 2015
@@ -0,0 +1,60 @@
+/*
+ * 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 WARRANTIESOR 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.jpa.container.parser.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Embeddable;
+import javax.persistence.Entity;
+import javax.persistence.MappedSuperclass;
+
+import org.apache.xbean.finder.Annotated;
+import org.apache.xbean.finder.BundleAnnotationFinder;
+import org.osgi.framework.Bundle;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings("deprecation")
+class JPAAnnotationScannerXbean {
+ private static Logger LOGGER = LoggerFactory.getLogger(JPAAnnotationScannerXbean.class);
+
+ public static Collection<String> findJPAAnnotatedClasses(Bundle bundle, PackageAdmin packageAdmin) {
+ Collection<String> classes = new ArrayList<String>();
+ try {
+ BundleAnnotationFinder finder = new BundleAnnotationFinder(packageAdmin, bundle);
+ Set<Annotated<Class<?>>> annotatedSet = new HashSet<Annotated<Class<?>>>();
+ annotatedSet.addAll(finder.findMetaAnnotatedClasses(Entity.class));
+ annotatedSet.addAll(finder.findMetaAnnotatedClasses(MappedSuperclass.class));
+ annotatedSet.addAll(finder.findMetaAnnotatedClasses(Embeddable.class));
+ LOGGER.info("Searching for entities");
+ for (Annotated<Class<?>> annotated : annotatedSet) {
+ LOGGER.info("Found entity " + annotated.get().getName());
+ classes.add(annotated.get().getName());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return classes;
+ }
+
+}
\ No newline at end of file
Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/JPAHandler.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/JPAHandler.java?rev=1680218&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/JPAHandler.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/JPAHandler.java Tue May 19 09:47:49 2015
@@ -0,0 +1,127 @@
+/*
+ * 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 WARRANTIESOR 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.jpa.container.parser.impl;
+
+import java.util.Collection;
+import java.util.Stack;
+
+import javax.persistence.SharedCacheMode;
+import javax.persistence.ValidationMode;
+import javax.persistence.spi.PersistenceUnitTransactionType;
+
+import org.osgi.framework.Bundle;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * This code is responsible for parsing the persistence.xml into PersistenceUnits
+ */
+public class JPAHandler extends DefaultHandler {
+ /** The Persistence Units that we have parsed */
+ private final Stack<PersistenceUnit> persistenceUnits = new Stack<PersistenceUnit>();
+ /** The name of the current element */
+ private String elementName;
+ /** The version of the persistence.xml file */
+ /** A StringBuilder for caching the information from getCharacters */
+ private StringBuilder builder = new StringBuilder();
+ /** The bundle that contains this persistence descriptor */
+ private Bundle bundle;
+
+ /**
+ * Create a new JPA Handler for a bundle
+ *
+ * @param bundle
+ */
+ public JPAHandler(Bundle bundle) {
+ this.bundle = bundle;
+ }
+
+ /**
+ * Collect up the characters, as element's characters may be split across multiple calls. Isn't SAX
+ * lovely...
+ */
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ builder.append(ch, start, length);
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String name, Attributes attributes)
+ throws SAXException {
+ // Do this setting first as we use it later.
+ elementName = (localName == null || "".equals(localName)) ? name : localName;
+
+ if ("persistence-unit".equals(elementName)) {
+ String tranTypeSt = attributes.getValue("transaction-type");
+ PersistenceUnitTransactionType tranType = tranTypeSt == null ? null : PersistenceUnitTransactionType.valueOf(tranTypeSt);
+ persistenceUnits.push(new PersistenceUnit(bundle,
+ attributes.getValue("name"),
+ tranType));
+ } else if ("exclude-unlisted-classes".equals(elementName))
+ persistenceUnits.peek().setExcludeUnlisted(true);
+ else if ("property".equals(elementName))
+ persistenceUnits.peek().addProperty(attributes.getValue("name"), attributes.getValue("value"));
+
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String name) throws SAXException {
+ String s = builder.toString().trim();
+ // This step is VERY important, otherwise we pollute subsequent
+ // elements
+ builder = new StringBuilder();
+
+ if ("".equals(s))
+ return;
+
+ PersistenceUnit pu = persistenceUnits.peek();
+
+ if ("provider".equals(elementName))
+ pu.setProviderClassName(s);
+ else if ("jta-data-source".equals(elementName))
+ pu.setJtaDataSourceName(s);
+ else if ("non-jta-data-source".equals(elementName))
+ pu.setNonJtaDataSourceName(s);
+ else if ("class".equals(elementName))
+ pu.addClassName(s);
+ else if ("exclude-unlisted-classes".equals(elementName))
+ pu.setExcludeUnlisted(Boolean.parseBoolean(s));
+ else if ("shared-cache-mode".equals(elementName))
+ pu.setSharedCacheMode(SharedCacheMode.valueOf(s));
+ else if ("validation-mode".equals(elementName))
+ pu.setValidationMode(ValidationMode.valueOf(s));
+ }
+
+ @Override
+ public void error(SAXParseException spe) throws SAXException {
+ // We throw this exception to be caught further up and logged
+ // as an error there
+ throw spe;
+ }
+
+ /**
+ * @return The collection of persistence units that we have parsed
+ */
+ public Collection<PersistenceUnit> getPersistenceUnits() {
+ return persistenceUnits;
+ }
+
+}
Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/PersistenceUnit.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/PersistenceUnit.java?rev=1680218&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/PersistenceUnit.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/PersistenceUnit.java Tue May 19 09:47:49 2015
@@ -0,0 +1,229 @@
+/*
+ * 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 WARRANTIESOR 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.jpa.container.parser.impl;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.persistence.SharedCacheMode;
+import javax.persistence.ValidationMode;
+import javax.persistence.spi.ClassTransformer;
+import javax.persistence.spi.PersistenceUnitInfo;
+import javax.persistence.spi.PersistenceUnitTransactionType;
+import javax.sql.DataSource;
+
+import org.apache.aries.jpa.container.weaving.impl.TransformerRegistry;
+import org.apache.aries.jpa.container.weaving.impl.TransformerRegistrySingleton;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.wiring.BundleWiring;
+import org.osgi.service.packageadmin.PackageAdmin;
+
+public class PersistenceUnit implements PersistenceUnitInfo {
+
+ private Bundle bundle;
+ private ClassLoader classLoader;
+ private Set<String> classNames;
+ private boolean excludeUnlisted;
+ private DataSource jtaDataSource;
+ private String jtaDataSourceName;
+ private DataSource nonJtaDataSource;
+ private String nonJtaDataSourceName;
+ private String persistenceProviderClassName;
+ private String persistenceUnitName;
+ private String persistenceXMLSchemaVersion;
+ private Properties props;
+ private SharedCacheMode sharedCacheMode = SharedCacheMode.UNSPECIFIED;
+ private PersistenceUnitTransactionType transactionType;
+ private ValidationMode validationMode = ValidationMode.NONE;
+
+ public PersistenceUnit(Bundle bundle, String persistenceUnitName,
+ PersistenceUnitTransactionType transactionType) {
+ this.bundle = bundle;
+ this.persistenceUnitName = persistenceUnitName;
+ this.transactionType = transactionType;
+ this.props = new Properties();
+ this.classLoader = bundle.adapt(BundleWiring.class).getClassLoader();
+ this.classNames = new HashSet<>();
+ }
+
+ public void addClassName(String className) {
+ this.classNames.add(className);
+ }
+
+ public void addProperty(String name, String value) {
+ props.put(name, value);
+ }
+
+ @Override
+ public void addTransformer(ClassTransformer transformer) {
+ TransformerRegistry reg = TransformerRegistrySingleton.get();
+ reg.addTransformer(bundle, transformer);
+ }
+
+ @Override
+ public boolean excludeUnlistedClasses() {
+ return this.excludeUnlisted;
+ }
+
+ public Bundle getBundle() {
+ return bundle;
+ }
+
+ @Override
+ public ClassLoader getClassLoader() {
+ return this.classLoader;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List<URL> getJarFileUrls() {
+ return Collections.EMPTY_LIST;
+ }
+
+ @Override
+ public DataSource getJtaDataSource() {
+ return this.jtaDataSource;
+ }
+
+ public String getJtaDataSourceName() {
+ return jtaDataSourceName;
+ }
+
+ @Override
+ public List<String> getManagedClassNames() {
+ ArrayList<String> names = new ArrayList<>();
+ names.addAll(classNames);
+ return names;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List<String> getMappingFileNames() {
+ return Collections.EMPTY_LIST;
+ }
+
+ public String getName() {
+ return persistenceUnitName;
+ }
+
+ @Override
+ public ClassLoader getNewTempClassLoader() {
+ return new TempBundleDelegatingClassLoader(bundle, classLoader);
+ }
+
+ @Override
+ public DataSource getNonJtaDataSource() {
+ return this.nonJtaDataSource;
+ }
+
+ public String getNonJtaDataSourceName() {
+ return nonJtaDataSourceName;
+ }
+
+ @Override
+ public String getPersistenceProviderClassName() {
+ return this.persistenceProviderClassName;
+ }
+
+ @Override
+ public String getPersistenceUnitName() {
+ return this.persistenceUnitName;
+ }
+
+ @Override
+ public URL getPersistenceUnitRootUrl() {
+ return bundle.getResource("/");
+ }
+
+ @Override
+ public String getPersistenceXMLSchemaVersion() {
+ return this.persistenceXMLSchemaVersion;
+ }
+
+ @Override
+ public Properties getProperties() {
+ return this.props;
+ }
+
+ @Override
+ public SharedCacheMode getSharedCacheMode() {
+ return this.sharedCacheMode;
+ }
+
+ @Override
+ public PersistenceUnitTransactionType getTransactionType() {
+ return transactionType;
+ }
+
+ @Override
+ public ValidationMode getValidationMode() {
+ return this.validationMode;
+ }
+
+ public boolean isExcludeUnlisted() {
+ return excludeUnlisted;
+ }
+
+ public void setExcludeUnlisted(boolean excludeUnlisted) {
+ this.excludeUnlisted = excludeUnlisted;
+ }
+
+ public void setJtaDataSource(DataSource jtaDataSource) {
+ this.jtaDataSource = jtaDataSource;
+ }
+
+ public void setJtaDataSourceName(String jtaDataSourceName) {
+ this.jtaDataSourceName = jtaDataSourceName;
+ }
+
+ public void setNonJtaDataSource(DataSource nonJtaDataSource) {
+ this.nonJtaDataSource = nonJtaDataSource;
+ }
+
+ public void setNonJtaDataSourceName(String nonJtaDataSourceName) {
+ this.nonJtaDataSourceName = nonJtaDataSourceName;
+ }
+
+ public void setProviderClassName(String providerClassName) {
+ this.persistenceProviderClassName = providerClassName;
+ }
+
+ public void setSharedCacheMode(SharedCacheMode sharedCacheMode) {
+ this.sharedCacheMode = sharedCacheMode;
+ }
+
+ public void setValidationMode(ValidationMode validationMode) {
+ this.validationMode = validationMode;
+ }
+
+ public void addAnnotated(PackageAdmin packageAdmin) {
+ if (!excludeUnlistedClasses()) {
+ Collection<String> detected = JPAAnnotationScanner.findJPAAnnotatedClasses(bundle);
+ for (String name : detected) {
+ addClassName(name);
+ }
+ }
+ }
+}
Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/PersistenceUnitParser.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/PersistenceUnitParser.java?rev=1680218&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/PersistenceUnitParser.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/PersistenceUnitParser.java Tue May 19 09:47:49 2015
@@ -0,0 +1,187 @@
+/*
+ * 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.jpa.container.parser.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+
+import javax.persistence.spi.PersistenceUnitTransactionType;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.osgi.framework.Bundle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This helper can be used to locate persistence.xml files in a bundle
+ */
+public class PersistenceUnitParser {
+ private static final String DEFAULT_PERSISTENCE_LOCATION = "META-INF/persistence.xml";
+ private static final Logger _logger = LoggerFactory.getLogger("org.apache.aries.jpa.container");
+ public static final String PERSISTENCE_UNIT_HEADER = "Meta-Persistence";
+
+ /**
+ * This method locates persistence descriptor files based on a combination of the default location
+ * "META-INF/persistence.xml" and the Meta-Persistence header. Note that getEntry is used to ensure we do
+ * not alter the state of the bundle Note also that web application bundles will never return persistence
+ * descriptors
+ * @param context
+ *
+ * @param bundle The bundle to search
+ * @param packageAdmin
+ * @return
+ */
+ public static Collection<PersistenceUnit> getPersistenceUnits(Bundle bundle) {
+ Collection<PersistenceUnit> punits = new ArrayList<PersistenceUnit>();
+ Dictionary<String, String> headers = bundle.getHeaders();
+ String metaPersistence = headers.get(PERSISTENCE_UNIT_HEADER);
+
+ Set<String> locations = new HashSet<String>();
+ if (metaPersistence == null) {
+ return punits;
+ }
+
+ if (!metaPersistence.isEmpty()) {
+ // Split apart the header to get the individual entries
+ for (String s : metaPersistence.split(",")) {
+ locations.add(s.trim());
+ }
+ }
+
+ if (!locations.contains(DEFAULT_PERSISTENCE_LOCATION)) {
+ locations.add(DEFAULT_PERSISTENCE_LOCATION);
+ }
+
+ // Find the file and add it to our list
+ for (String location : locations) {
+ try {
+ InputStream is = locateFile(bundle, location);
+ if (is != null) {
+ parse(bundle, location, is, punits);
+ }
+ } catch (Exception e) {
+ _logger.error("exception.while.locating.descriptor", e);
+ return Collections.emptySet();
+ }
+ }
+
+ return punits;
+ }
+
+ private static void parse(Bundle bundle, String location, InputStream is, Collection<PersistenceUnit> punits) {
+ SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+ try {
+ SAXParser parser = parserFactory.newSAXParser();
+ JPAHandler handler = new JPAHandler(bundle);
+ parser.parse(is, handler);
+ punits.addAll(handler.getPersistenceUnits());
+// for (PersistenceUnit punit : punits) {
+ //validate(punit);
+// }
+ } catch (Exception e) {
+ throw new RuntimeException("persistence.description.parse.error", e);
+ } finally {
+ safeClose(is);
+ }
+ }
+
+ private static void validate(PersistenceUnit punit) {
+ if (punit.getTransactionType() == null) {
+ throw new IllegalArgumentException("No transaction type specified for persistence unit " + punit.getName());
+ }
+ if (punit.getTransactionType() == PersistenceUnitTransactionType.JTA) {
+ if (punit.getJtaDataSourceName() == null) {
+ throw new IllegalArgumentException("Must specify jta-data-source for persistence unit " + punit.getName());
+ }
+ }
+ if (punit.getTransactionType() == PersistenceUnitTransactionType.RESOURCE_LOCAL) {
+ if (punit.getNonJtaDataSourceName() == null) {
+ throw new IllegalArgumentException("Must specify non-jta-data-source for persistence unit " + punit.getName());
+ }
+ }
+ }
+
+ private static void safeClose(InputStream is) {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ // No logging necessary, just consume
+ }
+ }
+ }
+
+ /**
+ * Locate a persistence descriptor file in a bundle based on a String name.
+ *
+ * @param bundle
+ * @param persistenceXmlFiles
+ * @param jarLocation
+ * @throws IOException
+ */
+ private static InputStream locateFile(Bundle bundle, String location) throws IOException {
+ // There is nothing for an empty location
+ InputStream is = null;
+ if ("".equals(location)) {
+ return null;
+ }
+
+ // If there is a '!' then we have to look in a jar
+ int bangIndex = location.indexOf('!');
+ // No '!', getEntry will do
+ if (bangIndex == -1) {
+ URL url = bundle.getEntry(location);
+
+ if (url != null)
+ is = url.openStream();
+
+ } else {
+ // There was a '!', find the jar
+ URL url = bundle.getEntry(location.substring(0, bangIndex));
+
+ if (url != null) {
+ // Remember to trim off the "!/"
+ String toLocate = location.substring(bangIndex + 2);
+
+ @SuppressWarnings("resource")
+ JarInputStream jis = new JarInputStream(url.openStream());
+ JarEntry entry = jis.getNextJarEntry();
+
+ while (entry != null) {
+ if (entry.getName().equals(toLocate)) {
+ is = jis;
+ break;
+ }
+ entry = jis.getNextJarEntry();
+ }
+ }
+ }
+ return is;
+ }
+}
Copied: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/TempBundleDelegatingClassLoader.java (from r1680054, aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/TempBundleDelegatingClassLoader.java)
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/TempBundleDelegatingClassLoader.java?p2=aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/TempBundleDelegatingClassLoader.java&p1=aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/TempBundleDelegatingClassLoader.java&r1=1680054&r2=1680218&rev=1680218&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/TempBundleDelegatingClassLoader.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/parser/impl/TempBundleDelegatingClassLoader.java Tue May 19 09:47:49 2015
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.aries.jpa.container.unit.impl;
+package org.apache.aries.jpa.container.parser.impl;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/DummyDataSource.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/DummyDataSource.java?rev=1680218&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/DummyDataSource.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/DummyDataSource.java Tue May 19 09:47:49 2015
@@ -0,0 +1,97 @@
+package org.apache.aries.jpa.container.weaving.impl;
+
+import java.io.PrintWriter;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+
+import javax.sql.DataSource;
+
+/**
+ * DummyDataSource to be able to create the EMF before DataSource is ready
+ */
+public final class DummyDataSource implements DataSource {
+
+ /**
+ * Simply tries to avoid that calling code runs into NPE
+ */
+ private final class DummyHandler implements InvocationHandler {
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ ClassLoader classLoader = this.getClass().getClassLoader();
+ if (method.getReturnType() == DatabaseMetaData.class) {
+ Class<?>[] ifAr = new Class[] {
+ DatabaseMetaData.class
+ };
+ return Proxy.newProxyInstance(classLoader, ifAr, this);
+ }
+ if (method.getReturnType() == int.class) {
+ return new Integer(0);
+ }
+ if (method.getReturnType() == boolean.class) {
+ return new Boolean(false);
+ }
+ if (method.getReturnType() == String.class) {
+ return "";
+ }
+ if (method.getReturnType() == ResultSet.class) {
+ Class<?>[] ifAr = new Class[] {
+ ResultSet.class
+ };
+ return Proxy.newProxyInstance(classLoader, ifAr, this);
+ }
+ return null;
+ }
+ }
+
+ @Override
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ return null;
+ }
+
+ @Override
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ return false;
+ }
+
+ @Override
+ public void setLoginTimeout(int seconds) throws SQLException {
+ }
+
+ @Override
+ public void setLogWriter(PrintWriter out) throws SQLException {
+ }
+
+ @Override
+ public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException {
+ return null;
+ }
+
+ @Override
+ public int getLoginTimeout() throws SQLException {
+ return 0;
+ }
+
+ @Override
+ public PrintWriter getLogWriter() throws SQLException {
+ return null;
+ }
+
+ @Override
+ public Connection getConnection(String username, String password) throws SQLException {
+ InvocationHandler handler = new DummyHandler();
+ ClassLoader classLoader = this.getClass().getClassLoader();
+ return (Connection)Proxy.newProxyInstance(classLoader, new Class[] {
+ Connection.class
+ }, handler);
+ }
+
+ @Override
+ public Connection getConnection() throws SQLException {
+ return getConnection(null, null);
+ }
+}
Modified: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/JPAWeavingHook.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/JPAWeavingHook.java?rev=1680218&r1=1680217&r2=1680218&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/JPAWeavingHook.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/JPAWeavingHook.java Tue May 19 09:47:49 2015
@@ -20,112 +20,115 @@ package org.apache.aries.jpa.container.w
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.LinkedHashSet;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
+import java.util.Map;
import javax.persistence.spi.ClassTransformer;
-import org.apache.aries.jpa.container.impl.NLS;
import org.osgi.framework.Bundle;
-import org.osgi.framework.ServiceReference;
import org.osgi.framework.hooks.weaving.WeavingException;
import org.osgi.framework.hooks.weaving.WeavingHook;
import org.osgi.framework.hooks.weaving.WovenClass;
import org.osgi.framework.wiring.BundleWiring;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
- * This weaving hook delegates to any registered {@link ClassTransformer} instances
- * for a given bundle
+ * This weaving hook delegates to any registered {@link ClassTransformer} instances for a given bundle
*/
public class JPAWeavingHook implements WeavingHook, TransformerRegistry {
+ private static final Logger LOGGER = LoggerFactory.getLogger(JPAWeavingHook.class);
- /**
- * This constructor should not be called directly, the {@link JPAWeavingHookFactory}
- * should be used to ensure that Weaving support is available.
- */
- JPAWeavingHook() { }
-
- /**
- * With luck we will only have one persistence unit per bundle, but
- * if we don't we'll need to call them until one of them does a transform
- * or we run out.
- */
- private final ConcurrentMap<Bundle, LinkedHashSet<WrappingTransformer>> registeredTransformers
- = new ConcurrentHashMap<Bundle, LinkedHashSet<WrappingTransformer>>();
-
- public void weave(WovenClass wovenClass) {
-
- BundleWiring wiring = wovenClass.getBundleWiring();
-
- Collection<WrappingTransformer> transformers = registeredTransformers.get(
- wiring.getBundle());
-
- if(transformers != null) {
- Collection<WrappingTransformer> transformersToTry;
- synchronized (transformers) {
- transformersToTry = new ArrayList<WrappingTransformer>(transformers);
- }
- for(WrappingTransformer transformer : transformersToTry) {
+ /**
+ * This constructor should not be called directly, the {@link JPAWeavingHookFactory} should be used to
+ * ensure that Weaving support is available.
+ */
+ JPAWeavingHook() {
+ }
+
+ /**
+ * With luck we will only have one persistence unit per bundle, but if we don't we'll need to call them
+ * until one of them does a transform or we run out.
+ */
+ private final Map<Bundle, LinkedHashSet<ClassTransformer>> registeredTransformers = new HashMap<Bundle, LinkedHashSet<ClassTransformer>>();
+
+ public void weave(WovenClass wovenClass) {
+ BundleWiring wiring = wovenClass.getBundleWiring();
+ Bundle bundle = wiring.getBundle();
+ ClassLoader cl = wiring.getClassLoader();
+ Collection<ClassTransformer> transformersToTry = getTransformers(bundle);
+ if (transformersToTry.size() == 0 && wovenClass.getClassName().endsWith("Car")) {
+ LOGGER.error("Loading " + wovenClass.getClassName() + " before transformer is present");
+ //for (StackTraceElement el : Thread.currentThread().getStackTrace()) {
+// LOGGER.info(el.toString());
+// }
+ }
+ for (ClassTransformer transformer : transformersToTry) {
+
+ if (transformClass(wovenClass, cl, transformer)) {
+ LOGGER.info("Weaving " + wovenClass.getClassName() + " using " + transformer.getClass().getName());
+ break;
+ };
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private synchronized Collection<ClassTransformer> getTransformers(Bundle bundle) {
+ LinkedHashSet<ClassTransformer> transformers = registeredTransformers.get(bundle);
+ return transformers != null ? new ArrayList<ClassTransformer>(transformers) : Collections.EMPTY_LIST;
+ }
+
+ private boolean transformClass(WovenClass wovenClass, ClassLoader cl, ClassTransformer transformer)
+ throws ThreadDeath, OutOfMemoryError {
try {
- byte[] result = transformer.transform(wiring.getClassLoader(),
- wovenClass.getClassName(), wovenClass.getDefinedClass(),
- wovenClass.getProtectionDomain(), wovenClass.getBytes());
- if(result != null) {
- wovenClass.setBytes(result);
- wovenClass.getDynamicImports().addAll(transformer.getPackagesToAdd());
- break;
- }
+ byte[] result = transformer
+ .transform(cl,
+ wovenClass.getClassName(),
+ wovenClass.getDefinedClass(),
+ wovenClass.getProtectionDomain(),
+ wovenClass.getBytes());
+ if (result != null) {
+ wovenClass.setBytes(result);
+ wovenClass.getDynamicImports().add("org.eclipse.persistence.*");
+ wovenClass.getDynamicImports().add("org.apache.openjpa.*");
+
+ return true;
+ }
} catch (Throwable t) {
- if(t instanceof ThreadDeath)
- throw (ThreadDeath)t;
- else if (t instanceof OutOfMemoryError)
- throw (OutOfMemoryError) t;
- else {
- Bundle b = wovenClass.getBundleWiring().getBundle();
- throw new WeavingException(NLS.MESSAGES.getMessage("jpa.weaving.failure", wovenClass.getClassName(), b.getSymbolicName(), b.getVersion(), transformer), t);
- }
- }
- }
- }
- }
-
- public void addTransformer(Bundle pBundle, ClassTransformer transformer, ServiceReference<?> provider) {
-
- //Optimised for single adds
-
- LinkedHashSet<WrappingTransformer> set = new LinkedHashSet<WrappingTransformer>();
- WrappingTransformer wt = new WrappingTransformer(transformer, provider);
- set.add(wt);
-
- LinkedHashSet<WrappingTransformer> existingSet = registeredTransformers.putIfAbsent(pBundle, set);
-
- if(existingSet != null) {
- synchronized (existingSet) {
- existingSet.add(wt);
- }
- }
- }
-
- public void removeTransformer(Bundle pBundle, ClassTransformer transformer) {
- LinkedHashSet<WrappingTransformer> set = registeredTransformers.get(pBundle);
-
- if(set == null || !!!safeRemove(set, transformer))
- throw new IllegalStateException(NLS.MESSAGES.getMessage("jpa.weaving.transformer.not.registered", transformer));
-
- if(set.isEmpty())
- registeredTransformers.remove(pBundle);
- }
-
- /**
- * Perform a remove on the collection while synchronized on it
- * @param set
- * @param t
- * @return
- */
- private boolean safeRemove(Collection<WrappingTransformer> set, ClassTransformer t) {
- synchronized(set) {
- return set.remove(new WrappingTransformer(t));
- }
- }
+ if (t instanceof ThreadDeath)
+ throw (ThreadDeath)t;
+ else if (t instanceof OutOfMemoryError)
+ throw (OutOfMemoryError)t;
+ else {
+ Bundle b = wovenClass.getBundleWiring().getBundle();
+ String msg = String.format("Weaving failure", wovenClass.getClassName(),
+ b.getSymbolicName(), b.getVersion(), transformer);
+ throw new WeavingException(msg, t);
+ }
+ }
+ return false;
+ }
+
+ public synchronized void addTransformer(Bundle pBundle, ClassTransformer transformer) {
+ LOGGER.info("Adding transformer " + transformer.getClass().getName());
+ LinkedHashSet<ClassTransformer> transformers = registeredTransformers.get(pBundle);
+ if (transformers == null) {
+ transformers = new LinkedHashSet<ClassTransformer>();
+ registeredTransformers.put(pBundle, transformers);
+ }
+ transformers.add(transformer);
+ }
+
+ public synchronized void removeTransformer(Bundle pBundle, ClassTransformer transformer) {
+ LinkedHashSet<ClassTransformer> set = registeredTransformers.get(pBundle);
+ if (set == null || !set.remove(transformer)) {
+ throw new IllegalStateException("Transformer " + transformer + " not registered");
+ }
+ if (set.isEmpty()) {
+ registeredTransformers.remove(pBundle);
+ }
+ }
+
}
Modified: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/TransformerRegistry.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/TransformerRegistry.java?rev=1680218&r1=1680217&r2=1680218&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/TransformerRegistry.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/TransformerRegistry.java Tue May 19 09:47:49 2015
@@ -21,11 +21,10 @@ package org.apache.aries.jpa.container.w
import javax.persistence.spi.ClassTransformer;
import org.osgi.framework.Bundle;
-import org.osgi.framework.ServiceReference;
/**
* {@link ClassTransformer} instances should be registered with the
- * instance of this interface returned by {@link TransformerRegistryFactory#getTransformerRegistry()}
+ * instance of this interface returned by {@link TransformerRegistrySingleton#getTransformerRegistry()}
*/
public interface TransformerRegistry {
@@ -36,7 +35,7 @@ public interface TransformerRegistry {
* @param transformer The transformer to weave with
* @param provider The provider to provide packages from
*/
- public void addTransformer(Bundle pBundle, ClassTransformer transformer, ServiceReference<?> provider);
+ public void addTransformer(Bundle pBundle, ClassTransformer transformer);
/**
Copied: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/TransformerRegistrySingleton.java (from r1680054, aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/DestroyCallback.java)
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/TransformerRegistrySingleton.java?p2=aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/TransformerRegistrySingleton.java&p1=aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/DestroyCallback.java&r1=1680054&r2=1680218&rev=1680218&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/DestroyCallback.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/TransformerRegistrySingleton.java Tue May 19 09:47:49 2015
@@ -16,11 +16,19 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.aries.jpa.container.quiesce.impl;
+package org.apache.aries.jpa.container.weaving.impl;
+
/**
- * An asynchronous callback for destroying something
+ * This class is used to get hold of the active {@link TransformerRegistry} for this bundle.
*/
-public interface DestroyCallback {
- public void callback();
+public class TransformerRegistrySingleton {
+ private static TransformerRegistry _instance;
+
+ public static TransformerRegistry get() {
+ if (_instance == null) {
+ _instance = new JPAWeavingHook();
+ }
+ return _instance;
+ }
}
Modified: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/WrappingTransformer.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/WrappingTransformer.java?rev=1680218&r1=1680217&r2=1680218&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/WrappingTransformer.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/weaving/impl/WrappingTransformer.java Tue May 19 09:47:49 2015
@@ -25,7 +25,6 @@ import java.util.HashSet;
import javax.persistence.spi.ClassTransformer;
-import org.apache.aries.jpa.container.impl.NLS;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
@@ -34,65 +33,63 @@ import org.osgi.framework.wiring.BundleR
import org.osgi.framework.wiring.BundleWiring;
class WrappingTransformer implements ClassTransformer {
- private final ClassTransformer delegate;
- private final Collection<String> packageImportsToAdd = new HashSet<String>();
-
- public WrappingTransformer(ClassTransformer delegate,
- ServiceReference<?> persistenceProvider) {
-
- if(delegate == null)
- throw new NullPointerException(NLS.MESSAGES.getMessage("jpa.weaving.null.transformer"));
-
- if(persistenceProvider == null) {
- throw new NullPointerException(NLS.MESSAGES.getMessage("jpa.weaving.null.provider"));
- }
-
- this.delegate = delegate;
-
- Object packages = persistenceProvider.getProperty("org.apache.aries.jpa.container.weaving.packages");
-
- if(packages instanceof String[]) {
- for(String s : (String[]) packages) {
- packageImportsToAdd.add(s);
- }
- } else {
- Bundle provider = persistenceProvider.getBundle();
- String suffix = ";" + Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE + "=" +
- provider.getSymbolicName() + ";" + Constants.BUNDLE_VERSION_ATTRIBUTE
- + "=" + provider.getVersion();
-
- BundleRevision br = provider.adapt(BundleWiring.class).getRevision();
- for(BundleCapability bc : br.getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE)) {
- packageImportsToAdd.add(bc.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE) + suffix);
- }
- }
- }
-
- public WrappingTransformer(ClassTransformer transformer) {
- delegate = transformer;
- }
-
- public byte[] transform(ClassLoader arg0, String arg1, Class<?> arg2,
- ProtectionDomain arg3, byte[] arg4) throws IllegalClassFormatException {
- return delegate.transform(arg0, arg1, arg2, arg3, arg4);
- }
-
- public Collection<String> getPackagesToAdd() {
- return packageImportsToAdd;
- }
-
- public int hashCode() {
- return delegate.hashCode();
- }
-
- public boolean equals(Object o) {
- if(o instanceof WrappingTransformer)
- return delegate == ((WrappingTransformer) o).delegate;
-
- return false;
- }
-
- public String toString() {
- return "Transformer: " + delegate.toString() + " Packages to add: " + packageImportsToAdd;
- }
-}
\ No newline at end of file
+ private final ClassTransformer delegate;
+ private final Collection<String> packageImportsToAdd = new HashSet<String>();
+
+ public WrappingTransformer(ClassTransformer delegate, ServiceReference<?> persistenceProvider) {
+
+ if (delegate == null)
+ throw new NullPointerException("Transformer delegate may not be null");
+
+ if (persistenceProvider == null) {
+ throw new NullPointerException("PersistenceProvider may not be null");
+ }
+
+ this.delegate = delegate;
+
+ Object packages = persistenceProvider.getProperty("org.apache.aries.jpa.container.weaving.packages");
+
+ if (packages instanceof String[]) {
+ for (String s : (String[])packages) {
+ packageImportsToAdd.add(s);
+ }
+ } else {
+ Bundle provider = persistenceProvider.getBundle();
+ String suffix = ";" + Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE + "=" + provider.getSymbolicName()
+ + ";" + Constants.BUNDLE_VERSION_ATTRIBUTE + "=" + provider.getVersion();
+
+ BundleRevision br = provider.adapt(BundleWiring.class).getRevision();
+ for (BundleCapability bc : br.getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE)) {
+ packageImportsToAdd.add(bc.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE) + suffix);
+ }
+ }
+ }
+
+ public WrappingTransformer(ClassTransformer transformer) {
+ delegate = transformer;
+ }
+
+ public byte[] transform(ClassLoader arg0, String arg1, Class<?> arg2, ProtectionDomain arg3, byte[] arg4)
+ throws IllegalClassFormatException {
+ return delegate.transform(arg0, arg1, arg2, arg3, arg4);
+ }
+
+ public Collection<String> getPackagesToAdd() {
+ return packageImportsToAdd;
+ }
+
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ public boolean equals(Object o) {
+ if (o instanceof WrappingTransformer)
+ return delegate == ((WrappingTransformer)o).delegate;
+
+ return false;
+ }
+
+ public String toString() {
+ return "Transformer: " + delegate.toString() + " Packages to add: " + packageImportsToAdd;
+ }
+}
Added: aries/trunk/jpa/jpa-container/src/test/java/org/apache/aries/jpa/container/impl/DataSourceTrackerTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/test/java/org/apache/aries/jpa/container/impl/DataSourceTrackerTest.java?rev=1680218&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/test/java/org/apache/aries/jpa/container/impl/DataSourceTrackerTest.java (added)
+++ aries/trunk/jpa/jpa-container/src/test/java/org/apache/aries/jpa/container/impl/DataSourceTrackerTest.java Tue May 19 09:47:49 2015
@@ -0,0 +1,60 @@
+/*
+ * 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 WARRANTIESOR 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.jpa.container.impl;
+
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import javax.persistence.spi.PersistenceUnitTransactionType;
+
+import org.apache.aries.jpa.container.impl.DataSourceTracker;
+import org.apache.aries.jpa.container.parser.impl.PersistenceUnit;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+
+public class DataSourceTrackerTest {
+
+ @Test
+ public void testCreateFilterFull() throws InvalidSyntaxException {
+ PersistenceUnit punit = mock(PersistenceUnit.class);
+ when(punit.getJtaDataSourceName()).thenReturn("osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=tasklist)");
+ when(punit.getTransactionType()).thenReturn(PersistenceUnitTransactionType.JTA);
+ BundleContext context = mock(BundleContext.class);
+
+ DataSourceTracker.createFilter(context, punit);
+
+ verify(context, atLeastOnce()).createFilter(Mockito.eq("(&(objectClass=javax.sql.DataSource)(osgi.jndi.service.name=tasklist))"));
+ }
+
+ @Test
+ public void testCreateFilterSimple() throws InvalidSyntaxException {
+ PersistenceUnit punit = mock(PersistenceUnit.class);
+ when(punit.getJtaDataSourceName()).thenReturn("tasklist");
+ when(punit.getTransactionType()).thenReturn(PersistenceUnitTransactionType.JTA);
+ BundleContext context = mock(BundleContext.class);
+
+ DataSourceTracker.createFilter(context, punit);
+
+ verify(context, atLeastOnce()).createFilter(Mockito.eq("(&(objectClass=javax.sql.DataSource)(osgi.jndi.service.name=tasklist))"));
+ }
+}