mirror of https://github.com/apache/openjpa.git
OPENJPA-2094: Metadata processing needs to support jar:file URLs that address Jar directories
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1213958 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
e3fbbfbced
commit
1a383857ff
|
@ -44,6 +44,7 @@ import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
|
|||
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 AbstractCFMetaDataFactory
|
|||
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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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.PrivilegedExceptionAction;
|
|||
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().
|
||||
|
|
Loading…
Reference in New Issue