All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.osgi.internal.framework.EquinoxBundle Maven / Gradle / Ivy

Go to download

AspectJ tools most notably contains the AspectJ compiler (AJC). AJC applies aspects to Java classes during compilation, fully replacing Javac for plain Java classes and also compiling native AspectJ or annotation-based @AspectJ syntax. Furthermore, AJC can weave aspects into existing class files in a post-compile binary weaving step. This library is a superset of AspectJ weaver and hence also of AspectJ runtime.

There is a newer version: 1.9.22.1
Show newest version
/*******************************************************************************
 * Copyright (c) 2012, 2021 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.framework;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Permission;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.EnumSet;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.osgi.container.Module;
import org.eclipse.osgi.container.Module.Settings;
import org.eclipse.osgi.container.Module.StartOptions;
import org.eclipse.osgi.container.Module.State;
import org.eclipse.osgi.container.Module.StopOptions;
import org.eclipse.osgi.container.ModuleContainer;
import org.eclipse.osgi.container.ModuleContainerAdaptor.ContainerEvent;
import org.eclipse.osgi.container.ModuleContainerAdaptor.ModuleEvent;
import org.eclipse.osgi.container.ModuleLoader;
import org.eclipse.osgi.container.ModuleRevision;
import org.eclipse.osgi.container.ModuleWire;
import org.eclipse.osgi.container.ModuleWiring;
import org.eclipse.osgi.container.SystemModule;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.internal.container.InternalUtils;
import org.eclipse.osgi.internal.debug.Debug;
import org.eclipse.osgi.internal.loader.BundleLoader;
import org.eclipse.osgi.internal.loader.ModuleClassLoader;
import org.eclipse.osgi.internal.loader.classpath.ClasspathManager;
import org.eclipse.osgi.internal.messages.Msg;
import org.eclipse.osgi.internal.permadmin.EquinoxSecurityManager;
import org.eclipse.osgi.report.resolution.ResolutionReport;
import org.eclipse.osgi.signedcontent.SignedContent;
import org.eclipse.osgi.signedcontent.SignedContentFactory;
import org.eclipse.osgi.signedcontent.SignerInfo;
import org.eclipse.osgi.storage.BundleInfo.Generation;
import org.eclipse.osgi.storage.Storage;
import org.osgi.framework.AdaptPermission;
import org.osgi.framework.AdminPermission;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.BundleReference;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.Version;
import org.osgi.framework.dto.BundleDTO;
import org.osgi.framework.dto.FrameworkDTO;
import org.osgi.framework.dto.ServiceReferenceDTO;
import org.osgi.framework.launch.Framework;
import org.osgi.framework.namespace.HostNamespace;
import org.osgi.framework.startlevel.BundleStartLevel;
import org.osgi.framework.startlevel.FrameworkStartLevel;
import org.osgi.framework.startlevel.dto.BundleStartLevelDTO;
import org.osgi.framework.startlevel.dto.FrameworkStartLevelDTO;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleRevisions;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.framework.wiring.FrameworkWiring;
import org.osgi.framework.wiring.dto.BundleRevisionDTO;
import org.osgi.framework.wiring.dto.BundleWiringDTO;
import org.osgi.framework.wiring.dto.FrameworkWiringDTO;

public class EquinoxBundle implements Bundle, BundleReference {

	static class SystemBundle extends EquinoxBundle implements Framework {
		class SystemBundleHeaders extends Dictionary {
			private final Dictionary headers;

			public SystemBundleHeaders(Dictionary headers) {
				this.headers = headers;
			}

			@Override
			public Enumeration elements() {
				return headers.elements();
			}

			@Override
			public String get(Object key) {
				if (!(key instanceof String))
					return null;

				String sKey = (String) key;
				if (Constants.EXPORT_PACKAGE.equalsIgnoreCase(sKey) || Constants.PROVIDE_CAPABILITY.equalsIgnoreCase(sKey)) {
					String systemProvideHeader = getEquinoxContainer().getConfiguration().getConfiguration(EquinoxConfiguration.PROP_SYSTEM_PROVIDE_HEADER, EquinoxConfiguration.SYSTEM_PROVIDE_HEADER_SYSTEM_EXTRA);
					boolean useSystemExtra = systemProvideHeader.equals(EquinoxConfiguration.SYSTEM_PROVIDE_HEADER_SYSTEM_EXTRA);
					boolean useSystem = systemProvideHeader.equals(EquinoxConfiguration.SYSTEM_PROVIDE_HEADER_SYSTEM) || useSystemExtra;
					String systemProp = useSystem ? (Constants.EXPORT_PACKAGE.equalsIgnoreCase(sKey) ? Constants.FRAMEWORK_SYSTEMPACKAGES : Constants.FRAMEWORK_SYSTEMCAPABILITIES) : null;
					String systemExtraProp = useSystemExtra ? (Constants.EXPORT_PACKAGE.equalsIgnoreCase(sKey) ? Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA : Constants.FRAMEWORK_SYSTEMCAPABILITIES_EXTRA) : null;
					return getExtra(sKey, systemProp, systemExtraProp);
				}

				return headers.get(key);
			}

			private String getExtra(String header, String systemProp, String systemExtraProp) {
				String systemValue = systemProp != null ? getEquinoxContainer().getConfiguration().getConfiguration(systemProp) : null;
				String systemExtraValue = systemExtraProp != null ? getEquinoxContainer().getConfiguration().getConfiguration(systemExtraProp) : null;
				if (systemValue == null)
					systemValue = systemExtraValue;
				else if (systemExtraValue != null && systemExtraValue.trim().length() > 0)
					systemValue += ", " + systemExtraValue; //$NON-NLS-1$
				String result = headers.get(header);
				if (systemValue != null && systemValue.trim().length() > 0) {
					if (result != null)
						result += ", " + systemValue; //$NON-NLS-1$
					else
						result = systemValue;
				}
				return result;
			}

			@Override
			public boolean isEmpty() {
				return headers.isEmpty();
			}

			@Override
			public Enumeration keys() {
				return headers.keys();
			}

			@Override
			public String put(String key, String value) {
				return headers.put(key, value);
			}

			@Override
			public String remove(Object key) {
				return headers.remove(key);
			}

			@Override
			public int size() {
				return headers.size();
			}

		}

		final List initListeners = new ArrayList<>(0);

		class EquinoxSystemModule extends SystemModule {
			public EquinoxSystemModule(ModuleContainer container) {
				super(container);
			}

			@Override
			public Bundle getBundle() {
				return SystemBundle.this;
			}

			@Override
			protected void cleanup(ModuleRevision revision) {
				// Nothing to do
			}

			@Override
			protected void initWorker() throws BundleException {
				EquinoxConfiguration config = getEquinoxContainer().getConfiguration();
				String initUUID = config.setConfiguration(EquinoxConfiguration.PROP_INIT_UUID, Boolean.TRUE.toString());
				if (initUUID != null) {
					// this is not the first framework init, need to generate a new UUID
					config.setConfiguration(Constants.FRAMEWORK_UUID, InternalUtils.newUUID(config));
				}
				getEquinoxContainer().init();
				addInitFrameworkListeners();
				startWorker0();
			}

			@Override
			protected void stopWorker() throws BundleException {
				super.stopWorker();
				stopWorker0();
				getEquinoxContainer().close();
			}

			void asyncStop() throws BundleException {
				if (getEquinoxContainer().getConfiguration().getDebug().DEBUG_SYSTEM_BUNDLE) {
					Debug.printStackTrace(new Exception("Framework has been requested to stop.")); //$NON-NLS-1$
				}
				lockStateChange(ModuleEvent.STOPPED);
				try {
					if (Module.ACTIVE_SET.contains(getState())) {
						// TODO this still has a chance of a race condition:
						// multiple threads could get started if stop is called over and over
						Thread t = new Thread(new Runnable() {
							@Override
							public void run() {
								try {
									stop();
								} catch (Throwable e) {
									SystemBundle.this.getEquinoxContainer().getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, "Error stopping the framework.", e); //$NON-NLS-1$
								}
							}
						}, "Framework stop - " + getEquinoxContainer().toString()); //$NON-NLS-1$
						t.start();
					}
				} finally {
					unlockStateChange(ModuleEvent.STOPPED);
				}
			}

			void asyncUpdate() throws BundleException {
				if (getEquinoxContainer().getConfiguration().getDebug().DEBUG_SYSTEM_BUNDLE) {
					Debug.printStackTrace(new Exception("Framework has been requested to update (restart).")); //$NON-NLS-1$
				}
				lockStateChange(ModuleEvent.UPDATED);
				try {
					if (Module.ACTIVE_SET.contains(getState())) {
						Thread t = new Thread(new Runnable() {
							@Override
							public void run() {
								try {
									update();
								} catch (Throwable e) {
									SystemBundle.this.getEquinoxContainer().getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, "Error updating the framework.", e); //$NON-NLS-1$
								}
							}
						}, "Framework update - " + getEquinoxContainer().toString()); //$NON-NLS-1$
						t.start();
					}
				} finally {
					unlockStateChange(ModuleEvent.UPDATED);
				}
			}
		}

		SystemBundle(ModuleContainer moduleContainer, EquinoxContainer equinoxContainer) {
			super(moduleContainer, equinoxContainer);
		}

		@Override
		public void init() throws BundleException {
			this.init((FrameworkListener[]) null);
		}

		@Override
		public void init(FrameworkListener... listeners) throws BundleException {
			if (listeners != null) {
				if (getEquinoxContainer().getConfiguration().getDebug().DEBUG_SYSTEM_BUNDLE) {
					Debug.println("Initializing framework with framework listeners: " + listeners); //$NON-NLS-1$
				}
				initListeners.addAll(Arrays.asList(listeners));
			} else {
				if (getEquinoxContainer().getConfiguration().getDebug().DEBUG_SYSTEM_BUNDLE) {
					Debug.println("Initializing framework with framework no listeners"); //$NON-NLS-1$
				}
			}
			try {
				((SystemModule) getModule()).init();
			} finally {
				if (!initListeners.isEmpty()) {
					getEquinoxContainer().getEventPublisher().flushFrameworkEvents();
					removeInitListeners();
				}
			}
		}

		void addInitFrameworkListeners() {
			BundleContext context = createBundleContext();
			for (FrameworkListener initListener : initListeners) {
				context.addFrameworkListener(initListener);
			}
		}

		void removeInitListeners() {
			BundleContext context = createBundleContext();
			for (FrameworkListener initListener : initListeners) {
				context.removeFrameworkListener(initListener);
			}
			initListeners.clear();
		}

		@Override
		public FrameworkEvent waitForStop(long timeout) throws InterruptedException {
			ContainerEvent event = ((SystemModule) getModule()).waitForStop(timeout);
			return new FrameworkEvent(EquinoxContainerAdaptor.getType(event), this, null);
		}

		@Override
		Module createSystemModule(ModuleContainer moduleContainer) {
			return new EquinoxSystemModule(moduleContainer);
		}

		@Override
		public void stop(final int options) throws BundleException {
			getEquinoxContainer().checkAdminPermission(this, AdminPermission.EXECUTE);
			((EquinoxSystemModule) getModule()).asyncStop();
		}

		@Override
		public void stop() throws BundleException {
			stop(0);
		}

		@Override
		public void update(InputStream input) throws BundleException {
			getEquinoxContainer().checkAdminPermission(this, AdminPermission.LIFECYCLE);
			try {
				if (input != null)
					input.close();
			} catch (IOException e) {
				// do nothing
			}
			((EquinoxSystemModule) getModule()).asyncUpdate();
		}

		@Override
		public void update() throws BundleException {
			update(null);
		}

		@Override
		public void uninstall() throws BundleException {
			getEquinoxContainer().checkAdminPermission(this, AdminPermission.LIFECYCLE);
			throw new BundleException(Msg.BUNDLE_SYSTEMBUNDLE_UNINSTALL_EXCEPTION, BundleException.INVALID_OPERATION);
		}

		@Override
		public Dictionary getHeaders(String locale) {
			return new SystemBundleHeaders(super.getHeaders(locale));
		}
	}

	private final EquinoxContainer equinoxContainer;
	private final Module module;
	private final Object monitor = new Object();
	private BundleContextImpl context;
	private volatile SignedContent signedContent;

	private class EquinoxModule extends Module {

		@Override
		protected void startWorker() throws BundleException {
			startWorker0();
		}

		@Override
		protected void stopWorker() throws BundleException {
			stopWorker0();
		}

		public EquinoxModule(Long id, String location, ModuleContainer container, EnumSet settings, int startlevel) {
			super(id, location, container, settings, startlevel);
		}

		@Override
		public Bundle getBundle() {
			return EquinoxBundle.this;
		}

		@Override
		protected void cleanup(ModuleRevision revision) {
			Generation generation = (Generation) revision.getRevisionInfo();
			generation.delete();
			if (revision.equals(getCurrentRevision())) {
				// uninstall case
				generation.getBundleInfo().delete();
			}
		}
	}

	EquinoxBundle(ModuleContainer moduleContainer, EquinoxContainer equinoxContainer) {
		this.equinoxContainer = equinoxContainer;
		this.module = createSystemModule(moduleContainer);
	}

	public EquinoxBundle(Long id, String location, ModuleContainer moduleContainer, EnumSet settings, int startlevel, EquinoxContainer equinoxContainer) {
		this.equinoxContainer = equinoxContainer;
		this.module = new EquinoxModule(id, location, moduleContainer, settings, startlevel);
	}

	Module createSystemModule(ModuleContainer moduleContainer) {
		throw new UnsupportedOperationException();
	}

	@Override
	public int compareTo(Bundle bundle) {
		long idcomp = getBundleId() - bundle.getBundleId();
		return (idcomp < 0L) ? -1 : ((idcomp > 0L) ? 1 : 0);
	}

	@Override
	public int getState() {
		switch (module.getState()) {
			case INSTALLED :
				return Bundle.INSTALLED;
			case RESOLVED :
				return Bundle.RESOLVED;
			case STARTING :
			case LAZY_STARTING :
				return Bundle.STARTING;
			case ACTIVE :
				return Bundle.ACTIVE;
			case STOPPING :
				return Bundle.STOPPING;
			case UNINSTALLED :
				return Bundle.UNINSTALLED;
			default :
				throw new IllegalStateException("No valid bundle state for module state: " + module.getState()); //$NON-NLS-1$
		}
	}

	@Override
	public void start(int options) throws BundleException {
		if (options == 0 && equinoxContainer.getConfiguration().getDebug().MONITOR_ACTIVATION) {
			Debug.printStackTrace(new Exception("A persistent start has been called on bundle: " + this)); //$NON-NLS-1$
		}
		module.start(getStartOptions(options));
	}

	private static StartOptions[] getStartOptions(int options) {
		if (options == 0) {
			return new StartOptions[0];
		}
		Collection result = new ArrayList<>(2);
		if ((options & Bundle.START_TRANSIENT) != 0) {
			result.add(StartOptions.TRANSIENT);
		}
		if ((options & Bundle.START_ACTIVATION_POLICY) != 0) {
			result.add(StartOptions.USE_ACTIVATION_POLICY);
		}
		return result.toArray(new StartOptions[result.size()]);
	}

	@Override
	public void start() throws BundleException {
		start(0);
	}

	@Override
	public void stop(int options) throws BundleException {
		if (options == 0 && equinoxContainer.getConfiguration().getDebug().MONITOR_ACTIVATION) {
			Debug.printStackTrace(new Exception("A persistent stop has been called on bundle: " + this)); //$NON-NLS-1$
		}
		module.stop(getStopOptions(options));
	}

	private StopOptions[] getStopOptions(int options) {
		if ((options & Bundle.STOP_TRANSIENT) == 0) {
			return new StopOptions[0];
		}
		return new StopOptions[] {StopOptions.TRANSIENT};
	}

	@Override
	public void stop() throws BundleException {
		stop(0);
	}

	@Override
	public void update(InputStream input) throws BundleException {
		Storage storage = equinoxContainer.getStorage();
		storage.update(module, input);
		signedContent = null;
	}

	@Override
	public void update() throws BundleException {
		update(null);
	}

	@Override
	public void uninstall() throws BundleException {
		// be sure to prime the headers with default local; calling priv method to avoid permission check
		privGetHeaders(null);
		Storage storage = equinoxContainer.getStorage();
		storage.getModuleContainer().uninstall(module);
	}

	@Override
	public Dictionary getHeaders() {
		return getHeaders(null);
	}

	@Override
	public Dictionary getHeaders(String locale) {
		equinoxContainer.checkAdminPermission(this, AdminPermission.METADATA);
		return privGetHeaders(locale);
	}

	private Dictionary privGetHeaders(String locale) {
		Generation current = (Generation) module.getCurrentRevision().getRevisionInfo();
		return current.getHeaders(locale);
	}

	@Override
	public long getBundleId() {
		return module.getId();
	}

	@Override
	public String getLocation() {
		equinoxContainer.checkAdminPermission(getBundle(), AdminPermission.METADATA);
		return module.getLocation();
	}

	@Override
	public ServiceReference[] getRegisteredServices() {
		checkValid();
		BundleContextImpl current = getBundleContextImpl();
		return current == null ? null : equinoxContainer.getServiceRegistry().getRegisteredServices(current);
	}

	@Override
	public ServiceReference[] getServicesInUse() {
		checkValid();
		BundleContextImpl current = getBundleContextImpl();
		return current == null ? null : equinoxContainer.getServiceRegistry().getServicesInUse(current);
	}

	@Override
	public boolean hasPermission(Object permission) {
		Generation current = (Generation) module.getCurrentRevision().getRevisionInfo();
		ProtectionDomain domain = current.getDomain();
		if (domain != null) {
			if (permission instanceof Permission) {
				SecurityManager sm = System.getSecurityManager();
				if (sm instanceof EquinoxSecurityManager) {
					/*
					 * If the FrameworkSecurityManager is active, we need to do checks the "right" way.
					 * We can exploit our knowledge that the security context of FrameworkSecurityManager
					 * is an AccessControlContext to invoke it properly with the ProtectionDomain.
					 */
					AccessControlContext acc = new AccessControlContext(new ProtectionDomain[] {domain});
					try {
						sm.checkPermission((Permission) permission, acc);
						return true;
					} catch (Exception e) {
						return false;
					}
				}
				return domain.implies((Permission) permission);
			}
			return false;
		}
		return true;
	}

	@Override
	public URL getResource(String name) {
		try {
			equinoxContainer.checkAdminPermission(this, AdminPermission.RESOURCE);
		} catch (SecurityException e) {
			return null;
		}
		checkValid();
		if (isFragment()) {
			return null;
		}

		ModuleClassLoader classLoader = getModuleClassLoader(false);
		if (classLoader != null) {
			return classLoader.getResource(name);
		}

		return new ClasspathManager((Generation) module.getCurrentRevision().getRevisionInfo(), null).findLocalResource(name);
	}

	@Override
	public String getSymbolicName() {
		return module.getCurrentRevision().getSymbolicName();
	}

	@Override
	public Version getVersion() {
		return module.getCurrentRevision().getVersion();
	}

	@Override
	public Class loadClass(String name) throws ClassNotFoundException {
		try {
			equinoxContainer.checkAdminPermission(this, AdminPermission.CLASS);
		} catch (SecurityException e) {
			throw new ClassNotFoundException(name, e);
		}
		checkValid();
		if (isFragment()) {
			throw new ClassNotFoundException("Can not load a class from a fragment bundle: " + this); //$NON-NLS-1$
		}
		try {
			ModuleClassLoader classLoader = getModuleClassLoader(true);
			if (classLoader != null) {
				if (name.length() > 0 && name.charAt(0) == '[')
					return Class.forName(name, false, classLoader);
				return classLoader.loadClass(name);
			}
		} catch (ClassNotFoundException e) {
			// This is an equinox-ism, check compatibility flag
			boolean compatibilityLazyTrigger = equinoxContainer.getConfiguration().compatibilityLazyTriggerOnFailLoad;
			// On failure attempt to activate lazy activating bundles.
			if (compatibilityLazyTrigger && State.LAZY_STARTING.equals(module.getState())) {
				try {
					module.start(StartOptions.LAZY_TRIGGER);
				} catch (BundleException e1) {
					equinoxContainer.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, e.getMessage(), e);
				}
			}
			throw e;
		}
		throw new ClassNotFoundException("No class loader available for the bundle: " + this); //$NON-NLS-1$
	}

	private ModuleClassLoader getModuleClassLoader(boolean logResolveError) {
		ResolutionReport report = resolve();
		if (logResolveError && !Module.RESOLVED_SET.contains(module.getState())) {
			String reportMessage = report.getResolutionReportMessage(module.getCurrentRevision());
			equinoxContainer.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, this, new BundleException(reportMessage, BundleException.RESOLVE_ERROR));
		}
		return AccessController.doPrivileged(new PrivilegedAction() {
			@Override
			public ModuleClassLoader run() {
				ModuleWiring wiring = getModule().getCurrentRevision().getWiring();
				if (wiring != null) {
					ModuleLoader moduleLoader = wiring.getModuleLoader();
					if (moduleLoader instanceof BundleLoader) {
						return ((BundleLoader) moduleLoader).getModuleClassLoader();
					}
				}
				return null;
			}
		});
	}

	@Override
	public Enumeration getResources(String name) throws IOException {
		try {
			equinoxContainer.checkAdminPermission(this, AdminPermission.RESOURCE);
		} catch (SecurityException e) {
			return null;
		}
		checkValid();
		if (isFragment()) {
			return null;
		}
		ModuleClassLoader classLoader = getModuleClassLoader(false);
		Enumeration result = null;
		if (classLoader != null) {
			result = classLoader.getResources(name);
		} else {
			result = new ClasspathManager((Generation) module.getCurrentRevision().getRevisionInfo(), null).findLocalResources(name);
		}
		return result != null && result.hasMoreElements() ? result : null;
	}

	@Override
	public Enumeration getEntryPaths(String path) {
		try {
			equinoxContainer.checkAdminPermission(this, AdminPermission.RESOURCE);
		} catch (SecurityException e) {
			return null;
		}
		checkValid();
		Generation current = (Generation) getModule().getCurrentRevision().getRevisionInfo();
		return current.getBundleFile().getEntryPaths(path);
	}

	@Override
	public URL getEntry(String path) {
		try {
			equinoxContainer.checkAdminPermission(this, AdminPermission.RESOURCE);
		} catch (SecurityException e) {
			return null;
		}
		checkValid();
		Generation current = (Generation) getModule().getCurrentRevision().getRevisionInfo();
		return current.getEntry(path);
	}

	@Override
	public long getLastModified() {
		return module.getLastModified();
	}

	@Override
	public Enumeration findEntries(String path, String filePattern, boolean recurse) {
		try {
			equinoxContainer.checkAdminPermission(this, AdminPermission.RESOURCE);
		} catch (SecurityException e) {
			return null;
		}
		checkValid();
		resolve();
		return Storage.findEntries(getGenerations(), path, filePattern, recurse ? BundleWiring.FINDENTRIES_RECURSE : 0);
	}

	@Override
	public BundleContext getBundleContext() {
		equinoxContainer.checkAdminPermission(this, AdminPermission.CONTEXT);
		return createBundleContext();
	}

	BundleContextImpl createBundleContext() {
		if (isFragment()) {
			// fragments cannot have contexts
			return null;
		}
		synchronized (this.monitor) {
			if (context == null) {
				// only create the context if we are starting, active or stopping
				// this is so that SCR can get the context for lazy-start bundles
				if (Module.ACTIVE_SET.contains(module.getState())) {
					context = new BundleContextImpl(this, equinoxContainer);
				}
			}
			return context;
		}
	}

	private BundleContextImpl getBundleContextImpl() {
		synchronized (this.monitor) {
			return context;
		}
	}

	@Override
	public Map> getSignerCertificates(int signersType) {
		try {
			SignedContent current = getSignedContent();
			SignerInfo[] infos = current == null ? null : current.getSignerInfos();
			if (infos.length == 0)
				return Collections.emptyMap();
			Map> results = new HashMap<>(infos.length);
			for (SignerInfo info : infos) {
				if (signersType == SIGNERS_TRUSTED && !info.isTrusted()) {
					continue;
				}
				Certificate[] certs = info.getCertificateChain();
				if (certs == null || certs.length == 0)
					continue;
				List certChain = new ArrayList<>();
				for (Certificate cert : certs) {
					certChain.add((X509Certificate) cert);
				}
				results.put((X509Certificate) certs[0], certChain);
			}
			return results;
		} catch (Exception e) {
			return Collections.emptyMap();
		}
	}

	@Override
	public final  A adapt(Class adapterType) {
		checkAdaptPermission(adapterType);
		return adapt0(adapterType);
	}

	private void readLock() {
		equinoxContainer.getStorage().getModuleDatabase().readLock();
	}

	private void readUnlock() {
		equinoxContainer.getStorage().getModuleDatabase().readUnlock();
	}

	@SuppressWarnings("unchecked")
	private  A adapt0(Class adapterType) {
		if (AccessControlContext.class.equals(adapterType)) {
			Generation current = (Generation) module.getCurrentRevision().getRevisionInfo();
			ProtectionDomain domain = current.getDomain();
			return (A) (domain == null ? null : new AccessControlContext(new ProtectionDomain[] {domain}));
		}

		if (BundleContext.class.equals(adapterType)) {
			try {
				return (A) getBundleContext();
			} catch (SecurityException e) {
				return null;
			}
		}

		if (BundleRevision.class.equals(adapterType)) {
			if (module.getState().equals(State.UNINSTALLED)) {
				return null;
			}
			return (A) module.getCurrentRevision();
		}

		if (BundleRevisions.class.equals(adapterType)) {
			return (A) module.getRevisions();
		}

		if (BundleStartLevel.class.equals(adapterType)) {
			return (A) module;
		}

		if (BundleWiring.class.equals(adapterType)) {
			if (module.getState().equals(State.UNINSTALLED)) {
				return null;
			}
			ModuleRevision revision = module.getCurrentRevision();
			if (revision == null) {
				return null;
			}
			return (A) revision.getWiring();
		}

		if (BundleDTO.class.equals(adapterType)) {
			// Unfortunately we need to lock here to make sure the BSN and version
			// are consistent in case of updates
			readLock();
			try {
				return (A) DTOBuilder.newBundleDTO(this);
			} finally {
				readUnlock();
			}
		}

		if (BundleStartLevelDTO.class.equals(adapterType)) {
			if (module.getState().equals(State.UNINSTALLED)) {
				return null;
			}
			return (A) DTOBuilder.newBundleStartLevelDTO(this, module);
		}

		if (BundleRevisionDTO.class.equals(adapterType)) {
			if (module.getState().equals(State.UNINSTALLED)) {
				return null;
			}
			return (A) DTOBuilder.newBundleRevisionDTO(module.getCurrentRevision());
		}

		if (BundleRevisionDTO[].class.equals(adapterType)) {
			if (module.getState().equals(State.UNINSTALLED)) {
				return null;
			}
			// No need to lock the database here since the ModuleRevisions object does the
			// proper locking for us.
			return (A) DTOBuilder.newArrayBundleRevisionDTO(module.getRevisions());
		}

		if (BundleWiringDTO.class.equals(adapterType)) {
			if (module.getState().equals(State.UNINSTALLED)) {
				return null;
			}
			readLock();
			try {
				return (A) DTOBuilder.newBundleWiringDTO(module.getCurrentRevision());
			} finally {
				readUnlock();
			}
		}

		if (BundleWiringDTO[].class.equals(adapterType)) {
			if (module.getState().equals(State.UNINSTALLED)) {
				return null;
			}
			readLock();
			try {
				return (A) DTOBuilder.newArrayBundleWiringDTO(module.getRevisions());
			} finally {
				readUnlock();
			}
		}

		if (ServiceReferenceDTO[].class.equals(adapterType)) {
			if (module.getState().equals(State.UNINSTALLED)) {
				return null;
			}
			BundleContextImpl current = getBundleContextImpl();
			ServiceReference[] references = (current == null) ? null : equinoxContainer.getServiceRegistry().getRegisteredServices(current);
			return (A) DTOBuilder.newArrayServiceReferenceDTO(references);
		}

		if (getBundleId() == 0) {
			if (Framework.class.equals(adapterType)) {
				return (A) this;
			}

			if (FrameworkStartLevel.class.equals(adapterType)) {
				return (A) module.getContainer().getFrameworkStartLevel();
			}

			if (FrameworkWiring.class.equals(adapterType)) {
				return (A) module.getContainer().getFrameworkWiring();
			}

			if (FrameworkDTO.class.equals(adapterType)) {
				BundleContextImpl current = getBundleContextImpl();
				Map configuration = equinoxContainer.getConfiguration().getConfiguration();
				readLock();
				try {
					return (A) DTOBuilder.newFrameworkDTO(current, configuration);
				} finally {
					readUnlock();
				}
			}

			if (FrameworkStartLevelDTO.class.equals(adapterType)) {
				return (A) DTOBuilder.newFrameworkStartLevelDTO(module.getContainer().getFrameworkStartLevel());
			}

			if (FrameworkWiringDTO.class.equals(adapterType)) {
				readLock();
				try {
					Set allWirings = new HashSet<>();
					for (Module m : module.getContainer().getModules()) {
						for (ModuleRevision revision : m.getRevisions().getModuleRevisions()) {
							ModuleWiring wiring = revision.getWiring();
							if (wiring != null) {
								allWirings.add(wiring);
							}
						}
					}
					for (ModuleRevision revision : module.getContainer().getRemovalPending()) {
						ModuleWiring wiring = revision.getWiring();
						if (wiring != null) {
							allWirings.add(wiring);
						}
					}
					return (A) DTOBuilder.newFrameworkWiringDTO(allWirings);
				} finally {
					readUnlock();
				}
			}
		}

		// Equinox extras
		if (Module.class.equals(adapterType)) {
			return (A) module;
		}
		if (ProtectionDomain.class.equals(adapterType)) {
			Generation current = (Generation) module.getCurrentRevision().getRevisionInfo();
			return (A) current.getDomain();
		}
		if (SignedContent.class.equals(adapterType)) {
			return (A) getSignedContent();
		}
		if (File.class.equals(adapterType)) {
			Generation current = (Generation) module.getCurrentRevision().getRevisionInfo();
			return (A) current.getContent();
		}
		return null;
	}

	private SignedContent getSignedContent() {
		SignedContent current = signedContent;
		if (current == null) {
			SignedContentFactory factory = equinoxContainer.getSignedContentFactory();
			if (factory == null) {
				return null;
			}
			try {
				signedContent = current = factory.getSignedContent(this);
			} catch (InvalidKeyException | SignatureException | CertificateException | NoSuchAlgorithmException
					| NoSuchProviderException | IOException e) {
				return null;
			}
		}
		return current;
	}

	/**
	 * Check for permission to adapt.
	 */
	private  void checkAdaptPermission(Class adapterType) {
		SecurityManager sm = System.getSecurityManager();
		if (sm == null) {
			return;
		}
		sm.checkPermission(new AdaptPermission(adapterType.getName(), this, AdaptPermission.ADAPT));
	}

	@Override
	public File getDataFile(String filename) {
		checkValid();
		Generation current = (Generation) module.getCurrentRevision().getRevisionInfo();
		return current.getBundleInfo().getDataFile(filename);
	}

	@Override
	public Bundle getBundle() {
		return this;
	}

	public Module getModule() {
		return module;
	}

	private final void checkValid() {
		if (module.getState().equals(State.UNINSTALLED))
			throw new IllegalStateException("Bundle has been uninstalled: " + this); //$NON-NLS-1$
	}

	public boolean isFragment() {
		return (getModule().getCurrentRevision().getTypes() & BundleRevision.TYPE_FRAGMENT) != 0;
	}

	void startWorker0() throws BundleException {
		BundleContextImpl current = createBundleContext();
		if (current == null) {
			throw new BundleException("Unable to create bundle context! " + this); //$NON-NLS-1$
		}
		try {
			current.start();
		} catch (BundleException e) {
			current.close();
			synchronized (EquinoxBundle.this.monitor) {
				context = null;
			}
			throw e;
		}
	}

	void stopWorker0() throws BundleException {
		BundleContextImpl current = getBundleContextImpl();
		if (current != null) {
			try {
				current.stop();
			} finally {
				current.close();
			}
			synchronized (EquinoxBundle.this.monitor) {
				context = null;
			}
		}
	}

	ResolutionReport resolve() {
		if (!Module.RESOLVED_SET.contains(module.getState())) {
			return module.getContainer().resolve(Collections.singletonList(module), true);
		}
		return null;
	}

	List getGenerations() {
		List result = new ArrayList<>();
		ModuleRevision current = getModule().getCurrentRevision();
		result.add((Generation) current.getRevisionInfo());
		ModuleWiring wiring = current.getWiring();
		if (wiring != null) {
			List hostWires = wiring.getProvidedModuleWires(HostNamespace.HOST_NAMESPACE);
			if (hostWires != null) {
				for (ModuleWire hostWire : hostWires) {
					result.add((Generation) hostWire.getRequirer().getRevisionInfo());
				}
			}
		}
		return result;
	}

	EquinoxContainer getEquinoxContainer() {
		return equinoxContainer;
	}

	@Override
	public String toString() {
		String name = getSymbolicName();
		if (name == null)
			name = "unknown"; //$NON-NLS-1$
		return (name + '_' + getVersion() + " [" + getBundleId() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy