org.eclipse.osgi.internal.loader.sources.PackageSource Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aspectjtools Show documentation
Show all versions of aspectjtools Show documentation
Tools from the AspectJ project
/*******************************************************************************
* Copyright (c) 2003, 2014 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.osgi.internal.loader.sources;
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.Enumeration;
import org.eclipse.osgi.container.ModuleRevision;
import org.eclipse.osgi.container.ModuleWiring;
import org.eclipse.osgi.internal.framework.EquinoxBundle;
import org.eclipse.osgi.internal.framework.EquinoxContainer;
import org.eclipse.osgi.internal.loader.BundleLoader;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceFactory;
public abstract class PackageSource {
protected final String id;
public PackageSource(String id) {
// others depend on the id being interned; see SingleSourcePackage.equals
this.id = id.intern();
}
public String getId() {
return id;
}
public abstract SingleSourcePackage[] getSuppliers();
public boolean compare(PackageSource other) {
return id.equals(other.getId());
}
@Override
public int hashCode() {
return id.hashCode();
}
public boolean isNullSource() {
return false;
}
public abstract Class> loadClass(String name) throws ClassNotFoundException;
public abstract URL getResource(String name);
public abstract Enumeration getResources(String name) throws IOException;
// This is intentionally lenient; we don't force all suppliers to match (only one)
// it is better to get class cast exceptions in split package cases than miss an event
public boolean hasCommonSource(PackageSource other) {
if (other == null)
return false;
if (this == other)
return true;
SingleSourcePackage[] suppliers1 = getSuppliers();
SingleSourcePackage[] suppliers2 = other.getSuppliers();
if (suppliers1 == null || suppliers2 == null)
return false;
// This will return true if the specified source has at least one
// of the suppliers of this source.
for (SingleSourcePackage supplier1 : suppliers1) {
for (SingleSourcePackage supplier2 : suppliers2) {
if (supplier2.equals(supplier1)) {
return true;
}
}
}
return false;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(id).append(" -> "); //$NON-NLS-1$
SingleSourcePackage[] suppliers = getSuppliers();
if (suppliers == null) {
return builder.append(String.valueOf(null)).toString();
}
builder.append('[');
for (int i = 0; i < suppliers.length; i++) {
if (i > 0) {
builder.append(',');
}
builder.append(suppliers[i].getLoader());
}
builder.append(']');
return builder.toString();
}
public abstract Collection listResources(String path, String filePattern);
/**
* Used by ServiceReferenceImpl for isAssignableTo
* @param registrant Bundle registering service
* @param client Bundle desiring to use service
* @param className class name to use
* @param serviceClass class of original service object
* @param container the equinox container
* @return true if assignable given package wiring
*/
public static boolean isServiceAssignableTo(Bundle registrant, Bundle client, String className,
Class> serviceClass, boolean checkInternal, EquinoxContainer container) {
// 1) if the registrant == client always return true
if (registrant == client) {
return true;
}
// 2) get the package name from the specified className
String pkgName = BundleLoader.getPackageName(className);
if (pkgName.startsWith("java.")) { //$NON-NLS-1$
return true;
}
BundleLoader producerBL = getBundleLoader(registrant);
if (producerBL == null) {
return false;
}
BundleLoader consumerBL = getBundleLoader(client);
if (consumerBL == null) {
return false;
}
// 3) for the specified bundle, find the wiring for the package. If no wiring is found return true
PackageSource consumerSource = getSourceFromLoader(consumerBL, pkgName, className, checkInternal,
container);
if (consumerSource == null) {
// confirmed no source for consumer
return true;
}
// if boot delegate just return true
if (container.isBootDelegationPackage(pkgName)) {
return true;
}
// 4) For the registrant bundle, find the wiring for the package.
PackageSource producerSource = getSourceFromLoader(producerBL, pkgName, className, checkInternal,
container);
if (producerSource == null) {
// confirmed no local class either; now check service object
if (serviceClass != null && ServiceFactory.class.isAssignableFrom(serviceClass)) {
Bundle bundle = container.getBundle(serviceClass);
if (bundle != null && bundle != registrant) {
// in this case we have a wacky ServiceFactory that is doing something we cannot
// verify if it is correct. Instead of failing we allow the assignment and hope
// for the best
// bug 326918
return true;
}
}
// 5) If no wiring is found for the registrant bundle then find the wiring for
// the classloader of the service object. If no wiring is found return false.
producerSource = getPackageSource(serviceClass, pkgName, className, checkInternal,
container);
if (producerSource == null) {
return false;
}
}
// 6) If the two wirings found are equal then return true; otherwise return false.
return producerSource.hasCommonSource(consumerSource);
}
private static PackageSource getSourceFromLoader(BundleLoader loader, String pkgName, String className,
boolean checkInternal, EquinoxContainer container) {
PackageSource source = loader.getPackageSource(pkgName);
if (source != null || !checkInternal) {
return source;
}
try {
Class> clazz = loader.findLocalClass(className);
if (clazz != null) {
// make sure it is from this actual loader
Bundle b = container.getBundle(clazz);
if (b != null) {
if (loader.getWiring().getBundle() == b) {
// create a source that represents the private package
return (new SingleSourcePackage(pkgName, loader));
}
// it is from a different loader (probably something with connect)
BundleLoader classBundleLoader = getBundleLoader(b);
if (classBundleLoader != null) {
return (new SingleSourcePackage(pkgName, classBundleLoader));
}
}
}
} catch (ClassNotFoundException e) {
// ignore
}
return null;
}
private static PackageSource getPackageSource(Class> serviceClass, String pkgName, String className,
boolean checkInternal, EquinoxContainer container) {
if (serviceClass == null) {
return null;
}
Bundle serviceBundle = container.getBundle(serviceClass);
if (serviceBundle == null) {
return null;
}
BundleLoader producerBL = getBundleLoader(serviceBundle);
if (producerBL == null) {
return null;
}
PackageSource producerSource = getSourceFromLoader(producerBL, pkgName, className, checkInternal, container);
if (producerSource != null) {
return producerSource;
}
// try the interfaces
Class>[] interfaces = serviceClass.getInterfaces();
// note that getInterfaces never returns null
for (Class> intf : interfaces) {
producerSource = getPackageSource(intf, pkgName, className, checkInternal, container);
if (producerSource != null) {
return producerSource;
}
}
// try super class
return getPackageSource(serviceClass.getSuperclass(), pkgName, className, checkInternal, container);
}
private static BundleLoader getBundleLoader(Bundle bundle) {
ModuleRevision producer = ((EquinoxBundle) bundle).getModule().getCurrentRevision();
ModuleWiring producerWiring = producer.getWiring();
return producerWiring == null ? null : (BundleLoader) producerWiring.getModuleLoader();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy