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

org.eclipse.osgi.internal.loader.classpath.ClasspathEntry 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) 2005, 2017 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.classpath;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import org.eclipse.osgi.container.Module;
import org.eclipse.osgi.framework.util.KeyedElement;
import org.eclipse.osgi.storage.BundleInfo;
import org.eclipse.osgi.storage.BundleInfo.Generation;
import org.eclipse.osgi.storage.Storage;
import org.eclipse.osgi.storage.bundlefile.BundleEntry;
import org.eclipse.osgi.storage.bundlefile.BundleFile;

/**
 * A ClasspathEntry contains a single BundleFile which is used as
 * a source to load classes and resources from, and a single
 * ProtectionDomain which is used as the domain to define classes
 * loaded from this ClasspathEntry.
 * @since 3.2
 */
public class ClasspathEntry {
	static final class PDEData {
		final String fileName;
		final String symbolicName;

		PDEData(File baseFile, String symbolicName) {
			this.fileName = baseFile == null ? null : baseFile.getAbsolutePath();
			this.symbolicName = symbolicName;
		}
	}

	private final BundleFile bundlefile;
	private final ProtectionDomain domain;
	private final ManifestPackageAttributes mainManifestPackageAttributes;
	private final Map perPackageManifestAttributes;
	private final List mrBundleFiles;
	private HashMap userObjects = null;

	// TODO Note that PDE has internal dependency on this field type/name (bug 267238)
	@SuppressWarnings("unused")
	private final PDEData data;

	/**
	 * Constructs a ClasspathElement with the specified bundlefile and domain
	 * @param bundlefile A BundleFile object which acts as a source
	 * @param domain the protection domain
	 */
	public ClasspathEntry(BundleFile bundlefile, ProtectionDomain domain, Generation generation) {
		this.bundlefile = bundlefile;
		this.domain = domain;
		this.data = new PDEData(generation.getBundleFile().getBaseFile(), generation.getRevision().getSymbolicName());
		final Manifest manifest = loadManifest(bundlefile, generation);
		if (manifest != null && generation.getBundleInfo().getStorage().getConfiguration().DEFINE_PACKAGE_ATTRIBUTES) {
			mainManifestPackageAttributes = manifestPackageAttributesFor(manifest.getMainAttributes(), null);
			perPackageManifestAttributes = manifestPackageAttributesMapFor(manifest.getEntries().entrySet(), mainManifestPackageAttributes);
		} else {
			mainManifestPackageAttributes = ManifestPackageAttributes.NONE;
			perPackageManifestAttributes = null;
		}

		boolean isMRJar;
		if (bundlefile == generation.getBundleFile()) {
			// this is the root bundle file
			isMRJar = generation.isMRJar();
		} else {
			isMRJar = manifest != null ? Boolean.parseBoolean(manifest.getMainAttributes().getValue(BundleInfo.MULTI_RELEASE_HEADER)) : false;
		}
		if (isMRJar) {
			mrBundleFiles = getMRBundleFiles(bundlefile, generation);
		} else {
			mrBundleFiles = Collections.emptyList();
		}
	}

	private static List getMRBundleFiles(BundleFile bundlefile, Generation generation) {
		Storage storage = generation.getBundleInfo().getStorage();
		if (storage.getRuntimeVersion().getMajor() < 9) {
			return Collections.emptyList();
		}
		List mrBundleFiles = new ArrayList<>();
		for (int i = storage.getRuntimeVersion().getMajor(); i > 8; i--) {
			String versionPath = BundleInfo.MULTI_RELEASE_VERSIONS + i + '/';
			BundleEntry versionEntry = bundlefile.getEntry(versionPath);
			if (versionEntry != null) {
				mrBundleFiles.add(storage.createNestedBundleFile(versionPath, bundlefile, generation, BundleInfo.MULTI_RELEASE_FILTER_PREFIXES));
			}
		}
		return Collections.unmodifiableList(mrBundleFiles);
	}

	private static ManifestPackageAttributes manifestPackageAttributesFor(Attributes attributes, ManifestPackageAttributes defaultAttributes) {
		return ManifestPackageAttributes.of(attributes.getValue(Attributes.Name.SPECIFICATION_TITLE), //
				attributes.getValue(Attributes.Name.SPECIFICATION_VERSION), //
				attributes.getValue(Attributes.Name.SPECIFICATION_VENDOR), //
				attributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE), //
				attributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION), //
				attributes.getValue(Attributes.Name.IMPLEMENTATION_VENDOR), //
				defaultAttributes);
	}

	private static Map manifestPackageAttributesMapFor(Set> entries, ManifestPackageAttributes defaultAttributes) {
		Map result = null;
		for (Entry entry : entries) {
			String name = entry.getKey();
			Attributes attributes = entry.getValue();
			if (name != null && name.endsWith("/")) { //$NON-NLS-1$
				String packageName = name.substring(0, name.length() - 1).replace('/', '.');
				if (result == null) {
					result = new HashMap<>(4);
				}
				result.put(packageName, manifestPackageAttributesFor(attributes, defaultAttributes));
			}
		}
		return result;
	}

	/**
	 * Returns the source BundleFile for this classpath entry
	 * @return the source BundleFile for this classpath entry
	 */
	public BundleFile getBundleFile() {
		return bundlefile;
	}

	/**
	 * Returns the ProtectionDomain for this classpath entry
	 * @return the ProtectionDomain for this classpath entry
	 */
	public ProtectionDomain getDomain() {
		return domain;
	}

	/**
	 * Returns a user object which is keyed by the specified key
	 * @param key the key of the user object to get
	 * @return a user object which is keyed by the specified key
	 */
	public synchronized Object getUserObject(Object key) {
		if (userObjects == null)
			return null;
		return userObjects.get(key);

	}

	/**
	 * Adds a user object
	 * @param userObject the user object to add
	 */
	public synchronized void addUserObject(KeyedElement userObject) {
		if (userObjects == null)
			userObjects = new HashMap<>(5);
		if (!userObjects.containsKey(userObject.getKey())) {
			userObjects.put(userObject.getKey(), userObject);
		}
	}

	/**
	 * Finds the entry with the specified path.
	 * This handles Multi-Release searching also.
	 * @param path the path to find
	 * @return the entry with the specified path.
	 */
	public BundleEntry findEntry(String path) {
		for (BundleFile mrFile : mrBundleFiles) {
			BundleEntry mrEntry = mrFile.getEntry(path);
			if (mrEntry != null) {
				return mrEntry;
			}
		}
		return bundlefile.getEntry(path);
	}

	/**
	 * Finds the resource wiht the specified name.
	 * This handles Multi-Release searching also.
	 * @param name the resource name
	 * @param m the module this classpath entry is for
	 * @param index the index this classpath entry.
	 * @return the resource URL or {@code null} if the resource does not exist.
	 */
	public URL findResource(String name, Module m, int index) {
		for (BundleFile mrFile : mrBundleFiles) {
			URL mrURL = mrFile.getResourceURL(name, m, index);
			if (mrURL != null) {
				return mrURL;
			}
		}
		return bundlefile.getResourceURL(name, m, index);
	}

	/**
	 * Adds the BundleFile objects for this classpath in the proper order
	 * for searching for resources. This handles Multi-Release ordering also.
	 * @param bundlefiles
	 */
	public void addBundleFiles(List bundlefiles) {
		bundlefiles.addAll(mrBundleFiles);
		bundlefiles.add(bundlefile);
	}

	private static Manifest loadManifest(BundleFile cpBundleFile, Generation generation) {
		if (!generation.hasPackageInfo() && generation.getBundleFile() == cpBundleFile) {
			return null;
		}
		BundleEntry mfEntry = cpBundleFile.getEntry(BundleInfo.OSGI_BUNDLE_MANIFEST);
		if (mfEntry != null) {
			InputStream manIn = null;
			try {
				try {
					manIn = mfEntry.getInputStream();
					return new Manifest(manIn);
				} finally {
					if (manIn != null)
						manIn.close();
				}
			} catch (IOException e) {
				// do nothing
			}
		}
		return null;
	}

	ManifestPackageAttributes manifestPackageAttributesFor(String packageName) {
		ManifestPackageAttributes perPackage = perPackageManifestAttributes == null ? null : perPackageManifestAttributes.get(packageName);
		if (perPackage != null) {
			return perPackage;
		}
		return mainManifestPackageAttributes;
	}

	public void close() throws IOException {
		bundlefile.close();
		for (BundleFile bf : mrBundleFiles) {
			bf.close();
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy