diff options
Diffstat (limited to 'sandbox/old/contrib/persistence/common/src/main/java')
9 files changed, 960 insertions, 0 deletions
diff --git a/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/DefaultPersistenceUnitBuilder.java b/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/DefaultPersistenceUnitBuilder.java new file mode 100644 index 0000000000..684eee8c09 --- /dev/null +++ b/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/DefaultPersistenceUnitBuilder.java @@ -0,0 +1,66 @@ +/* + * 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.tuscany.service.persistence.common; + +import java.util.HashMap; +import java.util.Map; + +import javax.persistence.EntityManagerFactory; +import javax.persistence.spi.PersistenceProvider; +import javax.persistence.spi.PersistenceUnitInfo; + +/** + * Default implementation of the persistence unit builder. + * + * @version $Rev$ $Date$ + */ +public class DefaultPersistenceUnitBuilder implements PersistenceUnitBuilder { + + /** Persistence unit scanner */ + private PersistenceUnitScanner scanner = new PersistenceUnitScanner(); + + /** + * Builds the entity manager factory matching the unit name. All persistence.xml + * files available for the specified classloader is scanned for the specified + * persistence unit. The JPA provider API is used to create the entity manager + * factory. + * + * @param unitName Persistence unit name. + * @param classLoader Classloader. + * @return Entity manager factory. + */ + public EntityManagerFactory newEntityManagerFactory(String unitName, ClassLoader classLoader) { + + PersistenceUnitInfo info = scanner.getPersistenceUnitInfo(unitName, classLoader); + String providerClass = info.getPersistenceProviderClassName(); + try { + Map overrides = new HashMap(); + PersistenceProvider provider = (PersistenceProvider) Class.forName(providerClass).newInstance(); + return provider.createContainerEntityManagerFactory(info, overrides); + } catch (InstantiationException ex) { + throw new TuscanyJpaException(ex); + } catch (IllegalAccessException ex) { + throw new TuscanyJpaException(ex); + } catch (ClassNotFoundException ex) { + throw new TuscanyJpaException(ex); + } + + } + +} diff --git a/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/EntityManagerProxy.java b/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/EntityManagerProxy.java new file mode 100644 index 0000000000..492bd36689 --- /dev/null +++ b/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/EntityManagerProxy.java @@ -0,0 +1,86 @@ +/* + * 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.tuscany.service.persistence.common; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.Properties; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.transaction.Synchronization; +import javax.transaction.Transaction; +import javax.transaction.TransactionManager; + +/** + * Proxy for entity manager. + * + * @version $Rev$ $Date$ + */ +public class EntityManagerProxy implements InvocationHandler { + + // Thread local cache of entity managers + private ThreadLocal<EntityManager> entityManagers = new ThreadLocal<EntityManager>(); + + // Properties + private Properties prop; + + // Entity manager factory + private EntityManagerFactory emf; + + // Transaction manager + private TransactionManager txm; + + /** + * Initializes the artifacts required to create an EM. + * + * @param prop EM creation porperty overrides. + * @param emf Entity manager factory to use. + * @param txm Transaction manager to use. + */ + public EntityManagerProxy(Properties prop, EntityManagerFactory emf, TransactionManager txm) { + this.prop = prop; + this.txm = txm; + this.emf = emf; + } + + /** + * Proxies the entity manager. + */ + public Object invoke(Object target, Method method, Object[] parameters) throws Throwable { + + EntityManager entityManager = entityManagers.get(); + if(entityManager != null) { + entityManager = emf.createEntityManager(prop); + entityManagers.set(entityManager); + Transaction tx = txm.getTransaction(); + if(tx != null) { + tx.registerSynchronization(new Synchronization() { + public void afterCompletion(int arg0) { + entityManagers.set(null); + } + public void beforeCompletion() { + } + }); + } + } + return method.invoke(entityManager, parameters); + } + +} diff --git a/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/JpaConstants.java b/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/JpaConstants.java new file mode 100644 index 0000000000..04d1c419ca --- /dev/null +++ b/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/JpaConstants.java @@ -0,0 +1,47 @@ +/* + * 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.tuscany.service.persistence.common; + +public class JpaConstants { + + public static final String PROPERTY_VALUE = "value"; + + public static final String PROPERTY_NAME = "name"; + + public static final String PROPERTY = "//persistence-unit/properties/property"; + + public static final String TRANSACTION_TYPE = "//persistence-unit/@transaction-type"; + + public static final String NAME = "//persistence-unit/@name"; + + public static final String PROVIDER = "//persistence-unit/provider"; + + public static final String NON_JTA_DATA_SOURCE = "//persistence-unit/non-jta-data-source"; + + public static final String MAPPING_FILE = "//persistence-unit/mapping-file"; + + public static final String CLASS = "//persistence-unit/class"; + + public static final String JTA_DATA_SOURCE = "//persistence-unit/jta-data-source"; + + public static final String JAR_FILE = "//persistence-unit/jar-file"; + + public static final String EXCLUDE_UNLISTED_CLASSES = "//persistence-unit/exclude-unlisted-classes"; + +} diff --git a/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/PersistenceContextProcessor.java b/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/PersistenceContextProcessor.java new file mode 100644 index 0000000000..9d247fae43 --- /dev/null +++ b/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/PersistenceContextProcessor.java @@ -0,0 +1,161 @@ +/* + * 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.tuscany.service.persistence.common; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; +import java.net.URI; +import java.util.Properties; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.PersistenceContext; +import javax.persistence.PersistenceContextType; +import javax.persistence.PersistenceProperty; +import javax.transaction.TransactionManager; + +import org.osoa.sca.annotations.Reference; + +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.component.RegistrationException; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.InterfaceJavaIntrospector; +import org.apache.tuscany.spi.implementation.java.AbstractPropertyProcessor; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.model.ServiceContract; + +import org.apache.tuscany.core.component.ComponentManager; + +/** + * Annotation processor for injecting <code>PersistenceUnit</code> annotations on properties. + * + * @version $Rev$ $Date$ + */ +public class PersistenceContextProcessor extends AbstractPropertyProcessor<PersistenceContext> { + + /** + * Transaction Manager + */ + private TransactionManager transactionManager; + private ComponentManager componentManager; + private InterfaceJavaIntrospector introspector; + + /** + * Persistence unit builder + */ + private PersistenceUnitBuilder builder = new DefaultPersistenceUnitBuilder(); + + /** + * Injects the implementation processor service. + * + * @param service Implementation processor service. + */ + public PersistenceContextProcessor(@Reference ImplementationProcessorService service) { + super(PersistenceContext.class, service); + } + + @Reference + public void setTransactionManager(TransactionManager transactionManager) { + this.transactionManager = transactionManager; + } + + @Reference + public void setComponentManager(ComponentManager componentManager) { + this.componentManager = componentManager; + } + + @Reference + public void setIntrospector(InterfaceJavaIntrospector introspector) { + this.introspector = introspector; + } + + /** + * Defaults to the field name. + */ + @Override + protected String getName(PersistenceContext persistenceContext) { + return null; + } + + /** + * Initializes the property. + */ + @SuppressWarnings("unchecked") + protected <T> void initProperty(JavaMappedProperty<T> property, + PersistenceContext annotation, + DeploymentContext context) throws ProcessingException { + + String unitName = annotation.unitName(); + URI unitUri = context.getComponentId().resolve(unitName); + EntityManagerFactory emf = (EntityManagerFactory) componentManager.getComponent(unitUri); + + if (emf == null) { + emf = builder.newEntityManagerFactory(unitName, context.getClassLoader()); + try { + ServiceContract<EntityManagerFactory> contract = + (ServiceContract) introspector.introspect(EntityManagerFactory.class); + componentManager.registerJavaObject(unitUri, contract, emf); + } catch (RegistrationException e) { + throw new ProcessingException(e); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + } + ObjectFactory factory = new EmObjectFactory(emf, annotation); + property.setDefaultValueFactory(factory); + + } + + private class EmObjectFactory implements ObjectFactory<EntityManager> { + + private EntityManagerFactory emf; + private PersistenceContext annotation; + + public EmObjectFactory(EntityManagerFactory emf, PersistenceContext annotation) { + this.emf = emf; + this.annotation = annotation; + } + + public EntityManager getInstance() { + + PersistenceContextType type = annotation.type(); + if (type == PersistenceContextType.TRANSACTION) { + + Properties props = new Properties(); + for (PersistenceProperty property : annotation.properties()) { + props.put(property.name(), property.value()); + } + + Class[] interfaces = new Class[]{EntityManager.class}; + InvocationHandler handler = new EntityManagerProxy(props, emf, transactionManager); + EntityManager em = + (EntityManager) Proxy.newProxyInstance(getClass().getClassLoader(), interfaces, handler); + return em; + + } else { + throw new UnsupportedOperationException("Extended persistence contexts not supported"); + } + + } + + } + +} diff --git a/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/PersistenceUnitBuilder.java b/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/PersistenceUnitBuilder.java new file mode 100644 index 0000000000..d8d30d6811 --- /dev/null +++ b/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/PersistenceUnitBuilder.java @@ -0,0 +1,41 @@ +/* + * 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.tuscany.service.persistence.common; + +import javax.persistence.EntityManagerFactory; + +/** + * Interface for building persistence units as specified by the JPA specification.. + * + * @version $Rev$ $Date$ + */ +public interface PersistenceUnitBuilder { + + /** + * Builds the entity manager factory matching the unit name. All persistence.xml files available for the specified + * classloader is scanned for the specified persistence unit. The JPA provider API is used to create the entity + * manager factory. + * + * @param unitName Persistence unit name. + * @param classLoader Classloader. + * @return Entity manager factory. + */ + public EntityManagerFactory newEntityManagerFactory(String unitName, ClassLoader classLoader); + +} diff --git a/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/PersistenceUnitProcessor.java b/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/PersistenceUnitProcessor.java new file mode 100644 index 0000000000..169f48fec7 --- /dev/null +++ b/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/PersistenceUnitProcessor.java @@ -0,0 +1,122 @@ +/* + * 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.tuscany.service.persistence.common; + +import java.lang.reflect.Field; +import java.net.URI; +import javax.persistence.EntityManagerFactory; +import javax.persistence.PersistenceUnit; + +import org.osoa.sca.annotations.Reference; + +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.RegistrationException; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.InterfaceJavaIntrospector; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.implementation.java.Resource; +import org.apache.tuscany.spi.model.ServiceContract; + +import org.apache.tuscany.core.component.ComponentManager; + +/** + * Annotation processor for injecting <code>PersistenceUnit</code> annotations on properties. + * + * @version $Rev$ $Date$ + */ +public class PersistenceUnitProcessor extends ImplementationProcessorExtension { + /** + * Persistence unit builder + */ + private PersistenceUnitBuilder builder = new DefaultPersistenceUnitBuilder(); + private ComponentManager componentManager; + private InterfaceJavaIntrospector introspector; + + @Reference + public void setComponentManager(ComponentManager componentManager) { + this.componentManager = componentManager; + } + + @Reference + public void setIntrospector(InterfaceJavaIntrospector introspector) { + this.introspector = introspector; + } + + + @SuppressWarnings({"unchecked"}) + public void visitField(Field field, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + DeploymentContext context) throws ProcessingException { + + PersistenceUnit annotation = field.getAnnotation(PersistenceUnit.class); + if (annotation == null) { + return; + } + String unitName = annotation.unitName(); + URI unitUri = context.getComponentId().resolve(unitName); + AtomicComponent component = (AtomicComponent) componentManager.getComponent(unitUri); + EntityManagerFactory emf; + if (component == null) { + emf = builder.newEntityManagerFactory(unitName, context.getClassLoader()); + try { + ServiceContract<EntityManagerFactory> contract = + (ServiceContract) introspector.introspect(EntityManagerFactory.class); + componentManager.registerJavaObject(unitUri, contract, emf); + } catch (RegistrationException e) { + throw new ProcessingException(e); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + } else { + try { + emf = (EntityManagerFactory) component.getTargetInstance(); + } catch (TargetException e) { + throw new ProcessingException(e); + } + } + + ObjectFactory factory = new EmfObjectFactory(emf); + Resource resource = new Resource(unitName, field.getType(), field); + resource.setObjectFactory(factory); + type.add(resource); + } + + private class EmfObjectFactory implements ObjectFactory<EntityManagerFactory> { + + private EntityManagerFactory emf; + + public EmfObjectFactory(EntityManagerFactory emf) { + this.emf = emf; + } + + public EntityManagerFactory getInstance() { + return emf; + } + + } + +} diff --git a/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/PersistenceUnitScanner.java b/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/PersistenceUnitScanner.java new file mode 100644 index 0000000000..00fd02b891 --- /dev/null +++ b/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/PersistenceUnitScanner.java @@ -0,0 +1,99 @@ +/* + * 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.tuscany.service.persistence.common; + +import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import javax.persistence.spi.PersistenceUnitInfo; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +/** + * Scans the classloader for the specified persistence unit. + * + * @version $Rev$ $Date$ + */ +class PersistenceUnitScanner { + + /** Cache of persistence unit info */ + private Map<String, PersistenceUnitInfo> persistenceUnitInfos = new HashMap<String, PersistenceUnitInfo>(); + + /** + * Scans the lassloader for the specified persistence unit and creates + * an immutable representation of the information present in the matching + * persistence.xml file. + * + * @param unitName Persistence unit name. + * @param classLoader Classloader to scan. + * @return Persistence unit information. + */ + PersistenceUnitInfo getPersistenceUnitInfo(String unitName, ClassLoader classLoader) { + + synchronized (persistenceUnitInfos) { + + if(persistenceUnitInfos.containsKey(unitName)) { + return persistenceUnitInfos.get(unitName); + } + + try { + + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + + Enumeration<URL> persistenceUnitUrls = classLoader.getResources("META-INF/persistence.xml"); + while (persistenceUnitUrls.hasMoreElements()) { + + URL persistenceUnitUrl = persistenceUnitUrls.nextElement(); + Document persistenceDom = db.parse(persistenceUnitUrl.openStream()); + + String rootJarUrl = persistenceUnitUrl.toString(); + rootJarUrl = rootJarUrl.substring(0, rootJarUrl.lastIndexOf("META-INF")); + + PersistenceUnitInfo info = new TuscanyPersistenceUnitInfo(persistenceDom, classLoader, rootJarUrl); + if (!unitName.equals(info.getPersistenceUnitName())) { + continue; + } + + persistenceUnitInfos.put(unitName, info); + return info; + + } + } catch (IOException ex) { + throw new TuscanyJpaException(ex); + } catch (ParserConfigurationException ex) { + throw new TuscanyJpaException(ex); + } catch (SAXException ex) { + throw new TuscanyJpaException(ex); + } + + } + + throw new TuscanyJpaException("Unabel to find persistence unit: " + unitName); + + } + +} diff --git a/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/TuscanyJpaException.java b/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/TuscanyJpaException.java new file mode 100644 index 0000000000..2690f43f7c --- /dev/null +++ b/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/TuscanyJpaException.java @@ -0,0 +1,50 @@ +/* + * 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.tuscany.service.persistence.common; + +import org.apache.tuscany.api.TuscanyRuntimeException; + +/** + * Unexpected exception in processing JPA annotations. + * + */ +public class TuscanyJpaException extends TuscanyRuntimeException { + + /** + * Serial version UID. + */ + private static final long serialVersionUID = 2772746952304093785L; + + /** + * Initializes the message. + * @param message Message to be initialized. + */ + public TuscanyJpaException(String message) { + super(message); + } + + /** + * Initializes the underlying cause. + * @param cause Cause to be initialized. + */ + public TuscanyJpaException(Throwable cause) { + super(cause); + } + +} diff --git a/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/TuscanyPersistenceUnitInfo.java b/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/TuscanyPersistenceUnitInfo.java new file mode 100644 index 0000000000..eb1dee24a7 --- /dev/null +++ b/sandbox/old/contrib/persistence/common/src/main/java/org/apache/tuscany/service/persistence/common/TuscanyPersistenceUnitInfo.java @@ -0,0 +1,288 @@ +/* + * 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.tuscany.service.persistence.common; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.persistence.spi.ClassTransformer; +import javax.persistence.spi.PersistenceUnitInfo; +import javax.persistence.spi.PersistenceUnitTransactionType; +import javax.sql.DataSource; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import static org.apache.tuscany.service.persistence.common.JpaConstants.*; + +/** + * Encpasulates the information in the persistence.xml file. + * + * This class is expected to be interogated by the provider only + * during the creation of the entity manager factory. Hence none + * of the values are cached, rather every time a property is queried + * the underlying DOM is interogated. + * + */ +class TuscanyPersistenceUnitInfo implements PersistenceUnitInfo { + + /** Persistence DOM */ + private Node persistenceDom; + + /** Classloader */ + private ClassLoader classLoader; + + /** Root Url */ + private String rootUrl; + + /** XPath API */ + XPath xpath = XPathFactory.newInstance().newXPath(); + + /** + * Initializes the properties. + * + * @param persistenceDom + * @param classLoader + * @param rootUrl + */ + public TuscanyPersistenceUnitInfo(Node persistenceDom, ClassLoader classLoader, String rootUrl) { + this.persistenceDom = persistenceDom; + this.classLoader = classLoader; + this.rootUrl = rootUrl; + } + + /* (non-Javadoc) + * @see javax.persistence.spi.PersistenceUnitInfo#addTransformer(javax.persistence.spi.ClassTransformer) + */ + public void addTransformer(ClassTransformer classTransformer) { + } + + /* (non-Javadoc) + * @see javax.persistence.spi.PersistenceUnitInfo#excludeUnlistedClasses() + */ + public boolean excludeUnlistedClasses() { + return getBooleanValue(persistenceDom, EXCLUDE_UNLISTED_CLASSES); + } + + /* (non-Javadoc) + * @see javax.persistence.spi.PersistenceUnitInfo#getClassLoader() + */ + public ClassLoader getClassLoader() { + return classLoader; + } + + /* (non-Javadoc) + * @see javax.persistence.spi.PersistenceUnitInfo#getJarFileUrls() + */ + public List<URL> getJarFileUrls() { + + List<String> jarFiles = getMultipleValues(persistenceDom, JAR_FILE); + try { + List<URL> jarUrls = new LinkedList<URL>(); + for (String jarFile : jarFiles) { + jarUrls.add(new URL(jarFile)); + } + return jarUrls; + } catch (MalformedURLException ex) { + throw new TuscanyJpaException(ex); + } + + } + + /* (non-Javadoc) + * @see javax.persistence.spi.PersistenceUnitInfo#getJtaDataSource() + */ + public DataSource getJtaDataSource() { + + String jtaDsName = getSingleValue(persistenceDom, JTA_DATA_SOURCE); + if (jtaDsName == null || "".equals(jtaDsName)) { + return null; + } + return lookupDataSource(jtaDsName); + + } + + /* (non-Javadoc) + * @see javax.persistence.spi.PersistenceUnitInfo#getManagedClassNames() + */ + public List<String> getManagedClassNames() { + return getMultipleValues(persistenceDom, CLASS); + } + + /* (non-Javadoc) + * @see javax.persistence.spi.PersistenceUnitInfo#getMappingFileNames() + */ + public List<String> getMappingFileNames() { + return getMultipleValues(persistenceDom, MAPPING_FILE); + } + + /* (non-Javadoc) + * @see javax.persistence.spi.PersistenceUnitInfo#getNewTempClassLoader() + */ + public ClassLoader getNewTempClassLoader() { + return null; + } + + /* (non-Javadoc) + * @see javax.persistence.spi.PersistenceUnitInfo#getNonJtaDataSource() + */ + public DataSource getNonJtaDataSource() { + + String nonJtaDsName = getSingleValue(persistenceDom, NON_JTA_DATA_SOURCE); + if (nonJtaDsName == null || "".equals(nonJtaDsName)) { + return null; + } + return lookupDataSource(nonJtaDsName); + + } + + /* (non-Javadoc) + * @see javax.persistence.spi.PersistenceUnitInfo#getPersistenceProviderClassName() + */ + public String getPersistenceProviderClassName() { + return getSingleValue(persistenceDom, PROVIDER); + } + + /* (non-Javadoc) + * @see javax.persistence.spi.PersistenceUnitInfo#getPersistenceUnitName() + */ + public String getPersistenceUnitName() { + return getSingleValue(persistenceDom, NAME); + } + + /* (non-Javadoc) + * @see javax.persistence.spi.PersistenceUnitInfo#getPersistenceUnitRootUrl() + */ + public URL getPersistenceUnitRootUrl() { + try { + return new URL(rootUrl); + } catch (MalformedURLException ex) { + throw new TuscanyJpaException(ex); + } + } + + /* (non-Javadoc) + * @see javax.persistence.spi.PersistenceUnitInfo#getProperties() + */ + public Properties getProperties() { + return getProperties(persistenceDom); + } + + /* (non-Javadoc) + * @see javax.persistence.spi.PersistenceUnitInfo#getTransactionType() + */ + public PersistenceUnitTransactionType getTransactionType() { + String transactionType = getSingleValue(persistenceDom, TRANSACTION_TYPE); + return "JTA".equals(transactionType) ? PersistenceUnitTransactionType.JTA : PersistenceUnitTransactionType.RESOURCE_LOCAL; + } + + /* + * Extracts additional properties. + */ + private Properties getProperties(Node root) { + + try { + NodeList nodeList = (NodeList) xpath.evaluate(PROPERTY, root, XPathConstants.NODESET); + Properties data = new Properties(); + + for (int i = 0; i < nodeList.getLength(); i++) { + Element property = (Element) nodeList.item(i); + data.put(property.getAttribute(PROPERTY_NAME), property.getAttribute(PROPERTY_VALUE)); + } + + return data; + } catch (XPathExpressionException ex) { + throw new TuscanyJpaException(ex); + } + + } + + /* + * Gets multiple values for the specified expression. + */ + private List<String> getMultipleValues(Node context, String expression) { + + try { + NodeList nodeList = (NodeList) xpath.evaluate(expression, context, XPathConstants.NODESET); + List<String> data = new LinkedList<String>(); + + for (int i = 0; i < nodeList.getLength(); i++) { + data.add(nodeList.item(i).getTextContent()); + } + + return data; + } catch (XPathExpressionException ex) { + throw new TuscanyJpaException(ex); + } + + } + + /* + * Gets single value for the specified expression. + */ + private String getSingleValue(Node context, String expression) { + + try { + return xpath.evaluate(expression, context); + } catch (XPathExpressionException ex) { + throw new TuscanyJpaException(ex); + } + + } + + /* + * Gets single value for the specified expression. + */ + private boolean getBooleanValue(Node context, String expression) { + return Boolean.valueOf(getSingleValue(context, expression)); + } + + /* + * Looks up datasource. + */ + private DataSource lookupDataSource(String dsName) { + Context ctx = null; + try { + ctx = new InitialContext(); + return (DataSource) ctx.lookup(dsName); + } catch (NamingException ex) { + throw new TuscanyJpaException(ex); + } finally { + if (ctx != null) { + try { + ctx.close(); + } catch (NamingException ex) { + throw new TuscanyJpaException(ex); + } + } + } + } + +} |