| /******************************************************************************* |
| * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 |
| * which accompanies this distribution. |
| * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html |
| * and the Eclipse Distribution License is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * Contributors: |
| * dclarke - initial |
| ******************************************************************************/ |
| package org.eclipse.persistence.script; |
| |
| import java.lang.reflect.Field; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.ServiceLoader; |
| |
| import javax.persistence.EntityManagerFactory; |
| |
| import org.eclipse.persistence.config.PersistenceUnitProperties; |
| import org.eclipse.persistence.dynamic.DynamicClassLoader; |
| import org.eclipse.persistence.dynamic.DynamicEntity; |
| import org.eclipse.persistence.dynamic.DynamicType; |
| import org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl; |
| import org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider; |
| import org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl; |
| import org.eclipse.persistence.internal.jpa.deployment.SEPersistenceUnitInfo; |
| import org.eclipse.persistence.internal.sessions.DatabaseSessionImpl; |
| import org.eclipse.persistence.jpa.dynamic.JPADynamicHelper; |
| import org.eclipse.persistence.jpa.rs.PersistenceContext; |
| import org.eclipse.persistence.jpa.rs.PersistenceContextFactory; |
| import org.eclipse.persistence.jpa.rs.PersistenceContextFactoryProvider; |
| import org.eclipse.persistence.jpa.rs.PersistenceFactoryBase; |
| import org.eclipse.persistence.logging.SessionLog; |
| import org.eclipse.persistence.sessions.factories.SessionManager; |
| import org.eclipse.persistence.tools.schemaframework.SchemaManager; |
| |
| public class PersistenceUnit { |
| |
| private DynamicClassLoader dcl = new DynamicClassLoader(Thread.currentThread().getContextClassLoader()); |
| |
| private List<EntityType> types = new ArrayList<EntityType>(); |
| |
| private String packageName = "org.eclipse.pesistence.dynamic.model."; |
| |
| private String name; |
| |
| private Map<String, Object> properties = new HashMap<String, Object>(); |
| |
| public PersistenceUnit(String name, ClassLoader loader) { |
| this.name = name; |
| this.packageName = packageName + name + "."; |
| setClassLoader(loader); |
| |
| System.out.println("PersistenceUnit::" + name); |
| } |
| |
| public PersistenceUnit(String name) { |
| this(name, null); |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| public Map<String, Object> getProperties() { |
| return this.properties; |
| } |
| |
| public DynamicClassLoader getDynamicClassLoader() { |
| return dcl; |
| } |
| |
| public void setDynamicClassLoader(DynamicClassLoader dcl) { |
| this.dcl = dcl; |
| } |
| |
| public void setClassLoader(ClassLoader cl) { |
| if (cl instanceof DynamicClassLoader) { |
| dcl = (DynamicClassLoader) cl; |
| } else { |
| dcl = new DynamicClassLoader(cl == null ? Thread.currentThread().getContextClassLoader() : cl); |
| } |
| } |
| |
| protected List<EntityType> getTypes() { |
| return this.types; |
| } |
| |
| public String getPackageName() { |
| return packageName; |
| } |
| |
| public void setPackageName(String packageName) { |
| this.packageName = packageName; |
| } |
| |
| public EntityType addType(String name, String... tableNames) { |
| @SuppressWarnings("unchecked") |
| Class<DynamicEntity> dynamicClass = (Class<DynamicEntity>) getDynamicClassLoader().createDynamicClass(getPackageName() + name); |
| EntityType type = new EntityType(dynamicClass, tableNames); |
| getTypes().add(type); |
| return type; |
| } |
| |
| public EntityType addType(String name) { |
| @SuppressWarnings("unchecked") |
| Class<DynamicEntity> dynamicClass = (Class<DynamicEntity>) getDynamicClassLoader().createDynamicClass(getPackageName() + name); |
| EntityType type = new EntityType(dynamicClass, new String[] {name.toUpperCase()}); |
| getTypes().add(type); |
| return type; |
| } |
| |
| public void setDataSource(String dsName) { |
| getProperties().put(PersistenceUnitProperties.NON_JTA_DATASOURCE, dsName); |
| } |
| |
| /** |
| * Launch the dynamic PU and make it available through the REST interface. |
| * @param schemaGeneration |
| */ |
| public void create(String version, String schemaGeneration) { |
| DynamicType[] dynamicTypes = new DynamicType[getTypes().size()]; |
| for (int index = 0; index < getTypes().size(); index++) { |
| dynamicTypes[index] = getTypes().get(index).getBuilder().getType(); |
| } |
| |
| // Create an entity manager factory. |
| EntityManagerFactory emf = createEntityManagerFactory(getDynamicClassLoader(), version); |
| |
| // Create JPA Dynamic Helper (with the emf above) and after the types |
| // have been created and add the types through the helper. |
| JPADynamicHelper helper = new JPADynamicHelper(emf); |
| helper.addTypes(true, true, dynamicTypes); |
| |
| // Schema Generation |
| if (PersistenceUnitProperties.CREATE_ONLY.equals(schemaGeneration)) { |
| } else if (PersistenceUnitProperties.DROP_AND_CREATE.equals(schemaGeneration)) { |
| new SchemaManager(helper.getSession()).replaceDefaultTables(); |
| } else if (PersistenceUnitProperties.CREATE_OR_EXTEND.equals(schemaGeneration)) { |
| new SchemaManager(helper.getSession()).extendDefaultTables(true); |
| } else if (schemaGeneration != null) { |
| throw new IllegalArgumentException("Invalid schema-gen: " + schemaGeneration); |
| } |
| } |
| |
| private EntityManagerFactory createEntityManagerFactory(DynamicClassLoader dcl, String version) { |
| Map<String, Object> props = new HashMap<String, Object>(); |
| SEPersistenceUnitInfo info = new SEPersistenceUnitInfo(); |
| info.setClassLoader(dcl); |
| info.setPersistenceUnitName(getName()); |
| |
| Properties p = new Properties(); |
| p.putAll(getProperties()); |
| p.put(PersistenceUnitProperties.CLASSLOADER, dcl); |
| p.put(PersistenceUnitProperties.WEAVING, "static"); |
| p.put(PersistenceUnitProperties.LOGGING_LEVEL, SessionLog.FINE_LABEL); |
| |
| info.setProperties(p); |
| |
| if (EntityManagerFactoryProvider.getEmSetupImpls().containsKey(getName())) { |
| EntityManagerFactoryProvider.getEmSetupImpls().remove(getName()); |
| } |
| if (SessionManager.getManager().getSessions().containsKey(getName())) { |
| SessionManager.getManager().destroySession(getName()); |
| } |
| |
| EntityManagerSetupImpl setup = new EntityManagerSetupImpl(getName(), getName()); |
| setup.predeploy(info, props); |
| |
| // call to setup.deploy prevents execution of prelogin. Prelogin must be run to |
| // get JPA-RS mappings populated correctly |
| //DatabaseSessionImpl sessionImpl = setup.deploy(dcl, props); |
| |
| DatabaseSessionImpl sessionImpl = setup.getSession(); |
| |
| if (EntityManagerFactoryProvider.getEmSetupImpls().containsKey(getName())) { |
| EntityManagerFactoryProvider.getEmSetupImpls().put(getName(), setup); |
| } |
| |
| EntityManagerFactoryImpl emf = new EntityManagerFactoryImpl(sessionImpl); |
| |
| PersistenceFactoryBase factory = (PersistenceFactoryBase) getFactory(dcl); |
| PersistenceContext bootstrapPersistenceContext = factory.bootstrapPersistenceContext(getName(), emf, null, version, true); |
| |
| getDynamicPersistenceContexts(factory).put(getName(), bootstrapPersistenceContext); |
| |
| return emf; |
| } |
| |
| private static PersistenceContextFactory getFactory(ClassLoader loader) { |
| ServiceLoader<PersistenceContextFactoryProvider> contextFactoryLoader = ServiceLoader.load(PersistenceContextFactoryProvider.class, loader); |
| |
| for (PersistenceContextFactoryProvider provider : contextFactoryLoader) { |
| PersistenceContextFactory factory = provider.getPersistenceContextFactory(null); |
| if (factory != null) { |
| return factory; |
| } |
| } |
| return null; |
| } |
| |
| @SuppressWarnings("unchecked") |
| private static Map<String, PersistenceContext> getDynamicPersistenceContexts(PersistenceFactoryBase factory) { |
| try { |
| Field field = factory.getClass().getDeclaredField("dynamicPersistenceContexts"); |
| field.setAccessible(true); |
| return (Map<String, PersistenceContext>) field.get(factory); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| throw new RuntimeException(e); |
| } |
| } |
| |
| } |