blob: 20a340dded9afb0e0c65944e7baab0d69918ef81 [file] [log] [blame]
/*
* 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.framework;
import java.util.*;
import org.apache.felix.framework.util.Util;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;
import org.osgi.framework.VersionRange;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleRevisions;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.FrameworkWiring;
import org.osgi.service.packageadmin.ExportedPackage;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.service.packageadmin.RequiredBundle;
public class PackageAdminImpl implements PackageAdmin
{
private static final Comparator COMPARATOR = new Comparator() {
public int compare(Object o1, Object o2)
{
// Reverse arguments to sort in descending order.
return ((ExportedPackage) o2).getVersion().compareTo(
((ExportedPackage) o1).getVersion());
}
};
private Felix m_felix = null;
PackageAdminImpl(Felix felix)
{
m_felix = felix;
}
/**
* Returns the bundle associated with this class if the class was
* loaded from a bundle, otherwise returns null.
*
* @param clazz the class for which to determine its associated bundle.
* @return the bundle associated with the specified class, otherwise null.
**/
public Bundle getBundle(Class clazz)
{
return m_felix.getBundle(clazz);
}
/**
* Returns all bundles that have a specified symbolic name and whose
* version is in the specified version range. If no version range is
* specified, then all bundles with the specified symbolic name are
* returned. The array is sorted in descending version order.
*
* @param symbolicName the target symbolic name.
* @param versionRange the target version range.
* @return an array of matching bundles sorted in descending version order.
**/
public Bundle[] getBundles(String symbolicName, String versionRange)
{
VersionRange vr = (versionRange == null) ? null : new VersionRange(versionRange);
Bundle[] bundles = m_felix.getBundles();
List list = new ArrayList();
for (int i = 0; (bundles != null) && (i < bundles.length); i++)
{
String sym = bundles[i].getSymbolicName();
if ((sym != null) && sym.equals(symbolicName))
{
Version v = bundles[i].adapt(BundleRevision.class).getVersion();
if ((vr == null) || vr.includes(v))
{
list.add(bundles[i]);
}
}
}
if (list.isEmpty())
{
return null;
}
bundles = (Bundle[]) list.toArray(new Bundle[list.size()]);
Arrays.sort(bundles,new Comparator() {
public int compare(Object o1, Object o2)
{
Version v1 = ((Bundle) o1).adapt(BundleRevision.class).getVersion();
Version v2 = ((Bundle) o2).adapt(BundleRevision.class).getVersion();
// Compare in reverse order to get descending sort.
return v2.compareTo(v1);
}
});
return bundles;
}
public int getBundleType(Bundle bundle)
{
Map headerMap = ((BundleRevisionImpl)
bundle.adapt(BundleRevisionImpl.class)).getHeaders();
if (headerMap.containsKey(Constants.FRAGMENT_HOST))
{
return PackageAdmin.BUNDLE_TYPE_FRAGMENT;
}
return 0;
}
/**
* Returns the exported package associated with the specified
* package name. If there are more than one version of the package
* being exported, then the highest version is returned.
*
* @param name the name of the exported package to find.
* @return the exported package or null if no matching package was found.
**/
public ExportedPackage getExportedPackage(String name)
{
// Get all versions of the exported package.
ExportedPackage[] pkgs = m_felix.getExportedPackages(name);
// If there are no versions exported, then return null.
if ((pkgs == null) || (pkgs.length == 0))
{
return null;
}
// Sort the exported versions.
Arrays.sort(pkgs, COMPARATOR);
// Return the highest version.
return pkgs[0];
}
public ExportedPackage[] getExportedPackages(String name)
{
ExportedPackage[] pkgs = m_felix.getExportedPackages(name);
return ((pkgs == null) || pkgs.length == 0) ? null : pkgs;
}
/**
* Returns the packages exported by the specified bundle.
*
* @param bundle the bundle whose exported packages are to be returned.
* @return an array of packages exported by the bundle or null if the
* bundle does not export any packages.
**/
public ExportedPackage[] getExportedPackages(Bundle bundle)
{
ExportedPackage[] pkgs = m_felix.getExportedPackages(bundle);
return ((pkgs == null) || pkgs.length == 0) ? null : pkgs;
}
public Bundle[] getFragments(Bundle bundle)
{
// If the bundle is not a fragment, then return its fragments.
if ((getBundleType(bundle) & BUNDLE_TYPE_FRAGMENT) == 0)
{
List<Bundle> list = new ArrayList<Bundle>();
// Iterate through revisions
for (BundleRevision revision : bundle.adapt(BundleRevisions.class).getRevisions())
{
// Get attached fragments.
if (revision.getWiring() != null)
{
List<BundleRevision> fragments =
Util.getFragments(revision.getWiring());
for (int i = 0; i < fragments.size(); i++)
{
Bundle b = fragments.get(i).getBundle();
if (b != null)
{
list.add(b);
}
}
}
}
// Convert list to an array.
return (list.isEmpty())
? null
: (Bundle[]) list.toArray(new Bundle[list.size()]);
}
return null;
}
public Bundle[] getHosts(Bundle bundle)
{
// If the bundle is a fragment, return its hosts
if ((getBundleType(bundle) & BUNDLE_TYPE_FRAGMENT) != 0)
{
List<Bundle> list = new ArrayList<Bundle>();
// Iterate through revisions
for (BundleRevision revision : bundle.adapt(BundleRevisions.class).getRevisions())
{
// Get hosts
if (revision.getWiring() != null)
{
List<BundleWire> hostWires = revision.getWiring().getRequiredWires(null);
for (int i = 0; (hostWires != null) && (i < hostWires.size()); i++)
{
BundleWire wire = hostWires.get(i);
if (wire.getCapability().getNamespace().equals(BundleRevision.HOST_NAMESPACE))
{
Bundle b = wire.getProviderWiring().getBundle();
if (b != null)
{
list.add(b);
}
}
}
}
}
// Convert list to an array.
return (list.isEmpty())
? null
: (Bundle[]) list.toArray(new Bundle[list.size()]);
}
return null;
}
public RequiredBundle[] getRequiredBundles(String symbolicName)
{
List list = new ArrayList();
for (Bundle bundle : m_felix.getBundles())
{
if ((symbolicName == null)
|| (symbolicName.equals(bundle.getSymbolicName())))
{
list.add(new RequiredBundleImpl(m_felix, (BundleImpl) bundle));
}
}
return (list.isEmpty())
? null
: (RequiredBundle[]) list.toArray(new RequiredBundle[list.size()]);
}
/**
* The OSGi specification states that refreshing packages is
* asynchronous; this method simply notifies the package admin
* thread to do a refresh.
* @param bundles array of bundles to refresh or <tt>null</tt> to refresh
* any bundles in need of refreshing.
**/
public void refreshPackages(Bundle[] bundles)
throws SecurityException
{
List<Bundle> list = (bundles == null)
? null
: Arrays.asList(bundles);
m_felix.adapt(FrameworkWiring.class).refreshBundles(list);
}
public boolean resolveBundles(Bundle[] bundles)
{
List<Bundle> list = (bundles == null)
? null
: Arrays.asList(bundles);
return m_felix.adapt(FrameworkWiring.class).resolveBundles(list);
}
}