package br.com.geraldoferraz.testyourquery.util; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.StringWriter; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.Arrays; import java.util.Enumeration; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import javax.persistence.spi.PersistenceUnitTransactionType; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.InvocationHandler; import org.w3c.dom.Document; import org.w3c.dom.Element; public class RuntimePersistenceGenerator { private final String unitName; private final PersistenceUnitTransactionType transactionType; private final Set<Class<?>> classes = new LinkedHashSet<Class<?>>(); private final Map<String, String> properties = new LinkedHashMap<String, String>(); private final String providerName; public RuntimePersistenceGenerator(String unitName, PersistenceUnitTransactionType transactionType, String providerName) { this.unitName = unitName; this.transactionType = transactionType; this.providerName = providerName; try { ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(createProxy(originalClassLoader)); } catch (final Exception e) { throw new RuntimeException(e); } } public RuntimePersistenceGenerator addProperty(final String key, final String value) { if (key == null) { throw new IllegalArgumentException("Property key cannot be null"); } if (value == null) { throw new IllegalArgumentException("Property value cannot be null"); } properties.put(key, value); return this; } public RuntimePersistenceGenerator addAnnotatedClass(final Class<?> clazz) { classes.add(clazz); return this; } public EntityManagerFactory createEntityManagerFactory() { return Persistence.createEntityManagerFactory(this.unitName); } protected Document createDocument() throws ParserConfigurationException { final Document doc = createXmlDocument(); final Element persistence = createPersistenceElement(doc); doc.appendChild(persistence); final Element unit = createPersistenceUnitElement(doc); persistence.appendChild(unit); unit.appendChild(createProviderElement(doc, providerName)); for (final Class<?> clazz : this.classes) { final Element classElement = doc.createElement("class"); classElement.setTextContent(clazz.getName()); unit.appendChild(classElement); } if (!properties.isEmpty()) { final Element propertiesElement = createPropertiesElement(doc); unit.appendChild(propertiesElement); } return doc; } private Element createPersistenceUnitElement(Document doc) { final Element unit = doc.createElement("persistence-unit"); unit.setAttribute("name", unitName); unit.setAttribute("transaction-type", transactionType.name()); return unit; } private Element createPropertiesElement(Document doc) { final Element propertiesElement = doc.createElement("properties"); for (final Map.Entry<String, String> entry : properties.entrySet()) { final Element property = createPropertyElement(doc, entry); propertiesElement.appendChild(property); } return propertiesElement; } private Element createPropertyElement(Document doc, Map.Entry<String, String> entry) { final Element property = doc.createElement("property"); property.setAttribute("name", entry.getKey()); property.setAttribute("value", entry.getValue()); return property; } protected Element createPersistenceElement(final Document doc) { final Element persistence = doc.createElement("persistence"); // persistence.setAttribute("version", "2.0"); persistence.setAttribute("version", "1.0"); persistence.setAttribute("xmlns", "http://java.sun.com/xml/ns/persistence"); persistence.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); // persistence.setAttribute("xsi:schemaLocation", "http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"); persistence.setAttribute("xsi:schemaLocation", "http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"); return persistence; } protected Element createProviderElement(final Document doc, final String provider) { final Element element = doc.createElement("provider"); element.setTextContent(provider); return element; } protected Document createXmlDocument() throws ParserConfigurationException { final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); final DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); return docBuilder.newDocument(); } public ClassLoader createClassLoader(final String persistenceContent, final ClassLoader originalClassLoader) { return new ClassLoader() { @Override protected Enumeration<URL> findResources(final String name) throws IOException { if ("META-INF/persistence.xml".equals(name)) { final File file = getTempFile(); BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))); bufferedWriter.write(persistenceContent); bufferedWriter.close(); final URL url = file.toURI().toURL(); return java.util.Collections.enumeration(new HashSet<URL>(Arrays.asList(url))); } return originalClassLoader.getResources(name); } }; } private static File getTempFile() throws IOException { File temp = File.createTempFile("meta", Long.toString(System.nanoTime())); temp.delete(); temp.mkdir(); File directory = new File(temp, "META-INF"); directory.delete(); directory.mkdir(); File persistenceXMLFile = new File(directory, "persistence.xml"); return persistenceXMLFile; } public String generateXml() throws TransformerException, ParserConfigurationException { final Document doc = createDocument(); final TransformerFactory transformerFactory = TransformerFactory.newInstance(); final Transformer transformer = transformerFactory.newTransformer(); final DOMSource source = new DOMSource(doc); final StringWriter writer = new StringWriter(); final StreamResult result = new StreamResult(writer); transformer.transform(source, result); return writer.toString(); } @Override public String toString() { try { return generateXml(); } catch (TransformerException e) { throw new RuntimeException(e); } catch (ParserConfigurationException e) { throw new RuntimeException(e); } } private URLClassLoader createProxy(final ClassLoader cl) throws MalformedURLException { Enhancer e = new Enhancer(); e.setSuperclass(URLClassLoader.class); e.setCallback(new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("getResources") && "META-INF/persistence.xml".equals((String) args[0])) { final String persistenceContent = generateXml(); final File file = getTempFile(); BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))); bufferedWriter.write(persistenceContent); bufferedWriter.close(); final URL url = file.toURI().toURL(); return java.util.Collections.enumeration(new HashSet<URL>(Arrays.asList(url))); } else { return method.invoke(cl, args); } } }); URL[] arrayDeURL = new URL[] { new URL("http://google.com.br") }; Class<?>[] array = new Class<?>[] { arrayDeURL.getClass() }; URLClassLoader f = (URLClassLoader) e.create(array, new Object[] { arrayDeURL }); return f; } }