blob: bdd6b31a46de5aa57523558778941e9eac5aec9c [file] [log] [blame]
/*******************************************************************************
* 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);
}
}
}