是否可以创建指向内存中对象的URL? [英] Is it possible to create an URL pointing to an in-memory object?
问题描述
我正在尝试通过来扩展我的库以集成
配置为可自动(和可移植),它意味着以编程方式添加 Swing
和 JPA
JPA < class>
元素。 (我知道可以通过Hibernate的 AnnotationConfiguration
或EclipseLInk的 ServerSession
来完成,但是 - 可移植性)。我也想避免使用 Spring
仅用于此目的。
I'm trying to extend my library for integrating Swing
and JPA
by making JPA
config as automatic (and portable) as can be done, and it means programmatically adding <class>
elements. (I know it can be done via Hibernate's AnnotationConfiguration
or EclipseLInk's ServerSession
, but - portability). I'd also like to avoid using Spring
just for this single purpose.
我可以创建一个 persistence.xml
动态,并用指定包中的< class>
元素填充(通过Reflections库)。当我尝试将此 persistence.xml
提供给 JPA
提供程序时,问题就开始了。我能想到的唯一方法是设置一个 URLClassLoader
,但是我想不出一种方法,不会让我先把文件写到磁盘上,唯一能够获得有效的 URL
。通过 URL
( localhost:xxxx
)设置套接字来提供文件似乎......我不知道知道,邪恶吗?
I can create a persistence.xml
on the fly, and fill it with <class>
elements from specified packages (via the Reflections library). The problem starts when I try to feed this persistence.xml
to a JPA
provider. The only way I can think of is setting up a URLClassLoader
, but I can't think of a way what wouldn't make me write the file to the disk somewhere first, for sole ability to obtain a valid URL
. Setting up a socket for serving the file via an URL
(localhost:xxxx
) seems... I don't know, evil?
有谁知道如何解决这个问题?我知道避免使用一个库听起来很多工作,但我只想知道是否可以完成。
Does anyone have an idea how I could solve this problem? I know it sounds like a lot of work to avoid using one library, but I'd just like to know if it can be done.
EDIT (尝试更清楚):
动态生成的 XML
保存在字符串
对象。我不知道如何将它提供给持久性提供程序。另外,我想避免将文件写入磁盘。
Dynamically generated XML
is kept in a String
object. I don't know how to make it available to a persistence provider. Also, I want to avoid writing the file to disk.
出于我的问题的目的,持久性提供程序只是一个扫描类路径以查找 META-INF / persistence.xml
的类。可以使一些实现接受动态创建 XML
,但是没有通用接口(特别是对于文件的关键部分,< class>
tags)。
For purpose of my problem, a persistence provider is just a class which scans the classpath for META-INF/persistence.xml
. Some implementations can be made to accept dynamic creation of XML
, but there is no common interface (especially for a crucial part of the file, the <class>
tags).
我的想法是设置自定义 ClassLoader
- 如果你有任何其他的我会很感激,我不会参与其中。
My idea is to set up a custom ClassLoader
- if you have any other I'd be grateful, I'm not set on this one.
我能找到的唯一可轻松扩展/可配置的是的URLClassLoader
。它适用于 URL
对象,我不知道是否可以创建一个而不首先实际将XML写入磁盘。
The only easily extendable/configurable one I could find was a URLClassLoader
. It works on URL
objects, and I don't know if I can create one without actually writing XML to disk first.
这就是我正在设置的方法,但它的工作原理是将 persistenceXmlFile = new文件(META-INF / persistence.xml)
写入磁盘:
That's how I'm setting things up, but it's working by writing the persistenceXmlFile = new File("META-INF/persistence.xml")
to disk:
Thread.currentThread().setContextClassLoader(
new URLResourceClassLoader(
new URL[] { persistenceXmlFile.toURI().toURL() },
Thread.currentThread().getContextClassLoader()
)
);
URLResourceClassLoader
是 URLCLassLoader
的子类,它允许通过覆盖 public Enumeration< URL>来查找资源和类。 findResources(String name)
。
URLResourceClassLoader
is URLCLassLoader
's subclass, which allows for looking up resources as well as classes, by overriding public Enumeration<URL> findResources(String name)
.
推荐答案
也许有点晚了(4年后),但对于其他正在寻找类似解决方案的人,您可以使用我创建的URL工厂:
Maybe a bit late (after 4 years), but for others that are looking for a similar solution, you may be able to use the URL factory 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());
}
};
}
}
}
这篇关于是否可以创建指向内存中对象的URL?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!