是否可以创建指向内存中对象的URL? [英] Is it possible to create an URL pointing to an in-memory object?

查看:90
本文介绍了是否可以创建指向内存中对象的URL?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过来扩展我的库以集成 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆