Return-Path: Delivered-To: apmail-geronimo-scm-archive@www.apache.org Received: (qmail 42318 invoked from network); 16 Dec 2009 19:12:41 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 16 Dec 2009 19:12:41 -0000 Received: (qmail 70017 invoked by uid 500); 16 Dec 2009 19:12:41 -0000 Delivered-To: apmail-geronimo-scm-archive@geronimo.apache.org Received: (qmail 69945 invoked by uid 500); 16 Dec 2009 19:12:40 -0000 Mailing-List: contact scm-help@geronimo.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: dev@geronimo.apache.org List-Id: Delivered-To: mailing list scm@geronimo.apache.org Received: (qmail 69936 invoked by uid 99); 16 Dec 2009 19:12:40 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 16 Dec 2009 19:12:40 +0000 X-ASF-Spam-Status: No, hits=-6.1 required=5.0 tests=AWL,BAYES_00 X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 16 Dec 2009 19:12:37 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id BB768238897F; Wed, 16 Dec 2009 19:12:17 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: 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 Date: Wed, 16 Dec 2009 19:12:17 -0000 To: scm@geronimo.apache.org From: gawor@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20091216191217.BB768238897F@eris.apache.org> 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}. + *
+ * In OSGi, resource lookup on resources in the META-INF 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 Import-Package or DynamicImport-Package). 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 wiredBundles = getWiredBundles(); + Iterator iterator = wiredBundles.iterator(); + while (iterator.hasNext() && resource == null) { + resource = iterator.next().getResource(name); + } + } + return resource; } @SuppressWarnings("unchecked") @Override public Enumeration getResources(String name) throws IOException { - Enumeration e = (Enumeration)bundle.getResources(name); - if (e == null) { - return Collections.enumeration(Collections.EMPTY_LIST); + Enumeration e = (Enumeration) bundle.getResources(name); + if (isMetaInfResource(name)) { + ArrayList allResources = new ArrayList(); + addToList(allResources, e); + LinkedHashSet wiredBundles = getWiredBundles(); + for (Bundle wiredBundle : wiredBundles) { + Enumeration 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 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 imports = description.getExternalImports(); + LinkedHashSet wiredBundles = new LinkedHashSet(); + 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 list, Enumeration 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 DynamicImport-Package header. + */ + public List getDynamicImportPackage() { + String headerValue = (String) headers.get(Constants.DYNAMICIMPORT_PACKAGE); + List imports = new ArrayList(); + List 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