You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by jg...@apache.org on 2011/12/13 23:05:28 UTC

svn commit: r1213958 - in /openjpa/trunk: openjpa-kernel/src/main/java/org/apache/openjpa/meta/ openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/ openjpa-lib/src/main/java/org/apache/openjpa/lib/util/

Author: jgrassel
Date: Tue Dec 13 22:05:28 2011
New Revision: 1213958

URL: http://svn.apache.org/viewvc?rev=1213958&view=rev
Log:
OPENJPA-2094: Metadata processing needs to support jar:file URLs that address Jar directories

Added:
    openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/JarFileURLMetaDataIterator.java   (with props)
Modified:
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractCFMetaDataFactory.java
    openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/J2DoPrivHelper.java

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractCFMetaDataFactory.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractCFMetaDataFactory.java?rev=1213958&r1=1213957&r2=1213958&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractCFMetaDataFactory.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractCFMetaDataFactory.java Tue Dec 13 22:05:28 2011
@@ -44,6 +44,7 @@ import org.apache.openjpa.conf.OpenJPACo
 import org.apache.openjpa.lib.meta.ClassArgParser;
 import org.apache.openjpa.lib.meta.ClasspathMetaDataIterator;
 import org.apache.openjpa.lib.meta.FileMetaDataIterator;
+import org.apache.openjpa.lib.meta.JarFileURLMetaDataIterator;
 import org.apache.openjpa.lib.meta.MetaDataFilter;
 import org.apache.openjpa.lib.meta.MetaDataIterator;
 import org.apache.openjpa.lib.meta.MetaDataParser;
@@ -703,12 +704,18 @@ public abstract class AbstractCFMetaData
                         continue;
                     }
                 }
-                if ("jar".equals(url.getProtocol())
-                    && url.getPath().endsWith("!/")) {
-                    if (log.isTraceEnabled())
-                        log.trace(_loc.get("scanning-jar-url", url));
-                    scan(new ZipFileMetaDataIterator(url,
-                        newMetaDataFilter()), cparser, names, true, url);
+                if ("jar".equals(url.getProtocol())) {
+                    if (url.getPath().endsWith("!/")) {
+                        if (log.isTraceEnabled())
+                            log.trace(_loc.get("scanning-jar-url", url));
+                        scan(new ZipFileMetaDataIterator(url,
+                            newMetaDataFilter()), cparser, names, true, url);
+                    } else {
+                        if (log.isTraceEnabled())
+                            log.trace(_loc.get("scanning-jar-url", url));
+                        scan(new JarFileURLMetaDataIterator(url,
+                            newMetaDataFilter()), cparser, names, true, url);
+                    }                   
                 } else if (url.getPath().endsWith(".jar")) {
                     if (log.isTraceEnabled())
                         log.trace(_loc.get("scanning-jar-at-url", url));

Added: openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/JarFileURLMetaDataIterator.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/JarFileURLMetaDataIterator.java?rev=1213958&view=auto
==============================================================================
--- openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/JarFileURLMetaDataIterator.java (added)
+++ openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/JarFileURLMetaDataIterator.java Tue Dec 13 22:05:28 2011
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.lib.meta;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.JarURLConnection;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import org.apache.openjpa.lib.util.J2DoPrivHelper;
+
+/**
+ * Iterator over all metadata resources in a given resource addressed by a jar:file URL.
+ * 
+ */
+public class JarFileURLMetaDataIterator implements MetaDataIterator, MetaDataFilter.Resource {
+    private final MetaDataFilter _filter;
+    private final JarFile _jarFile;
+    private final JarEntry _jarTargetEntry;
+
+    private int index = 0;
+    private JarEntry _last = null;
+    private final ArrayList<JarEntry> _entryList = new ArrayList<JarEntry>();
+
+    public JarFileURLMetaDataIterator(URL url, MetaDataFilter filter) throws IOException {
+        if (url == null) {
+            _jarFile = null;
+            _jarTargetEntry = null;
+        } else {
+            JarURLConnection jarURLConn = (JarURLConnection) url.openConnection();
+            jarURLConn.setDefaultUseCaches(false);
+
+            try {
+                _jarFile = AccessController.doPrivileged(J2DoPrivHelper.getJarFileAction(jarURLConn));
+                _jarTargetEntry = AccessController.doPrivileged(J2DoPrivHelper.getJarEntryAction(jarURLConn));
+
+                if (_jarTargetEntry.isDirectory()) {
+                    Enumeration<JarEntry> jarEntryEnum = _jarFile.entries();
+                    while (jarEntryEnum.hasMoreElements()) {
+                        JarEntry jarEntry = jarEntryEnum.nextElement();
+                        if (jarEntry.getName().startsWith(_jarTargetEntry.getName())) {
+                            _entryList.add(jarEntry);
+                        }
+                    }
+                } else {
+                    _entryList.add(_jarTargetEntry);
+                }
+            } catch (PrivilegedActionException pae) {
+                throw (IOException) pae.getException();
+            }
+        }
+
+        _filter = filter;
+    }
+
+    /**
+     * Return whether there is another resource to iterate over.
+     */
+    public boolean hasNext() throws IOException {
+        if (_entryList.size() <= index) {
+            return false;
+        }
+
+        // Search for next metadata file
+        while (index < _entryList.size()) {
+            if (_filter != null && !_filter.matches(this)) {
+                index++;
+                continue;
+            }
+            break;
+        }
+
+        return (index < _entryList.size());
+    }
+
+    /**
+     * Return the next metadata resource.
+     */
+    public Object next() throws IOException {
+        if (!hasNext()) {
+            throw new NoSuchElementException();
+        }
+
+        String ret = _entryList.get(index).getName();
+        _last = _entryList.get(index);
+        index++;
+
+        return ret;
+    }
+
+    /**
+     * Return the last-iterated metadata resource content as a stream.
+     */
+    public InputStream getInputStream() throws IOException {
+        if (_last == null)
+            throw new IllegalStateException();
+        return _jarFile.getInputStream(_last);
+    }
+
+    /**
+     * Return the last-iterated metadata resource content as a file, or null if not an extant file.
+     */
+    public File getFile() throws IOException {
+        if (_last == null)
+            throw new IllegalStateException();
+        return null;
+    }
+
+    /**
+     * Close the resources used by this iterator.
+     */
+    public void close() {
+        try {
+            if (_jarFile != null)
+                _jarFile.close();
+        } catch (IOException ioe) {
+        }
+    }
+
+    // ////////////////////////////////////////
+    // MetaDataFilter.Resource implementation
+    // ////////////////////////////////////////
+
+    /**
+     * The name of the resource.
+     */
+    public String getName() {
+        if (index < _entryList.size()) {
+            return _entryList.get(index).getName();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Resource content.
+     */
+    public byte[] getContent() throws IOException {
+        if (_entryList.size() <= index) {
+            return new byte[0];
+        }
+
+        long size = _entryList.get(index).getSize();
+        if (size == 0)
+            return new byte[0];
+
+        InputStream in = _jarFile.getInputStream(_entryList.get(index));
+        byte[] content;
+        if (size < 0) {
+            ByteArrayOutputStream bout = new ByteArrayOutputStream();
+            byte[] buf = new byte[1024];
+            for (int r; (r = in.read(buf)) != -1; bout.write(buf, 0, r))
+                ;
+            content = bout.toByteArray();
+        } else {
+            content = new byte[(int) size];
+            int offset = 0;
+            int read;
+            while (offset < size && (read = in.read(content, offset, (int) size - offset)) != -1) {
+                offset += read;
+            }
+        }
+        in.close();
+        return content;
+    }
+}

Propchange: openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/JarFileURLMetaDataIterator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/J2DoPrivHelper.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/J2DoPrivHelper.java?rev=1213958&r1=1213957&r2=1213958&view=diff
==============================================================================
--- openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/J2DoPrivHelper.java (original)
+++ openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/J2DoPrivHelper.java Tue Dec 13 22:05:28 2011
@@ -31,6 +31,7 @@ import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.net.InetAddress;
+import java.net.JarURLConnection;
 import java.net.MalformedURLException;
 import java.net.ServerSocket;
 import java.net.Socket;
@@ -43,6 +44,8 @@ import java.security.PrivilegedException
 import java.util.Enumeration;
 import java.util.Properties;
 import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
 import java.util.zip.ZipFile;
 
 import javax.validation.ConstraintViolation;
@@ -962,6 +965,42 @@ public abstract class J2DoPrivHelper {
             }
         };
     }
+    
+    /**
+     * Return a PrivilegedExceptionAction object for con.getJarFile().
+     * 
+     * Requires security policy:
+     *   'permission java.io.FilePermission "read";'
+     * 
+     * @return JarFile
+     * @throws IOException
+     */
+    public static final PrivilegedExceptionAction<JarFile> getJarFileAction(final JarURLConnection con)
+        throws IOException {
+        return new PrivilegedExceptionAction<JarFile>() {
+            public JarFile run() throws IOException {
+                return con.getJarFile();
+            }
+        };
+    }
+    
+    /**
+     * Return a PrivilegedExceptionAction object for con.getJarEntry().
+     * 
+     * Requires security policy:
+     *   'permission java.io.FilePermission "read";'
+     * 
+     * @return JarFile
+     * @throws IOException
+     */
+    public static final PrivilegedExceptionAction<JarEntry> getJarEntryAction(final JarURLConnection con)
+        throws IOException {
+        return new PrivilegedExceptionAction<JarEntry>() {
+            public JarEntry run() throws IOException {
+                return con.getJarEntry();
+            }
+        };
+    }   
 
     /**
      * Return a PrivilegeAction object for new serp.bytecode.Code().