FELIX-5206: Added a patch for the support of JBoss VFS URls.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1736078 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/connect/pom.xml b/connect/pom.xml
index ba76c0a..65f61d7 100644
--- a/connect/pom.xml
+++ b/connect/pom.xml
@@ -65,6 +65,11 @@
<artifactId>org.osgi.compendium</artifactId>
<version>5.0.0</version>
</dependency>
+ <dependency>
+ <groupId>org.jboss</groupId>
+ <artifactId>jboss-vfs</artifactId>
+ <version>3.2.11.Final</version>
+ </dependency>
</dependencies>
<repositories />
<pluginRepositories />
diff --git a/connect/src/main/java/org/apache/felix/connect/PojoSR.java b/connect/src/main/java/org/apache/felix/connect/PojoSR.java
index 7f571f4..25d4782 100644
--- a/connect/src/main/java/org/apache/felix/connect/PojoSR.java
+++ b/connect/src/main/java/org/apache/felix/connect/PojoSR.java
@@ -82,7 +82,8 @@
private final EventDispatcher m_dispatcher = new EventDispatcher(m_registry);
private final Map<Long, Bundle> m_bundles = new HashMap<Long, Bundle>();
private final Map<String, Object> bundleConfig;
-
+ private final boolean m_hasVFS;
+
public static BundleDescriptor createSystemBundle() {
final Map<String, String> headers = new HashMap<String, String>();
headers.put(Constants.BUNDLE_SYMBOLICNAME, "org.apache.felix.connect");
@@ -241,6 +242,15 @@
b.getBundleContext().registerService(PackageAdmin.class.getName(), new PackageAdminImpl(), null);
m_context = b.getBundleContext();
+ boolean hasVFS;
+ try
+ {
+ hasVFS = org.jboss.vfs.VFS.class != null;
+ } catch (Throwable t) {
+ hasVFS = false;
+ }
+ m_hasVFS = hasVFS;
+
Collection<BundleDescriptor> scan = (Collection<BundleDescriptor>) config.get(PojoServiceRegistryFactory.BUNDLE_DESCRIPTORS);
if (scan != null)
@@ -317,7 +327,8 @@
Revision r;
URL url = new URL(desc.getUrl());
URL u = new URL(desc.getUrl() + "META-INF/MANIFEST.MF");
- if (u.toExternalForm().startsWith("file:"))
+ String extF = u.toExternalForm();
+ if (extF.startsWith("file:"))
{
File root = new File(URLDecoder.decode(url.getFile(), "UTF-8"));
r = new DirRevision(root);
@@ -339,6 +350,10 @@
prefix,
uc.getLastModified());
}
+ else if (m_hasVFS && extF.startsWith("vfs"))
+ {
+ r = new VFSRevision(url, url.openConnection().getLastModified());
+ }
else
{
r = new URLRevision(url, url.openConnection().getLastModified());
diff --git a/connect/src/main/java/org/apache/felix/connect/URLRevision.java b/connect/src/main/java/org/apache/felix/connect/URLRevision.java
index a084d25..721b897 100644
--- a/connect/src/main/java/org/apache/felix/connect/URLRevision.java
+++ b/connect/src/main/java/org/apache/felix/connect/URLRevision.java
@@ -18,15 +18,30 @@
*/
package org.apache.felix.connect;
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarInputStream;
+import java.lang.ref.WeakReference;
class URLRevision implements Revision
{
private final URL m_url;
private final long m_lastModified;
+ private WeakReference<byte[]> m_urlContent;
public URLRevision(URL url, long lastModified)
{
@@ -50,13 +65,39 @@
@Override
public Enumeration<String> getEntries()
{
- return Collections.enumeration(Collections.EMPTY_LIST);
- }
+ InputStream content = null;
+ JarInputStream jarInput = null;
+
+ try
+ {
+ content = getUrlContent();
+ jarInput = new JarInputStream(content);
+ List<String> entries = new ArrayList<String>();
+ JarEntry jarEntry;
+ while ((jarEntry = jarInput.getNextJarEntry()) != null)
+ {
+ entries.add(jarEntry.getName());
+ }
+ return Collections.enumeration(entries);
+ }
+
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ return Collections.enumeration(Collections.EMPTY_LIST);
+ }
+
+ finally
+ {
+ close(content);
+ close(jarInput);
+ }
+ }
+
@Override
public URL getEntry(String entryName)
{
- // TODO Auto-generated method stub
try
{
return new URL(m_url, entryName);
@@ -68,4 +109,59 @@
return null;
}
}
+
+ /**
+ * Loads the URL content, and cache it using a weak reference.
+ *
+ * @return the URL content
+ * @throws IOException on any io errors
+ */
+ private synchronized InputStream getUrlContent() throws IOException {
+ BufferedInputStream in = null;
+ ByteArrayOutputStream out = null;
+ byte[] content = null;
+
+ try
+ {
+ if (m_urlContent == null || (content = m_urlContent.get()) == null)
+ {
+ out = new ByteArrayOutputStream(4096);
+ in = new BufferedInputStream(m_url.openStream(), 4096);
+ int c;
+ while ((c = in.read()) != -1)
+ {
+ out.write(c);
+ }
+ content = out.toByteArray();
+ m_urlContent = new WeakReference<byte[]>(content);
+ }
+
+ return new ByteArrayInputStream(content);
+ }
+
+ finally
+ {
+ close(out);
+ close(in);
+ }
+ }
+
+ /**
+ * Helper method used to simply close a stream.
+ *
+ * @param closeable the stream to close
+ */
+ private void close(Closeable closeable)
+ {
+ try
+ {
+ if (closeable != null)
+ {
+ closeable.close();
+ }
+ }
+ catch (IOException e)
+ {
+ }
+ }
}
diff --git a/connect/src/main/java/org/apache/felix/connect/VFSRevision.java b/connect/src/main/java/org/apache/felix/connect/VFSRevision.java
new file mode 100644
index 0000000..fda0045
--- /dev/null
+++ b/connect/src/main/java/org/apache/felix/connect/VFSRevision.java
@@ -0,0 +1,121 @@
+/*
+ * 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.felix.connect;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jboss.vfs.VFS;
+import org.jboss.vfs.VirtualFile;
+import org.jboss.vfs.VirtualFileVisitor;
+import org.jboss.vfs.VisitorAttributes;
+
+/**
+ * Loads the content of a bundle using JBoss VFS protocol.
+ */
+public class VFSRevision implements Revision
+{
+ private final URL m_url;
+ private final long m_lastModified;
+ private final Map<String, VirtualFile> m_entries = new HashMap<String, VirtualFile>();
+
+ public VFSRevision(URL url, long lastModified)
+ {
+ m_url = url;
+ m_lastModified = lastModified;
+ }
+
+ public long getLastModified()
+ {
+ return m_lastModified;
+ }
+
+ public Enumeration<String> getEntries()
+ {
+ try
+ {
+ loadEntries(); // lazily load entries
+ return Collections.enumeration(m_entries.keySet());
+ }
+ catch (URISyntaxException e)
+ {
+ e.printStackTrace();
+ return null;
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ public URL getEntry(String entryName)
+ {
+ try
+ {
+ loadEntries();
+ VirtualFile vfile = m_entries.get(entryName);
+ return vfile != null ? vfile.toURL() : null;
+ }
+ catch (MalformedURLException e)
+ {
+ e.printStackTrace();
+ return null;
+ }
+ catch (URISyntaxException e)
+ {
+ e.printStackTrace();
+ return null;
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ private synchronized void loadEntries() throws URISyntaxException, IOException
+ {
+ if (m_entries.size() == 0)
+ {
+ final VirtualFile root = VFS.getChild(m_url.toURI());
+ final String uriPath = m_url.toURI().getPath();
+
+ root.visit(new VirtualFileVisitor()
+ {
+ public void visit(VirtualFile vfile)
+ {
+ String entryPath = vfile.getPathName().substring(uriPath.length());
+ m_entries.put(entryPath, vfile);
+ }
+
+ public VisitorAttributes getAttributes()
+ {
+ return VisitorAttributes.RECURSE_LEAVES_ONLY;
+ }
+ });
+ }
+ }
+}