blob: 839c96155ed39e3cc98ee02d601858132500368e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* dclarke - TODO
******************************************************************************/
package org.eclipse.persistence.jpa.rs;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ejb.Singleton;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.dynamic.DynamicClassLoader;
import org.eclipse.persistence.jpa.Archive;
import org.eclipse.persistence.jpa.rs.metadata.Application;
import org.eclipse.persistence.jpa.rs.metadata.MetadataStore;
import org.eclipse.persistence.jpa.rs.util.InMemoryArchive;
/**
* Factory for the creation of persistence contexts (JPA and JAXB). These
* contexts are for the persistence of both the meta-model as well as the
* dynamic persistence contexts for the hosted applications.
*
* @author douglas.clarke, tom.ware
*/
@Singleton
public class PersistenceFactory {
public static final String CHANGE_NOTIFICATION_LISTENER = "jpars.change-notification-listener";
private Map<String, PersistenceContext> persistenceContexts = new HashMap<String, PersistenceContext>();
private MetadataStore metadataStore;
public PersistenceFactory(){
}
public void initialize(){
initialize(new HashMap<String, Object>());
}
public void initialize(Map<String, Object> properties){
if (metadataStore != null && !metadataStore.isInitialized()){
List<Application> applications = metadataStore.retreiveMetadata();
for (Application application: applications){
try{
URL persistenceXMLURL = new URL( application.getPersistenceXMLURL());
bootstrapPersistenceContext(application.getName(), persistenceXMLURL, properties, false);
} catch (Exception e){
// TODO proper logging
System.out.println("Exception bootstrapping PersistenceFactory for application " + application.getName());
e.printStackTrace();
}
}
}
}
public PersistenceContext bootstrapPersistenceContext(String name, String persistenceXML, Map<String, ?> originalProperties, boolean replace){
ByteArrayInputStream stream = new ByteArrayInputStream(persistenceXML.getBytes());
InMemoryArchive archive = new InMemoryArchive(stream);
return bootstrapPersistenceContext(name, archive, null, originalProperties, replace);
}
public PersistenceContext bootstrapPersistenceContext(String name, URL persistenceXMLURL, Map<String, ?> originalProperties, boolean replace) throws IOException{
InMemoryArchive archive = new InMemoryArchive(persistenceXMLURL.openStream());
return bootstrapPersistenceContext(name, archive, persistenceXMLURL.toString(), originalProperties, replace);
}
public PersistenceContext bootstrapPersistenceContext(String name, InputStream persistenceXMLStream, Map<String, ?> originalProperties, boolean replace){
InMemoryArchive archive = new InMemoryArchive(persistenceXMLStream);
return bootstrapPersistenceContext(name, archive, null, originalProperties, replace);
}
public PersistenceContext bootstrapPersistenceContext(String name, Archive archive, String persistenceXMLLocation, Map<String, ?> originalProperties, boolean replace){
initialize();
PersistenceContext persistenceContext = getPersistenceContext(name);
if (persistenceContext == null || replace){
DynamicClassLoader dcl = new DynamicClassLoader(Thread.currentThread().getContextClassLoader());
Map<String, Object> properties = createProperties(dcl, originalProperties);
persistenceContext = new PersistenceContext(archive, properties, dcl);
persistenceContexts.put(name, persistenceContext);
// TODO store persistence units that were composed from a stream or a String rather than just a URL
if (persistenceXMLLocation != null){
storeApplicationMetadata(name, persistenceXMLLocation);
}
} else {
System.out.println("PersistenceContext " + name + " already started. Using existing.");
}
return persistenceContext;
}
public PersistenceContext getPersistenceContext(String name){
initialize();
return persistenceContexts.get(name);
}
public Set<String> getPersistenceContextNames(){
return persistenceContexts.keySet();
}
public void closePersistenceContext(String name){
PersistenceContext context = persistenceContexts.get(name);
if (context != null){
context.getEmf().close();
persistenceContexts.remove(name);
}
}
public void close(){
for (String key: persistenceContexts.keySet()){
persistenceContexts.get(key).stop();
}
if (metadataStore != null){
metadataStore.close();
}
}
protected static Map<String, Object> createProperties(DynamicClassLoader dcl, Map<String, ?> originalProperties) {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put(PersistenceUnitProperties.CLASSLOADER, dcl);
properties.put(PersistenceUnitProperties.WEAVING, "static");
properties.put("eclipselink.ddl-generation", "create-tables");
// properties.put("eclipselink.ddl-generation.output-mode", "database");
properties.put(PersistenceUnitProperties.LOGGING_LEVEL, "FINEST");
// For now we'll copy the connection info from admin PU
for (Map.Entry<String, ?> entry : originalProperties.entrySet()) {
if (entry.getKey().startsWith("javax") || entry.getKey().startsWith("eclipselink.log") || entry.getKey().startsWith("eclipselink.target-server")) {
properties.put(entry.getKey(), entry.getValue());
}
}
return properties;
}
public void storeApplicationMetadata(String applicationName, String persistenceXMLURL){
if (metadataStore != null){
metadataStore.persistMetadata(applicationName, persistenceXMLURL);
} else {
// TODO Real Logging
System.out.println("Unable to store metadata. No MetadataStore has been configured.");
}
}
public MetadataStore getMetadataStore() {
return metadataStore;
}
public void setMetadataStore(MetadataStore metadataStore) {
this.metadataStore = metadataStore;
}
}