001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *  http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019
020package org.apache.xbean.osgi.bundle.util;
021
022import java.io.IOException;
023import java.io.InputStream;
024import java.io.File;
025import java.net.URL;
026import java.util.ArrayList;
027import java.util.Collection;
028import java.util.Collections;
029import java.util.Dictionary;
030import java.util.Enumeration;
031import java.util.List;
032import java.util.Map;
033
034import org.osgi.framework.Bundle;
035import org.osgi.framework.BundleContext;
036import org.osgi.framework.BundleException;
037import org.osgi.framework.ServiceReference;
038import org.osgi.framework.Version;
039
040/**
041 * Bundle that delegates ClassLoader operations to a collection of {@link Bundle} objects. 
042 * 
043 * @version $Rev: 937957 $ $Date: 2010-04-26 10:00:08 +0200 (lun. 26 avril 2010) $
044 */
045public class DelegatingBundle implements Bundle {
046
047    private Collection<Bundle> bundles;
048    private Bundle bundle;
049    private BundleContext bundleContext;
050
051    public DelegatingBundle(Collection<Bundle> bundles) {
052        this.bundles = bundles;
053        if (bundles.isEmpty()) {
054            throw new IllegalArgumentException("At least one bundle is required");
055        }
056        // assume first Bundle is the main bundle
057        this.bundle = bundles.iterator().next();
058        this.bundleContext = new DelegatingBundleContext(this, bundle.getBundleContext());
059    }
060       
061    public Bundle getMainBundle() {
062        return bundle;
063    }
064    
065    public Class<?> loadClass(String name) throws ClassNotFoundException {
066        for (Bundle bundle : bundles) {
067            try {
068                return bundle.loadClass(name);
069            } catch (ClassNotFoundException ex) {
070                // ignore
071            }
072        }
073        throw new ClassNotFoundException(name);
074    }
075
076    public URL getResource(String name) {
077        URL resource = null;
078        for (Bundle bundle : bundles) {
079            resource = bundle.getResource(name);
080            if (resource != null) {
081                return resource;
082            }
083        }
084        return null;
085    }
086
087    public Enumeration<URL> getResources(String name) throws IOException {
088        ArrayList<URL> allResources = new ArrayList<URL>();
089        for (Bundle bundle : bundles) {
090            Enumeration<URL> e = (Enumeration<URL>) bundle.getResources(name);
091            addToList(allResources, e);
092        }
093        return Collections.enumeration(allResources); 
094    }    
095    
096    private static void addToList(List<URL> list, Enumeration<URL> enumeration) {
097        if (enumeration != null) {
098            while (enumeration.hasMoreElements()) {
099                list.add(enumeration.nextElement());
100            }
101        }
102    }
103
104    public BundleContext getBundleContext() {
105        return bundleContext;
106    }
107    
108    public Enumeration findEntries(String arg0, String arg1, boolean arg2) {
109        return bundle.findEntries(arg0, arg1, arg2);
110    }
111
112    public long getBundleId() {
113        return bundle.getBundleId();
114    }
115
116    public URL getEntry(String arg0) {
117        return bundle.getEntry(arg0);
118    }
119
120    public Enumeration getEntryPaths(String arg0) {
121        return bundle.getEntryPaths(arg0);
122    }
123
124    public Dictionary getHeaders() {
125        return bundle.getHeaders();
126    }
127
128    public Dictionary getHeaders(String arg0) {
129        return bundle.getHeaders(arg0);
130    }
131
132    public long getLastModified() {
133        return bundle.getLastModified();
134    }
135
136    public String getLocation() {
137        return bundle.getLocation();
138    }
139
140    public ServiceReference[] getRegisteredServices() {
141        return bundle.getRegisteredServices();
142    }
143
144    public ServiceReference[] getServicesInUse() {
145        return bundle.getServicesInUse();
146    }
147
148    public Map getSignerCertificates(int arg0) {
149        return bundle.getSignerCertificates(arg0);
150    }
151
152    public int getState() {
153        return bundle.getState();
154    }
155
156    public String getSymbolicName() {
157        return bundle.getSymbolicName();
158    }
159
160    public Version getVersion() {
161        return bundle.getVersion();
162    }
163
164    public boolean hasPermission(Object arg0) {
165        return bundle.hasPermission(arg0);
166    }
167
168    public void start() throws BundleException {
169        bundle.start();
170    }
171
172    public void start(int arg0) throws BundleException {
173        bundle.start(arg0);
174    }
175
176    public void stop() throws BundleException {
177        bundle.stop();
178    }
179
180    public void stop(int arg0) throws BundleException {
181        bundle.stop(arg0);
182    }
183
184    public void uninstall() throws BundleException {
185        bundle.uninstall();
186    }
187
188    public void update() throws BundleException {
189        bundle.update();
190    }
191
192    public void update(InputStream arg0) throws BundleException {
193        bundle.update(arg0);
194    }
195
196    public String toString() {
197        return "[DelegatingBundle: " + bundles + "]";
198    }
199    
200    // OSGI 4.3
201    public File getDataFile(String filename) {
202        return bundle.getDataFile(filename);
203    }
204    
205    // OSGI 4.3
206    public <A> A adapt(Class<A> type) {
207        return bundle.<A>adapt(type);
208    }
209
210    // OSGI 4.3
211    public int compareTo(Bundle bundle) {
212        return bundle.compareTo(bundle);
213    }
214}