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

org.eclipse.osgi.internal.connect.ConnectHookConfigurator 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) 2019, 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.connect;

import static org.eclipse.osgi.internal.framework.EquinoxContainer.sneakyThrow;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.eclipse.osgi.container.Module;
import org.eclipse.osgi.container.ModuleContainerAdaptor.ModuleEvent;
import org.eclipse.osgi.container.ModuleRevisionBuilder;
import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
import org.eclipse.osgi.internal.framework.EquinoxContainer.ConnectModules;
import org.eclipse.osgi.internal.hookregistry.ClassLoaderHook;
import org.eclipse.osgi.internal.hookregistry.HookConfigurator;
import org.eclipse.osgi.internal.hookregistry.HookRegistry;
import org.eclipse.osgi.internal.hookregistry.StorageHookFactory;
import org.eclipse.osgi.internal.hookregistry.StorageHookFactory.StorageHook;
import org.eclipse.osgi.internal.loader.BundleLoader;
import org.eclipse.osgi.internal.loader.ModuleClassLoader;
import org.eclipse.osgi.storage.BundleInfo.Generation;
import org.eclipse.osgi.storage.bundlefile.BundleFile;
import org.eclipse.osgi.storage.bundlefile.BundleFileWrapperChain;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.connect.ConnectContent;
import org.osgi.framework.connect.ConnectModule;
import org.osgi.framework.connect.ModuleConnector;
import org.osgi.framework.namespace.BundleNamespace;
import org.osgi.framework.namespace.HostNamespace;
import org.osgi.framework.namespace.IdentityNamespace;

public class ConnectHookConfigurator implements HookConfigurator {
	static final Collection CONNECT_TAG_NAMESPACES = new ArrayList<>(Arrays.asList(
			BundleNamespace.BUNDLE_NAMESPACE, HostNamespace.HOST_NAMESPACE, IdentityNamespace.IDENTITY_NAMESPACE));

	@Override
	public void addHooks(final HookRegistry hookRegistry) {
		final ConnectModules connectModules = hookRegistry.getContainer().getConnectModules();
		ModuleConnector moduleConnector = connectModules.getModuleConnector();

		hookRegistry.addStorageHookFactory(new StorageHookFactory>() {
			@Override
			protected StorageHook createStorageHook(Generation generation) {
				final ConnectModule m = connectModules.getConnectModule(generation.getBundleInfo().getLocation());

				return new StorageHook(generation, this.getClass()) {
					boolean hasModule = false;

					@Override
					public void save(Object saveContext, DataOutputStream os) throws IOException {
						os.writeBoolean(m != null);
					}

					@Override
					public void load(Object loadContext, DataInputStream is) throws IOException {
						hasModule = is.readBoolean();
					}

					@Override
					public void validate() throws IllegalStateException {
						// make sure we have the module still from the factory
						if (hasModule && m == null) {
							throw new IllegalStateException("Connect Factory no longer has the module at locataion: " + generation.getBundleInfo().getLocation()); //$NON-NLS-1$
						}
					}

					@Override
					public ModuleRevisionBuilder adaptModuleRevisionBuilder(ModuleEvent operation, Module origin, ModuleRevisionBuilder builder) {
						if (m != null) {
							CONNECT_TAG_NAMESPACES.stream().map(builder::getCapabilities).flatMap(List::stream)
									.forEach(c -> c.getAttributes().compute(IdentityNamespace.CAPABILITY_TAGS_ATTRIBUTE,
											(k, v) -> {
												if (v == null) {
													return Collections.singletonList(ConnectContent.TAG_OSGI_CONNECT);
												}
												if (v instanceof List) {
													@SuppressWarnings({ "unchecked", "rawtypes" })
													List l = new ArrayList<>((List) v);
													l.add(ConnectContent.TAG_OSGI_CONNECT);
													return Collections.unmodifiableList(l);
												}
												// should not get here, but just recover
												return Arrays.asList(v, ConnectContent.TAG_OSGI_CONNECT);
											}));
							return builder;
						}
						return null;
					}
				};
			}

			@Override
			public URLConnection handleContentConnection(Module module, String location, InputStream in) {
				if (in != null) {
					// Do not call ModuleConnector method connect when input stream is non null.
					return null;
				}
				if (location == null) {
					location = module.getLocation();
				}
				try {
					ConnectModule m = connectModules.connect(location);
					if (m != null) {
						return ConnectInputStream.URL_CONNECTION_INSTANCE;
					}
				} catch (IllegalStateException e) {
					if (e.getCause() instanceof BundleException) {
						sneakyThrow(e.getCause());
					}
				}
				return null;
			}
		});

		if (moduleConnector == null) {
			return;
		}

		hookRegistry.addClassLoaderHook(new ClassLoaderHook() {
			@Override
			public ModuleClassLoader createClassLoader(ClassLoader parent, EquinoxConfiguration configuration, BundleLoader delegate, Generation generation) {
				ConnectModule m = connectModules.getConnectModule(generation.getBundleInfo().getLocation());
				if (m != null) {
					BundleFile bundlefile = generation.getBundleFile();
					if (bundlefile instanceof BundleFileWrapperChain) {
						BundleFileWrapperChain chain = (BundleFileWrapperChain) bundlefile;
						while (chain.getNext() != null) {
							chain = chain.getNext();
						}
						bundlefile = chain.getBundleFile();
					}
					if (bundlefile instanceof ConnectBundleFile) {
						return ((ConnectBundleFile) bundlefile).getClassLoader().map(
								l -> new DelegatingConnectClassLoader(parent, configuration, delegate, generation, l)).orElse(null);
					}
				}
				return null;
			}
		});

		hookRegistry.addActivatorHookFactory(() -> {
			final List activators = new ArrayList<>();
			moduleConnector.newBundleActivator().ifPresent(activators::add);
			return new BundleActivator() {
				@Override
				public void start(BundleContext context) throws Exception {
					for (BundleActivator activator : activators) {
						activator.start(context);
					}
				}

				@Override
				public void stop(BundleContext context) throws Exception {
					for (BundleActivator activator : activators) {
						activator.stop(context);
					}
				}
			};
		});
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy