Is it possible to create a URL pointing to an object in memory?

I am trying to expand my library for Swing and JPA integration by setting the JPA config as automatic (and portable), how can this be done, and this means that the <class> elements are added programmatically. (I know that this can be done using Hibernate AnnotationConfiguration or EclipseLInk ServerSession , but portability). I would also like to avoid using Spring just for this purpose.

I can create persistence.xml on the fly and fill it with <class> elements from the specified packages (via the Reflections library). The problem starts when I try to pass this persistence.xml to the JPA provider. The only way I can think of is to create a URLClassLoader , but I can't figure out how to make me write the file to disk first, for the only way I can get a valid URL . Configuring the socket to serve the file using the URL ( localhost:xxxx ) seems ... I don't know, evil?

Does anyone have an idea how I can solve this problem? I know that it is a lot of work not to use one library, but I just would like to know if this can be done.

EDIT (try to make it more clear):

Dynamically generated XML is stored in a String object. I do not know how to make it available to the continuity provider. In addition, I want to not write the file to disk.

For my problem, the persistence provider is just a class that scans the classpath for META-INF/persistence.xml . Some implementations can be made to accept the dynamic creation of XML , but there is no common interface (especially for the important part of the file, <class> tags).

My idea is to set up a custom ClassLoader - if you have others, I would be grateful, I am not tuned for this.

The only easily extensible / customizable I could find was URLClassLoader . It works with URL objects, and I don’t know if I can create it without actually writing the XML to disk.

What I am setting up but working by writing persistenceXmlFile = new File("META-INF/persistence.xml") to disk:

 Thread.currentThread().setContextClassLoader( new URLResourceClassLoader( new URL[] { persistenceXmlFile.toURI().toURL() }, Thread.currentThread().getContextClassLoader() ) ); 

URLResourceClassLoader is a subclass of URLClassLoader that allows you to search for resources as well as classes, overriding public Enumeration<URL> findResources(String name) .

+7
source share
1 answer

Maybe a little late (after 4 years), but for others looking for a similar solution, you can use the factory URL that I created:

 public class InMemoryURLFactory { public static void main(String... args) throws Exception { URL url = InMemoryURLFactory.getInstance().build("/this/is/a/test.txt", "This is a test!"); byte[] data = IOUtils.toByteArray(url.openConnection().getInputStream()); // Prints out: This is a test! System.out.println(new String(data)); } private final Map<URL, byte[]> contents = new WeakHashMap<>(); private final URLStreamHandler handler = new InMemoryStreamHandler(); private static InMemoryURLFactory instance = null; public static synchronized InMemoryURLFactory getInstance() { if(instance == null) instance = new InMemoryURLFactory(); return instance; } private InMemoryURLFactory() { } public URL build(String path, String data) { try { return build(path, data.getBytes("UTF-8")); } catch (UnsupportedEncodingException ex) { throw new RuntimeException(ex); } } public URL build(String path, byte[] data) { try { URL url = new URL("memory", "", -1, path, handler); contents.put(url, data); return url; } catch (MalformedURLException ex) { throw new RuntimeException(ex); } } private class InMemoryStreamHandler extends URLStreamHandler { @Override protected URLConnection openConnection(URL u) throws IOException { if(!u.getProtocol().equals("memory")) { throw new IOException("Cannot handle protocol: " + u.getProtocol()); } return new URLConnection(u) { private byte[] data = null; @Override public void connect() throws IOException { initDataIfNeeded(); checkDataAvailability(); // Protected field from superclass connected = true; } @Override public long getContentLengthLong() { initDataIfNeeded(); if(data == null) return 0; return data.length; } @Override public InputStream getInputStream() throws IOException { initDataIfNeeded(); checkDataAvailability(); return new ByteArrayInputStream(data); } private void initDataIfNeeded() { if(data == null) data = contents.get(u); } private void checkDataAvailability() throws IOException { if(data == null) throw new IOException("In-memory data cannot be found for: " + u.getPath()); } }; } } } 
+3
source

All Articles