2013-06-29 86 views
7

我試圖通過將JPA配置爲自動(和便攜式)配置來集成SwingJPA以擴展我的庫,並且這意味着以編程方式添加<class>元素。 (我知道它可以通過Hibernate的AnnotationConfiguration或EclipseLInk的ServerSession完成,但可移植性)。我也想避免僅僅爲了這個目的而使用Spring是否可以創建指向內存中對象的URL?

我可以隨時創建persistence.xml,並使用指定包中的<class>元素(通過反射庫)填充它。當我嘗試將此persistence.xml提供給JPA供應商時,問題就開始了。我能想到的唯一方法是設置一個URLClassLoader,但我想不出什麼方法不能讓我先將文件寫入磁盤,因爲唯一的能力是獲得有效的URL。設置一個通過URLlocalhost:xxxx)提供文件的套接字似乎......我不知道,邪惡?

有沒有人有一個想法,我可以如何解決這個問題?我知道這聽起來像避免使用一個庫很多工作,但我只想知道它是否可以完成。

EDIT(在是更清楚一試):

動態生成XML保持在String對象。我不知道如何使它可用於持久性提供者另外,我想避免將文件寫入磁盤。

對於我的問題,持久性提供者只是一個類,它掃描類路徑爲META-INF/persistence.xml。一些實現可以接受動態創建XML,但沒有通用接口(特別是對於文件的關鍵部分,<class>標籤)。

我的想法是設置一個自定義ClassLoader - 如果你有其他人,我會很感激,我不會在這一個。

我能找到的唯一可輕鬆擴展/可配置的是URLClassLoader。它適用於URL對象,並且我不知道是否可以創建一個,而無需先將XML寫入磁盤。

這就是我如何設置的東西,但它的工作通過寫persistenceXmlFile = new File("META-INF/persistence.xml")磁盤:

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

URLResourceClassLoaderURLCLassLoader的子類,允許用於查找資源,以及類,通過重寫public Enumeration<URL> findResources(String name)

+1

你真正的意思是[「記憶映射「](http://en.wikipedia.org/wiki/Memory-mapped_file),還是你的意思是」一個只存在於內存中的對象?「 –

+0

我也懷疑是否有可能,因爲內存在每個進程中被認爲是私有的...... –

+0

您使用的是什麼代碼?爲什麼它必須是URL?如果你要顯示代碼,我們可能會提出一個很好的接受一些通用的'Resource'或類似的解決方案。 – yair

回答

3

也許有點晚(4年後),但對於其他人都在尋找一個類似的解決方案,您可以使用URL工廠,我創建:

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()); 
       } 

      }; 
     } 

    } 
} 
相關問題