You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by ga...@apache.org on 2009/12/16 20:12:17 UTC
svn commit: r891387 - in
/geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi:
BundleClassLoader.java BundleDescription.java DictionaryMap.java
Author: gawor
Date: Wed Dec 16 19:12:17 2009
New Revision: 891387
URL: http://svn.apache.org/viewvc?rev=891387&view=rev
Log:
Improved BundleClassLoader to deletage META-INF resource lookups to wired bundles. Might come useful in some cases
Added:
geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi/DictionaryMap.java (with props)
Modified:
geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi/BundleClassLoader.java
geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi/BundleDescription.java
Modified: geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi/BundleClassLoader.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi/BundleClassLoader.java?rev=891387&r1=891386&r2=891387&view=diff
==============================================================================
--- geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi/BundleClassLoader.java (original)
+++ geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi/BundleClassLoader.java Wed Dec 16 19:12:17 2009
@@ -21,21 +21,45 @@
import java.io.IOException;
import java.net.URL;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleReference;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.packageadmin.ExportedPackage;
+import org.osgi.service.packageadmin.PackageAdmin;
/**
+ * ClassLoader for a {@link Bundle}.
+ * <br/>
+ * In OSGi, resource lookup on resources in the <i>META-INF</i> directory using {@link Bundle#getResource(String)} or
+ * {@link Bundle#getResources(String)} does not return the resources found in the wired bundles of the bundle
+ * (wired via <i>Import-Package</i> or <i>DynamicImport-Package</i>). This class loader implementation provides
+ * {@link #getResource(String) and {@link #getResources(String)} methods that do delegate such resource lookups to
+ * the wired bundles.
+ *
* @version $Rev$ $Date$
*/
public class BundleClassLoader extends ClassLoader implements BundleReference {
+ private final static String META_INF_1 = "META-INF/";
+ private final static String META_INF_2 = "/META-INF/";
+
private final Bundle bundle;
+ private boolean searchWiredBundles;
public BundleClassLoader(Bundle bundle) {
+ this(bundle, true);
+ }
+
+ public BundleClassLoader(Bundle bundle, boolean searchWiredBundles) {
this.bundle = bundle;
+ this.searchWiredBundles = searchWiredBundles;
}
@Override
@@ -59,20 +83,110 @@
@Override
public URL getResource(String name) {
- return bundle.getResource(name);
+ URL resource = bundle.getResource(name);
+ if (resource == null && isMetaInfResource(name)) {
+ LinkedHashSet<Bundle> wiredBundles = getWiredBundles();
+ Iterator<Bundle> iterator = wiredBundles.iterator();
+ while (iterator.hasNext() && resource == null) {
+ resource = iterator.next().getResource(name);
+ }
+ }
+ return resource;
}
@SuppressWarnings("unchecked")
@Override
public Enumeration<URL> getResources(String name) throws IOException {
- Enumeration<URL> e = (Enumeration<URL>)bundle.getResources(name);
- if (e == null) {
- return Collections.enumeration(Collections.EMPTY_LIST);
+ Enumeration<URL> e = (Enumeration<URL>) bundle.getResources(name);
+ if (isMetaInfResource(name)) {
+ ArrayList<URL> allResources = new ArrayList<URL>();
+ addToList(allResources, e);
+ LinkedHashSet<Bundle> wiredBundles = getWiredBundles();
+ for (Bundle wiredBundle : wiredBundles) {
+ Enumeration<URL> resources = wiredBundle.getResources(name);
+ addToList(allResources, resources);
+ }
+ return Collections.enumeration(allResources);
} else {
- return e;
+ if (e == null) {
+ return Collections.enumeration(Collections.EMPTY_LIST);
+ } else {
+ return e;
+ }
}
}
+ public void setSearchWiredBundles(boolean search) {
+ searchWiredBundles = search;
+ }
+
+ public boolean getSearchWiredBundles() {
+ return searchWiredBundles;
+ }
+
+ private boolean isMetaInfResource(String name) {
+ return searchWiredBundles && name != null && (name.startsWith(META_INF_1) || name.startsWith(META_INF_2));
+ }
+
+ private LinkedHashSet<Bundle> getWiredBundles() {
+ ServiceReference reference = bundle.getBundleContext().getServiceReference(PackageAdmin.class.getName());
+ PackageAdmin packageAdmin = (PackageAdmin) bundle.getBundleContext().getService(reference);
+
+ BundleDescription description = new BundleDescription(bundle.getHeaders());
+
+ // handle static wire via Import-Package
+ List<BundleDescription.Package> imports = description.getExternalImports();
+ LinkedHashSet<Bundle> wiredBundles = new LinkedHashSet<Bundle>();
+ for (BundleDescription.Package packageImport : imports) {
+ ExportedPackage[] exports = packageAdmin.getExportedPackages(packageImport.getName());
+ Bundle wiredBundle = getWiredBundle(exports);
+ if (wiredBundle != null) {
+ wiredBundles.add(wiredBundle);
+ }
+ }
+
+ // handle dynamic wire via DynamicImport-Package
+ if (!description.getDynamicImportPackage().isEmpty()) {
+ for (Bundle b : bundle.getBundleContext().getBundles()) {
+ if (!wiredBundles.contains(b)) {
+ ExportedPackage[] exports = packageAdmin.getExportedPackages(b);
+ Bundle wiredBundle = getWiredBundle(exports);
+ if (wiredBundle != null) {
+ wiredBundles.add(wiredBundle);
+ }
+ }
+ }
+ }
+
+ bundle.getBundleContext().ungetService(reference);
+
+ return wiredBundles;
+ }
+
+ private Bundle getWiredBundle(ExportedPackage[] exports) {
+ if (exports != null) {
+ for (ExportedPackage exportedPackage : exports) {
+ Bundle[] importingBundles = exportedPackage.getImportingBundles();
+ if (importingBundles != null) {
+ for (Bundle importingBundle : importingBundles) {
+ if (importingBundle == bundle) {
+ return exportedPackage.getExportingBundle();
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private void addToList(List<URL> list, Enumeration<URL> enumeration) {
+ if (enumeration != null) {
+ while (enumeration.hasMoreElements()) {
+ list.add(enumeration.nextElement());
+ }
+ }
+ }
+
/**
* Return the bundle instance backing this classloader.
*
Modified: geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi/BundleDescription.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi/BundleDescription.java?rev=891387&r1=891386&r2=891387&view=diff
==============================================================================
--- geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi/BundleDescription.java (original)
+++ geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi/BundleDescription.java Wed Dec 16 19:12:17 2009
@@ -19,6 +19,7 @@
package org.apache.geronimo.kernel.osgi;
import java.util.ArrayList;
+import java.util.Dictionary;
import java.util.List;
import java.util.Map;
@@ -32,6 +33,10 @@
private Map headers;
+ public BundleDescription(Dictionary dictionary) {
+ this.headers = new DictionaryMap(dictionary);
+ }
+
public BundleDescription(Map headers) {
this.headers = headers;
}
@@ -100,6 +105,20 @@
return required;
}
+ /**
+ * Returns a list of packages that are listed in <i>DynamicImport-Package</i> header.
+ */
+ public List<Package> getDynamicImportPackage() {
+ String headerValue = (String) headers.get(Constants.DYNAMICIMPORT_PACKAGE);
+ List<Package> imports = new ArrayList<Package>();
+ List<HeaderElement> elements = HeaderParser.parseHeader(headerValue);
+ for (HeaderElement element : elements) {
+ Package p = new Package(element.getName(), element.getAttributes(), element.getDirectives());
+ imports.add(p);
+ }
+ return imports;
+ }
+
public static class Package {
private String name;
@@ -124,6 +143,13 @@
return directives;
}
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Name: ").append(name);
+ builder.append(", Attributes: ").append(attributes);
+ builder.append(", Directives: ").append(directives);
+ return builder.toString();
+ }
}
-
+
}
Added: geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi/DictionaryMap.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi/DictionaryMap.java?rev=891387&view=auto
==============================================================================
--- geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi/DictionaryMap.java (added)
+++ geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi/DictionaryMap.java Wed Dec 16 19:12:17 2009
@@ -0,0 +1,74 @@
+/**
+ * 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.geronimo.kernel.osgi;
+
+import java.util.AbstractMap;
+import java.util.Dictionary;
+import java.util.Set;
+
+/**
+ * Simple wrapper that exposes {@link Dictionary} class as a {@link Map}.
+ *
+ * @version $Rev$, $Date$
+ */
+public class DictionaryMap extends AbstractMap {
+
+ private final Dictionary dictionary;
+
+ public DictionaryMap(Dictionary dictionary) {
+ this.dictionary = dictionary;
+ }
+
+ @Override
+ public Object get(Object key) {
+ return dictionary.get(key);
+ }
+
+ @Override
+ public Object put(Object key, Object value) {
+ return dictionary.put(key, value);
+ }
+
+ @Override
+ public Object remove(Object key) {
+ return dictionary.remove(key);
+ }
+
+ @Override
+ public int size() {
+ return dictionary.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return dictionary.isEmpty();
+ }
+
+ @Override
+ public Set entrySet() {
+ // TODO: implement
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Set keySet() {
+ // TODO: implement
+ throw new UnsupportedOperationException();
+ }
+}
Propchange: geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi/DictionaryMap.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi/DictionaryMap.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/server/trunk/framework/modules/geronimo-kernel/src/main/java/org/apache/geronimo/kernel/osgi/DictionaryMap.java
------------------------------------------------------------------------------
svn:mime-type = text/plain