diff options
author | Martin Lippert | 2008-07-04 18:57:06 +0000 |
---|---|---|
committer | Martin Lippert | 2008-07-04 18:57:06 +0000 |
commit | 2f425920ab801b833bc8828a053d8adc1e427aa3 (patch) | |
tree | 92830ad0186a56d60ad3eb58cb71098ddc8787e6 | |
parent | a8ed43f1d037ff5a577f4c36d9876e874964b898 (diff) | |
download | rt.equinox.bundles-2f425920ab801b833bc8828a053d8adc1e427aa3.tar.gz rt.equinox.bundles-2f425920ab801b833bc8828a053d8adc1e427aa3.tar.xz rt.equinox.bundles-2f425920ab801b833bc8828a053d8adc1e427aa3.zip |
Bug 238730 - [aspects] rename bundles and start with new version numbering
65 files changed, 4157 insertions, 0 deletions
diff --git a/bundles/org.eclipse.equinox.weaving.aspectj/.classpath b/bundles/org.eclipse.equinox.weaving.aspectj/.classpath new file mode 100644 index 000000000..230429d56 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.aspectj/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry excluding="org/eclipse/osgi/aspectj/weavingService/WeavingServiceFactory.java" kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.3"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/bundles/org.eclipse.equinox.weaving.aspectj/.cvsignore b/bundles/org.eclipse.equinox.weaving.aspectj/.cvsignore new file mode 100644 index 000000000..ba077a403 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.aspectj/.cvsignore @@ -0,0 +1 @@ +bin diff --git a/bundles/org.eclipse.equinox.weaving.aspectj/.options b/bundles/org.eclipse.equinox.weaving.aspectj/.options new file mode 100644 index 000000000..a4c746efd --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.aspectj/.options @@ -0,0 +1 @@ +org.aspectj.osgi.service.weaving/debug=false diff --git a/bundles/org.eclipse.equinox.weaving.aspectj/.project b/bundles/org.eclipse.equinox.weaving.aspectj/.project new file mode 100644 index 000000000..3ddde52d0 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.aspectj/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.equinox.weaving.aspectj</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/bundles/org.eclipse.equinox.weaving.aspectj/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.equinox.weaving.aspectj/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..35c2a5b04 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.aspectj/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +#Wed Feb 27 23:06:56 CET 2008 +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.compliance=1.3 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.1 +org.eclipse.jdt.core.compiler.problem.enumIdentifier=ignore +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.source=1.3 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=ignore diff --git a/bundles/org.eclipse.equinox.weaving.aspectj/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.weaving.aspectj/META-INF/MANIFEST.MF new file mode 100644 index 000000000..ed836365b --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.aspectj/META-INF/MANIFEST.MF @@ -0,0 +1,11 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: WeavingService Plug-in (Incubation) +Bundle-SymbolicName: org.eclipse.equinox.weaving.aspectj +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: org.eclipse.equinox.weaving.aspectj.WeavingServicePlugin +Require-Bundle: org.aspectj.weaver, + system.bundle +Bundle-ActivationPolicy: lazy +Import-Package: org.eclipse.equinox.service.weaving, org.eclipse.osgi.service.resolver +Bundle-RequiredExecutionEnvironment: J2SE-1.3 diff --git a/bundles/org.eclipse.equinox.weaving.aspectj/build.properties b/bundles/org.eclipse.equinox.weaving.aspectj/build.properties new file mode 100644 index 000000000..07bbd6ddc --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.aspectj/build.properties @@ -0,0 +1,6 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + .options +src.includes = src/ diff --git a/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/WeavingService.java b/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/WeavingService.java new file mode 100644 index 000000000..fcb5ef7ed --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/WeavingService.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + * Matthew Webster Eclipse 3.2 changes + * Heiko Seeberger AJDT 1.5.1 changes + *******************************************************************************/ + +package org.eclipse.equinox.weaving.aspectj; + +import java.io.IOException; + +import org.eclipse.equinox.service.weaving.IWeavingService; +import org.eclipse.equinox.service.weaving.SupplementerRegistry; +import org.eclipse.equinox.weaving.aspectj.loadtime.OSGiWeavingAdaptor; +import org.eclipse.equinox.weaving.aspectj.loadtime.OSGiWeavingContext; +import org.eclipse.osgi.service.resolver.BundleDescription; +import org.eclipse.osgi.service.resolver.State; +import org.osgi.framework.Bundle; + +public class WeavingService implements IWeavingService { + + private ClassLoader loader; + private BundleDescription bundle; + private OSGiWeavingAdaptor adaptor1; + private OSGiWeavingContext weavingContext; + + public WeavingService(){ + if (WeavingServicePlugin.DEBUG) System.out.println("- WeavingService.<init>"); + } + + public WeavingService (ClassLoader loader, Bundle bundle, State state, BundleDescription bundleDescription, SupplementerRegistry supplementerRegistry) { + this.loader=(ClassLoader)loader; + this.bundle = bundleDescription; + this.weavingContext = new OSGiWeavingContext((ClassLoader)loader, bundle, state, bundleDescription, supplementerRegistry); + } + + /** + * Return an instance of this service, initalised with the specified classloader + */ + public IWeavingService getInstance(ClassLoader loader, Bundle bundle, State resolverState, BundleDescription bundleDesciption, SupplementerRegistry supplementerRegistry){ + return new WeavingService(loader, bundle, resolverState, bundleDesciption, supplementerRegistry); + } + + /** + * See Aj.preProcess + */ + public byte[] preProcess(String name, byte[] classbytes, ClassLoader loader) throws IOException { + if (WeavingServicePlugin.DEBUG) System.out.println("> WeavingService.preProcess() bundle=" + bundle.getSymbolicName() + ", name=" + name + ", bytes=" + classbytes.length); + byte[] newBytes; + ensureAdaptorInit(); + + // Bug 215177: Adapt to updated (AJ 1.5.4) signature. + newBytes = adaptor1.weaveClass(name,classbytes, false); + if (WeavingServicePlugin.DEBUG) System.out.println("< WeavingService.preProcess() bytes=" + newBytes.length); + return newBytes; + } + + /** + * Initialise Aj + */ + private void ensureAdaptorInit(){ + if (adaptor1 == null){ + adaptor1 = new OSGiWeavingAdaptor(loader,weavingContext); + adaptor1.initialize(); + } + } + + public String getKey () { + if (WeavingServicePlugin.DEBUG) System.out.println("> WeavingService.getKey() bundle=" + bundle.getSymbolicName()); + String key; + ensureAdaptorInit(); + key = adaptor1.getNamespace(); + if (WeavingServicePlugin.DEBUG)System.out.println("< WeavingService.getKey() key='" + key + "'"); + return key; + } + + public boolean generatedClassesExistFor(ClassLoader loader, String className) { + ensureAdaptorInit(); + return adaptor1.generatedClassesExistFor(className); + } + + public void flushGeneratedClasses(ClassLoader loader) { + ensureAdaptorInit(); + adaptor1.flushGeneratedClasses(); + } + +} diff --git a/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/WeavingServiceFactory.java b/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/WeavingServiceFactory.java new file mode 100644 index 000000000..6371c7e46 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/WeavingServiceFactory.java @@ -0,0 +1,17 @@ +package org.eclipse.equinox.weaving.aspectj; + +import org.osgi.framework.Bundle; +import org.osgi.framework.ServiceFactory; +import org.osgi.framework.ServiceRegistration; + +public class WeavingServiceFactory implements ServiceFactory { + + public Object getService(Bundle bundle, ServiceRegistration registration) { + return (new WeavingService()); + } + + public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) { + //nothing here + } + +} diff --git a/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/WeavingServicePlugin.java b/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/WeavingServicePlugin.java new file mode 100644 index 000000000..e05d0655a --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/WeavingServicePlugin.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + * Matthew Webster Eclipse 3.2 changes + *******************************************************************************/ + +package org.eclipse.equinox.weaving.aspectj; + +import java.util.Properties; + +import org.eclipse.equinox.service.weaving.IWeavingService; +import org.eclipse.osgi.service.debug.DebugOptions; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; + +/** + * The main plugin class to be used in the desktop. + */ +public class WeavingServicePlugin implements BundleActivator { + + public static boolean verbose = Boolean.getBoolean("org.aspectj.osgi.verbose"); + + //The shared instance. + private static WeavingServicePlugin plugin; + + /** + * The constructor. + */ + public WeavingServicePlugin() { + plugin = this; +// IWeavingContext iwc = new WeavingContext(null,null);//force bundle to be resolved + } + + /** + * This method is called upon plug-in activation + */ + public void start(BundleContext context) throws Exception { + loadOptions(context); + if (verbose) System.err.println("[org.aspectj.osgi.service.weaving] info Starting AspectJ weaving service ..."); + String serviceName = IWeavingService.class.getName(); +// ServiceFactory factory = new WeavingServiceFactory(); + IWeavingService weavingService = new WeavingService(); + Properties props = new Properties(); +// context.registerService(serviceName, factory, props); + context.registerService(serviceName, weavingService, props); +// System.out.println("WeavingServicePlugin.start() - registered WeavingService"); + } + + /** + * This method is called when the plug-in is stopped + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + } + + /** + * Returns the shared instance. + */ + public static WeavingServicePlugin getDefault() { + return plugin; + } + + private void loadOptions (BundleContext context) { + // all this is only to get the application args + DebugOptions service = null; + ServiceReference reference = context.getServiceReference(DebugOptions.class.getName()); + if (reference != null) + service = (DebugOptions) context.getService(reference); + if (service == null) + return; + try { + DEBUG = service.getBooleanOption("org.aspectj.osgi.service.weaving/debug", false); + } finally { + // we have what we want - release the service + context.ungetService(reference); + } + } + + public static boolean DEBUG; + +} diff --git a/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/loadtime/OSGiWeavingAdaptor.java b/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/loadtime/OSGiWeavingAdaptor.java new file mode 100644 index 000000000..f40bc9f14 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/loadtime/OSGiWeavingAdaptor.java @@ -0,0 +1,170 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + * Matthew Webster Eclipse 3.2 changes + * Heiko Seeberger AJDT 1.5.1 changes + * Martin Lippert minor changes and bugfixes + *******************************************************************************/ + +package org.eclipse.equinox.weaving.aspectj.loadtime; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.StringTokenizer; + +import org.aspectj.bridge.Constants; +import org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor; +import org.aspectj.weaver.loadtime.definition.DocumentParser; +import org.eclipse.equinox.weaving.aspectj.WeavingServicePlugin; +import org.osgi.framework.Bundle; + +public class OSGiWeavingAdaptor extends ClassLoaderWeavingAdaptor { + + private final static String AOP_XML = Constants.AOP_USER_XML + ";" + Constants.AOP_AJC_XML + ";" + Constants.AOP_OSGI_XML; + + private static final String AOP_CONTEXT_LOCATION_HEADER = "Eclipse-AspectContext"; + private static final String DEFAULT_AOP_CONTEXT_LOCATION = "META-INF/aop.xml"; + + private boolean initialized; + private boolean initializing; + private ClassLoader classLoader; + private OSGiWeavingContext weavingContext; + + public OSGiWeavingAdaptor (ClassLoader loader, OSGiWeavingContext context) { + super(); + this.classLoader = loader; + this.weavingContext = context; + } + + // Bug 215177: Adapt to updated (AJ 1.5.4) super class signature: + public byte[] weaveClass(String name, byte[] bytes, boolean mustWeave) throws IOException { + + /* Avoid recursion during adaptor initialization */ + if (!initializing) { + if (!initialized) { + initializing = true; + initialize(classLoader,weavingContext); + initialized = true; + initializing = false; + } + // Bug 215177: Adapt to updated (AJ 1.5.4) super class signature: + bytes = super.weaveClass(name, bytes, mustWeave); + } + return bytes; + } + + public void initialize() { + if (!initializing) { + if (!initialized) { + initializing = true; + super.initialize(classLoader,weavingContext); + initialized = true; + initializing = false; + } + } + + if (WeavingServicePlugin.verbose) { + if (isEnabled()) System.err.println("[org.aspectj.osgi.service.weaving] info weaving bundle '" + weavingContext.getClassLoaderName() + "'"); + else System.err.println("[org.aspectj.osgi.service.weaving] info not weaving bundle '" + weavingContext.getClassLoaderName() + "'"); + } + } + + /** + * Load and cache the aop.xml/properties according to the classloader visibility rules + * + * @param weaver + * @param loader + */ + public List parseDefinitionsForBundle() { + List definitions = new ArrayList(); + Set seenBefore = new HashSet(); + + try { + parseDefinitionsFromVisibility(definitions, seenBefore); + parseDefinitionsFromRequiredBundles(definitions, seenBefore); + if (definitions.isEmpty()) { + info("no configuration found. Disabling weaver for bundler " + weavingContext.getClassLoaderName()); + } + } catch (Exception e) { + definitions.clear(); + warn("parse definitions failed",e); + } + + return definitions; + } + + private void parseDefinitionsFromVisibility(List definitions, Set seenBefore) { + String resourcePath = System.getProperty("org.aspectj.weaver.loadtime.configuration", AOP_XML); + StringTokenizer st = new StringTokenizer(resourcePath,";"); + + while(st.hasMoreTokens()){ + try { + Enumeration xmls = weavingContext.getResources(st.nextToken()); + + while (xmls.hasMoreElements()) { + URL xml = (URL) xmls.nextElement(); + if (!seenBefore.contains(xml)) { + info("using configuration " + weavingContext.getFile(xml)); + definitions.add(DocumentParser.parse(xml)); + seenBefore.add(xml); + } + else { + warn("ignoring duplicate definition: " + xml); + } + } + } + catch (Exception e) { + warn("parse definitions failed",e); + } + } + } + + private void parseDefinitionsFromRequiredBundles(List definitions, + Set seenBefore) { + Bundle[] bundles = weavingContext.getBundles(); + for (int i = 0; i < bundles.length; i++) { + parseDefinitionFromRequiredBundle(bundles[i], definitions, seenBefore); + } + } + + private void parseDefinitionFromRequiredBundle(Bundle bundle, + List definitions, Set seenBefore) { + try { + URL aopXmlDef = bundle.getEntry(getDefinitionLocation(bundle)); + if (aopXmlDef != null) { + if (!seenBefore.contains(aopXmlDef)) { + definitions.add(DocumentParser.parse(aopXmlDef)); + seenBefore.add(aopXmlDef); + } + else { + warn("ignoring duplicate definition: " + aopXmlDef); + } + } + } + catch (Exception e) { + warn("parse definitions failed", e); + } + } + + private String getDefinitionLocation(Bundle bundle) { + String aopContextHeader = (String) bundle.getHeaders().get(AOP_CONTEXT_LOCATION_HEADER); + if (aopContextHeader != null) { + aopContextHeader = aopContextHeader.trim(); + return aopContextHeader; + } + + return DEFAULT_AOP_CONTEXT_LOCATION; + } + +} diff --git a/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/loadtime/OSGiWeavingContext.java b/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/loadtime/OSGiWeavingContext.java new file mode 100644 index 000000000..54adcf3d6 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/loadtime/OSGiWeavingContext.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + * Matthew Webster Eclipse 3.2 changes + *******************************************************************************/ + +package org.eclipse.equinox.weaving.aspectj.loadtime; + +import java.io.IOException; +import java.net.URL; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.Vector; + +import org.aspectj.weaver.loadtime.DefaultWeavingContext; +import org.aspectj.weaver.tools.WeavingAdaptor; +import org.eclipse.equinox.service.weaving.SupplementerRegistry; +import org.eclipse.equinox.weaving.aspectj.WeavingServicePlugin; +import org.eclipse.osgi.service.resolver.BundleDescription; +import org.eclipse.osgi.service.resolver.BundleSpecification; +import org.eclipse.osgi.service.resolver.State; +import org.osgi.framework.Bundle; + +public class OSGiWeavingContext extends DefaultWeavingContext { + + private final State resolverState; + private final Bundle bundle; + private final BundleDescription bundleDescription; + private final SupplementerRegistry supplementerRegistry; + + public OSGiWeavingContext(ClassLoader loader, Bundle bundle, State state, BundleDescription bundleDescription, SupplementerRegistry supplementerRegistry) { + super(loader); + this.bundle = bundle; + this.bundleDescription = bundleDescription; + this.resolverState = state; + this.supplementerRegistry = supplementerRegistry; + if (WeavingServicePlugin.DEBUG) System.out.println("- WeavingContext.WeavingContext() locader=" + loader + ", bundle=" + bundle.getSymbolicName()); + } + + public String getBundleIdFromURL(URL url) { + return resolverState.getBundle(Integer.parseInt(url.getHost())).getSymbolicName(); + } + + public String toString(){ + return getClass().getName() + "[" + bundleDescription.getSymbolicName() + "]"; + } + + public String getClassLoaderName() { + return bundleDescription.getSymbolicName(); + } + + public String getFile(URL url) { + return getBundleIdFromURL(url) + url.getFile(); + } + + public String getId () { + return bundleDescription.getSymbolicName(); + } + + public Enumeration getResources(String name) throws IOException { + Enumeration result = super.getResources(name); + + if (name.endsWith("aop.xml")){ + Vector modified =new Vector(); + BundleSpecification[] requires = bundleDescription.getRequiredBundles(); + BundleDescription[] fragments = bundleDescription.getFragments(); + + while(result.hasMoreElements()){ + URL xml = (URL) result.nextElement(); + String resourceBundleName = getBundleIdFromURL(xml); + + if (bundleDescription.getSymbolicName().equals(resourceBundleName)){ + modified.add(xml); + continue; + } + + for (int i=0; i<requires.length; i++){ + BundleSpecification r = requires[i]; + if (r.getName().equals(resourceBundleName)){ + modified.add(xml); + continue; + } + } + + for (int i = 0; i < fragments.length; i++) { + BundleSpecification[] fragmentRequires = fragments[i].getRequiredBundles(); + for (int j=0; j<fragmentRequires.length; j++){ + BundleSpecification r = fragmentRequires[j]; + if (r.getName().equals(resourceBundleName)){ + modified.add(xml); + continue; + } + } + } + } + + result=modified.elements(); + } + return result; + } + + public List getDefinitions(ClassLoader loader, WeavingAdaptor adaptor) { + List definitions = ((OSGiWeavingAdaptor)adaptor).parseDefinitionsForBundle(); + return definitions; + } + + public Bundle[] getBundles() { + Set bundles = new HashSet(); + + // the bundle this context belongs to should be used + bundles.add(this.bundle); + + // add required bundles + if (this.bundle.getBundleContext() != null) { + BundleDescription[] resolvedRequires = this.bundleDescription.getResolvedRequires(); + for (int i = 0; i < resolvedRequires.length; i++) { + Bundle requiredBundle = this.bundle.getBundleContext().getBundle(resolvedRequires[i].getBundleId()); + if (requiredBundle != null) { + bundles.add(requiredBundle); + } + } + } + + // add supplementers + Bundle[] supplementers = this.supplementerRegistry.getSupplementers(this.bundle); + bundles.addAll(Arrays.asList(supplementers)); + + return (Bundle[]) bundles.toArray(new Bundle[bundles.size()]); + } + +} diff --git a/bundles/org.eclipse.equinox.weaving.caching.j9/.classpath b/bundles/org.eclipse.equinox.weaving.caching.j9/.classpath new file mode 100644 index 000000000..304e86186 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching.j9/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/bundles/org.eclipse.equinox.weaving.caching.j9/.cvsignore b/bundles/org.eclipse.equinox.weaving.caching.j9/.cvsignore new file mode 100644 index 000000000..ba077a403 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching.j9/.cvsignore @@ -0,0 +1 @@ +bin diff --git a/bundles/org.eclipse.equinox.weaving.caching.j9/.options b/bundles/org.eclipse.equinox.weaving.caching.j9/.options new file mode 100644 index 000000000..7f5c58338 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching.j9/.options @@ -0,0 +1 @@ +org.aspectj.osgi.service.caching.j9/debug=false diff --git a/bundles/org.eclipse.equinox.weaving.caching.j9/.project b/bundles/org.eclipse.equinox.weaving.caching.j9/.project new file mode 100644 index 000000000..3443fe7fc --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching.j9/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.equinox.weaving.caching.j9</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/bundles/org.eclipse.equinox.weaving.caching.j9/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.weaving.caching.j9/META-INF/MANIFEST.MF new file mode 100644 index 000000000..bd21949ab --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching.j9/META-INF/MANIFEST.MF @@ -0,0 +1,12 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: J9 CachingService Plug-in (Incubation) +Bundle-SymbolicName: org.eclipse.equinox.weaving.caching.j9 +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: org.eclipse.equinox.weaving.internal.caching.j9.CachingServicePlugin +Bundle-ActivationPolicy: lazy +Import-Package: com.ibm.oti.shared;resolution:=optional, + org.eclipse.equinox.service.weaving, + org.eclipse.osgi.service.debug;version="1.0.0", + org.osgi.framework;version="1.4.0" +Bundle-RequiredExecutionEnvironment: J2SE-1.5 diff --git a/bundles/org.eclipse.equinox.weaving.caching.j9/build.properties b/bundles/org.eclipse.equinox.weaving.caching.j9/build.properties new file mode 100644 index 000000000..8951ab621 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching.j9/build.properties @@ -0,0 +1,5 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + .options diff --git a/bundles/org.eclipse.equinox.weaving.caching.j9/src/org/eclipse/equinox/weaving/internal/caching/j9/CachingService.java b/bundles/org.eclipse.equinox.weaving.caching.j9/src/org/eclipse/equinox/weaving/internal/caching/j9/CachingService.java new file mode 100644 index 000000000..109c49a06 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching.j9/src/org/eclipse/equinox/weaving/internal/caching/j9/CachingService.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + * Matthew Webster Eclipse 3.2 changes + *******************************************************************************/ + +package org.eclipse.equinox.weaving.internal.caching.j9; + +import java.net.URL; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import org.eclipse.equinox.service.weaving.ICachingService; +import org.osgi.framework.Bundle; + +import com.ibm.oti.shared.HelperAlreadyDefinedException; +import com.ibm.oti.shared.Shared; +import com.ibm.oti.shared.SharedClassURLHelper; + +public class CachingService implements ICachingService { + + private Bundle bundle; + private ClassLoader classLoader; + private String partition; + SharedClassURLHelper urlhelper; + + public CachingService () { + if (CachingServicePlugin.DEBUG) System.out.println("- CachingService.<init>()"); + } + + public CachingService (ClassLoader loader, Bundle bundle, String key) { + if (CachingServicePlugin.DEBUG) System.out.println("> CachingService.<init>() bundle=" + bundle.getSymbolicName() + ", loader=" + loader + ", key='" + key + "'"); + this.bundle = bundle; + this.classLoader = loader; + this.partition = hashNamespace(key); + try{ + urlhelper = Shared.getSharedClassHelperFactory().getURLHelper(classLoader); + } catch (HelperAlreadyDefinedException e) { + e.printStackTrace(); + } + if (CachingServicePlugin.DEBUG) System.out.println("< CachingService.<init>() partition='" + partition + "', urlhelper=" + urlhelper); + } + + public ICachingService getInstance(ClassLoader classLoader, Bundle bundle, String key) { + return new CachingService(classLoader,bundle, key); + } + + public byte[] findStoredClass(String namespace, URL sourceFileURL, String name) { + byte[] bytes = urlhelper.findSharedClass(partition, sourceFileURL, name); + if (CachingServicePlugin.DEBUG && bytes != null) System.out.println("- CachingService.findStoredClass() bundle=" + bundle.getSymbolicName() + ", name=" + name + ", url=" + sourceFileURL + ", bytes=" + bytes); + return bytes; + } + + public boolean storeClass(String namespace, URL sourceFileURL, Class clazz, byte[] classbytes) { + boolean success = urlhelper.storeSharedClass(partition, sourceFileURL, clazz); + if (CachingServicePlugin.DEBUG && success) System.out.println("- CachingService.storeClass() bundle=" + bundle.getSymbolicName() + ", clazz=" + clazz + ", url=" + sourceFileURL); + return success; + } + + /** + * Hash the shared class namespace using MD5 + * @param keyToHash + * @return the MD5 version of the input string + */ + public String hashNamespace(String namespace){ + MessageDigest md = null; + try { + md = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + byte[] bytes = md.digest(namespace.getBytes()); + StringBuffer result = new StringBuffer(); + for(int i=0; i<bytes.length; i++){ + byte b = bytes[i]; + int num; + if(b<0) { + num = b+256; + }else{ + num=b; + } + String s = Integer.toHexString(num); + while (s.length()<2){ + s = "0"+s; + } + result.append(s); + } + return new String(result); + } + +} diff --git a/bundles/org.eclipse.equinox.weaving.caching.j9/src/org/eclipse/equinox/weaving/internal/caching/j9/CachingServiceFactory.java b/bundles/org.eclipse.equinox.weaving.caching.j9/src/org/eclipse/equinox/weaving/internal/caching/j9/CachingServiceFactory.java new file mode 100644 index 000000000..c3c86db7d --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching.j9/src/org/eclipse/equinox/weaving/internal/caching/j9/CachingServiceFactory.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + * Matthew Webster Eclipse 3.2 changes + *******************************************************************************/ + +package org.eclipse.equinox.weaving.internal.caching.j9; + +import org.osgi.framework.Bundle; +import org.osgi.framework.ServiceFactory; +import org.osgi.framework.ServiceRegistration; + +public class CachingServiceFactory implements ServiceFactory { + + public Object getService(Bundle bundle, ServiceRegistration registration) { + return new CachingService(); + } + + public void ungetService(Bundle bundle, ServiceRegistration registration, + Object service) { + + } + +} diff --git a/bundles/org.eclipse.equinox.weaving.caching.j9/src/org/eclipse/equinox/weaving/internal/caching/j9/CachingServicePlugin.java b/bundles/org.eclipse.equinox.weaving.caching.j9/src/org/eclipse/equinox/weaving/internal/caching/j9/CachingServicePlugin.java new file mode 100644 index 000000000..4009aeb82 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching.j9/src/org/eclipse/equinox/weaving/internal/caching/j9/CachingServicePlugin.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + * Matthew Webster Eclipse 3.2 changes + * Martin Lippert minor changes + *******************************************************************************/ + +package org.eclipse.equinox.weaving.internal.caching.j9; + +import org.eclipse.equinox.service.weaving.ICachingService; +import org.eclipse.osgi.service.debug.DebugOptions; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; + +import com.ibm.oti.shared.Shared; + +/** + * The main plugin class to be used in the desktop. + */ +public class CachingServicePlugin implements BundleActivator { + + public static boolean verbose = Boolean.getBoolean("org.aspectj.osgi.verbose"); + + /** + * The constructor. + */ + public CachingServicePlugin() { + } + + /** + * This method is called upon plug-in activation + */ + public void start(BundleContext context) throws Exception { + if (CachingServicePlugin.DEBUG) System.out.println("> CachingServicePlugin.start() context=" + context); + + loadOptions(context); + + //are we on J9? + if(shouldRegister()){ + if (verbose) System.err.println("[org.aspectj.osgi.service.caching.j9] info starting J9 caching service ..."); + String name = ICachingService.class.getName(); +// CachingServiceFactory factory = new CachingServiceFactory(); + CachingService singleCachingService = new CachingService(); + context.registerService(name,singleCachingService,null); +// System.out.println("CachingServicePlugin.start() - registered cachingService"); + } + else { + if (verbose) System.err.println("[org.aspectj.osgi.service.caching.j9] warning cannot start J9 caching service"); + } + + if (CachingServicePlugin.DEBUG) System.out.println("< CachingServicePlugin.start()"); + } + + /** + * This method is called when the plug-in is stopped + */ + public void stop(BundleContext context) throws Exception { + } + + private boolean shouldRegister(){ + if (CachingServicePlugin.DEBUG) System.out.println("> CachingServicePlugin.shouldRegister()"); + + boolean enabled; + try{ + Class.forName("com.ibm.oti.vm.VM"); //if this fails we are not on J9 + boolean sharing = Shared.isSharingEnabled(); //if not using shared classes we want a different adaptor + if (CachingServicePlugin.DEBUG) System.out.println("- CachingServicePlugin.shouldRegister() sharing=" + sharing); + + if(sharing) { + enabled = true; + }else{ + enabled = false; + } + } + catch(ClassNotFoundException ex){ + if (CachingServicePlugin.DEBUG) System.out.println("E CachingServicePlugin.shouldRegister() ex=" + ex); + //not on J9 + enabled = false; + } + + if (CachingServicePlugin.DEBUG) System.out.println("< CachingServicePlugin.shouldRegister() " + enabled); + return enabled; + } + + private void loadOptions (BundleContext context) { + // all this is only to get the application args + DebugOptions service = null; + ServiceReference reference = context.getServiceReference(DebugOptions.class.getName()); + if (reference != null) + service = (DebugOptions) context.getService(reference); + if (service == null) + return; + try { + DEBUG = service.getBooleanOption("org.aspectj.osgi.service.caching.j9/debug", false); + } finally { + // we have what we want - release the service + context.ungetService(reference); + } + } + + public static boolean DEBUG; + +} diff --git a/bundles/org.eclipse.equinox.weaving.caching/.classpath b/bundles/org.eclipse.equinox.weaving.caching/.classpath new file mode 100644 index 000000000..304e86186 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/bundles/org.eclipse.equinox.weaving.caching/.cvsignore b/bundles/org.eclipse.equinox.weaving.caching/.cvsignore new file mode 100644 index 000000000..ba077a403 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching/.cvsignore @@ -0,0 +1 @@ +bin diff --git a/bundles/org.eclipse.equinox.weaving.caching/.options b/bundles/org.eclipse.equinox.weaving.caching/.options new file mode 100644 index 000000000..4a1f02a72 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching/.options @@ -0,0 +1 @@ +org.aspectj.osgi.service.caching/debug=false diff --git a/bundles/org.eclipse.equinox.weaving.caching/.project b/bundles/org.eclipse.equinox.weaving.caching/.project new file mode 100644 index 000000000..06b2f9f46 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.equinox.weaving.caching</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/bundles/org.eclipse.equinox.weaving.caching/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.equinox.weaving.caching/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..e46d604ee --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,78 @@ +#Sun Feb 17 19:55:33 CET 2008 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=ignore +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=disabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nullReference=ignore +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/bundles/org.eclipse.equinox.weaving.caching/.settings/org.eclipse.pde.core.prefs b/bundles/org.eclipse.equinox.weaving.caching/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 000000000..efde3d153 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,4 @@ +#Sun Jan 13 21:33:28 CET 2008 +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/bundles/org.eclipse.equinox.weaving.caching/.settings/org.eclipse.pde.prefs b/bundles/org.eclipse.equinox.weaving.caching/.settings/org.eclipse.pde.prefs new file mode 100644 index 000000000..382fc744a --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching/.settings/org.eclipse.pde.prefs @@ -0,0 +1,15 @@ +#Sun Feb 17 19:55:59 CET 2008 +compilers.incompatible-environment=1 +compilers.p.build=1 +compilers.p.deprecated=1 +compilers.p.missing-packages=2 +compilers.p.no-required-att=0 +compilers.p.not-externalized-att=2 +compilers.p.unknown-attribute=1 +compilers.p.unknown-class=1 +compilers.p.unknown-element=1 +compilers.p.unknown-resource=1 +compilers.p.unresolved-ex-points=0 +compilers.p.unresolved-import=0 +compilers.use-project=true +eclipse.preferences.version=1 diff --git a/bundles/org.eclipse.equinox.weaving.caching/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.weaving.caching/META-INF/MANIFEST.MF new file mode 100644 index 000000000..bd51e3b7b --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: org.eclipse.equinox.weaving.caching +Bundle-Version: 1.0.0.qualifier +Bundle-Name: Standard Caching Service for Equinox Aspects (Incubation) +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-Activator: org.eclipse.equinox.weaving.internal.caching.Activator +Import-Package: com.ibm.oti.shared;resolution:=optional, + org.eclipse.equinox.service.weaving, + org.eclipse.osgi.service.datalocation;version="1.0.0", + org.eclipse.osgi.service.debug;version="1.0.0", + org.osgi.framework;version="1.4.0" +Export-Package: org.eclipse.equinox.weaving.internal.caching;x-friends:="org.aspectj.osgi.service.caching.test" diff --git a/bundles/org.eclipse.equinox.weaving.caching/build.properties b/bundles/org.eclipse.equinox.weaving.caching/build.properties new file mode 100644 index 000000000..34d2e4d2d --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/bundles/org.eclipse.equinox.weaving.caching/src/org/eclipse/equinox/weaving/internal/caching/Activator.java b/bundles/org.eclipse.equinox.weaving.caching/src/org/eclipse/equinox/weaving/internal/caching/Activator.java new file mode 100644 index 000000000..06e3af0ef --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching/src/org/eclipse/equinox/weaving/internal/caching/Activator.java @@ -0,0 +1,108 @@ +/******************************************************************************* + * Copyright (c) 2008 Heiko Seeberger and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Heiko Seeberger - initial implementation + *******************************************************************************/ + +package org.eclipse.equinox.weaving.internal.caching; + +import org.eclipse.equinox.service.weaving.ICachingService; +import org.eclipse.osgi.service.debug.DebugOptions; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; + +import com.ibm.oti.shared.Shared; + +/** + * {@link BundleActivator} for "org.aspectj.osgi.service.caching". + * + * @author Heiko Seeberger + */ +public class Activator implements BundleActivator { + + public static boolean verbose = Boolean.getBoolean("org.aspectj.osgi.verbose"); + + private SingletonCachingService singletonCachingService; + private ServiceRegistration singletonCachingServiceRegistration; + + /** + * Registers a new {@link SingletonCachingService} instance as OSGi service + * under the interface {@link ICachingService}. + * + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + public void start(final BundleContext bundleContext) { + setDebugEnabled(bundleContext); + + if (shouldRegister()) { + if (verbose) System.err.println("[org.aspectj.osgi.service.caching] info starting standard caching service ..."); + registerSingletonCachingService(bundleContext); + } + else { + if (verbose) System.err.println("[org.aspectj.osgi.service.caching] warning cannot start standard caching service on J9 VM"); + } + } + + private boolean shouldRegister() { + boolean enabled = true; + try { + Class.forName("com.ibm.oti.vm.VM"); // if this fails we are not on J9 + boolean sharing = Shared.isSharingEnabled(); // if not using shared classes we want a different adaptor + + if (sharing) { + enabled = false; + } + } catch (ClassNotFoundException ex) { + } + + return enabled; + } + + /** + * Shuts down the {@link SingletonCachingService}. + * + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop(final BundleContext context) { + singletonCachingService.stop(); + singletonCachingServiceRegistration.unregister(); + if (Log.isDebugEnabled()) { + Log.debug("Shut down and unregistered SingletonCachingService."); + } + } + + private void registerSingletonCachingService( + final BundleContext bundleContext) { + singletonCachingService = new SingletonCachingService(bundleContext); + singletonCachingServiceRegistration = + bundleContext.registerService(ICachingService.class.getName(), + singletonCachingService, null); + if (Log.isDebugEnabled()) { + Log.debug("Created and registered SingletonCachingService."); + } + } + + private void setDebugEnabled(final BundleContext bundleContext) { + final ServiceReference debugOptionsReference = + bundleContext.getServiceReference(DebugOptions.class.getName()); + if (debugOptionsReference != null) { + final DebugOptions debugOptions = + (DebugOptions) bundleContext.getService(debugOptionsReference); + if (debugOptions != null) { + Log.debugEnabled = + debugOptions.getBooleanOption( + "org.aspectj.osgi.service.caching/debug", true); //$NON-NLS-1$ + } + } + if (debugOptionsReference != null) { + bundleContext.ungetService(debugOptionsReference); + } + } +} diff --git a/bundles/org.eclipse.equinox.weaving.caching/src/org/eclipse/equinox/weaving/internal/caching/BaseCachingService.java b/bundles/org.eclipse.equinox.weaving.caching/src/org/eclipse/equinox/weaving/internal/caching/BaseCachingService.java new file mode 100644 index 000000000..848308e6a --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching/src/org/eclipse/equinox/weaving/internal/caching/BaseCachingService.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2008 Heiko Seeberger and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Heiko Seeberger - initial implementation + *******************************************************************************/ + +package org.eclipse.equinox.weaving.internal.caching; + +import java.net.URL; + +import org.eclipse.equinox.service.weaving.ICachingService; +import org.osgi.framework.Bundle; + +/** + * Abstract superclass for {@link ICachingService}. Throws + * {@link UnsupportedOperationException}s for every method. + * + * @author Heiko Seeberger + */ +public abstract class BaseCachingService implements ICachingService { + + /** + * @see org.eclipse.equinox.service.weaving.ICachingService#findStoredClass(java.lang.String, + * java.net.URL, java.lang.String) + */ + public byte[] findStoredClass(final String namespace, + final URL sourceFileURL, final String name) { + throw new UnsupportedOperationException("Illegal call semantics!"); + } + + /** + * @see org.eclipse.equinox.service.weaving.ICachingService#getInstance(java.lang.ClassLoader, + * org.osgi.framework.Bundle, java.lang.String) + */ + public ICachingService getInstance(final ClassLoader classLoader, + final Bundle bundle, final String key) { + throw new UnsupportedOperationException("Illegal call semantics!"); + } + + /** + * @see org.eclipse.equinox.service.weaving.ICachingService#storeClass(java.lang.String, + * java.net.URL, java.lang.Class, byte[]) + */ + public boolean storeClass(final String namespace, final URL sourceFileURL, + final Class clazz, final byte[] classbytes) { + throw new UnsupportedOperationException("Illegal call semantics!"); + } +} diff --git a/bundles/org.eclipse.equinox.weaving.caching/src/org/eclipse/equinox/weaving/internal/caching/BundleCachingService.java b/bundles/org.eclipse.equinox.weaving.caching/src/org/eclipse/equinox/weaving/internal/caching/BundleCachingService.java new file mode 100644 index 000000000..81e58a734 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching/src/org/eclipse/equinox/weaving/internal/caching/BundleCachingService.java @@ -0,0 +1,310 @@ +/******************************************************************************* + * Copyright (c) 2008 Heiko Seeberger and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Heiko Seeberger - initial implementation + *******************************************************************************/ + +package org.eclipse.equinox.weaving.internal.caching; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.equinox.service.weaving.ICachingService; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; + +/** + * <p> + * {@link ICachingService} instantiated by {@link SingletonCachingService} for + * each bundle. + * </p> + * <p> + * The maximum number of classes cached in memory before writing to disk is + * definded via the system property + * <code>org.aspectj.osgi.service.caching.maxCachedClasses</code>. The + * default is 20. + * </p> + * + * @author Heiko Seeberger + */ +public class BundleCachingService extends BaseCachingService { + + private static final int BUFFER_SIZE = 8 * 1024; + private static final Integer MAX_CACHED_CLASSES = + Integer.getInteger("org.aspectj.osgi.service.caching.maxCachedClasses", + 20); + + private final Bundle bundle; + private final BundleContext bundleContext; + + private File cache; + private final String cacheKey; + + private final Map<String, byte[]> cachedClasses = + new HashMap<String, byte[]>(MAX_CACHED_CLASSES + 10); + + + /** + * @param bundleContext + * Must not be null! + * @param bundle + * Must not be null! + * @param key + * Must not be null! + * @throws IllegalArgumentException + * if given bundleContext or bundle is null. + */ + public BundleCachingService(final BundleContext bundleContext, + final Bundle bundle, final String key) { + + if (bundleContext == null) { + throw new IllegalArgumentException( + "Argument \"bundleContext\" must not be null!"); + } + if (bundle == null) { + throw new IllegalArgumentException( + "Argument \"bundle\" must not be null!"); + } + if (key == null) { + throw new IllegalArgumentException( + "Argument \"key\" must not be null!"); + } + + this.bundleContext = bundleContext; + this.bundle = bundle; + this.cacheKey = hashNamespace(key); + + initCache(); + } + + /** + * @see org.eclipse.equinox.service.weaving.ICachingService#findStoredClass(java.lang.String, + * java.net.URL, java.lang.String) + */ + @Override + public byte[] findStoredClass(final String namespace, + final URL sourceFileURL, final String name) { + + if (name == null) { + throw new IllegalArgumentException( + "Argument \"name\" must not be null!"); + } + + byte[] storedClass = null; + if (cache != null) { + File cachedBytecodeFile = new File(cache, name); + if (cachedBytecodeFile.exists()) { + storedClass = read(name, cachedBytecodeFile); + } + } + + if (Log.isDebugEnabled()) { + Log.debug(MessageFormat.format("for [{0}]: {1} {2}", bundle + .getSymbolicName(), ((storedClass != null) ? "Found" + : "Found NOT"), name)); + } + return storedClass; + } + + /** + * Writes the remaining cache to disk. + */ + public void stop() { + if (cache != null) { + for (final String name : cachedClasses.keySet()) { + write(name); + } + } + } + + /** + * @see org.eclipse.equinox.service.weaving.ICachingService#storeClass(java.lang.String, + * java.net.URL, java.lang.Class, byte[]) + */ + @Override + public boolean storeClass(final String namespace, final URL sourceFileURL, + final Class clazz, final byte[] classbytes) { + + if (clazz == null) { + throw new IllegalArgumentException( + "Argument \"clazz\" must not be null!"); + } + if (classbytes == null) { + throw new IllegalArgumentException( + "Argument \"classbytes\" must not be null!"); + } + + if (cache == null) { + return false; + } + + cachedClasses.put(clazz.getName(), classbytes); + if (cachedClasses.size() > MAX_CACHED_CLASSES) { + + final Iterator<String> names = cachedClasses.keySet().iterator(); + while (names.hasNext()) { + write(names.next()); + names.remove(); + } + } + return true; + } + + /** + * Hash the shared class namespace using MD5 + * + * @param keyToHash + * @return the MD5 version of the input string + */ + private String hashNamespace(final String namespace) { + MessageDigest md = null; + try { + md = MessageDigest.getInstance("MD5"); + } + catch (final NoSuchAlgorithmException e) { + e.printStackTrace(); + } + final byte[] bytes = md.digest(namespace.getBytes()); + final StringBuffer result = new StringBuffer(); + for (final byte b : bytes) { + int num; + if (b < 0) { + num = b + 256; + } + else { + num = b; + } + String s = Integer.toHexString(num); + while (s.length() < 2) { + s = "0" + s; + } + result.append(s); + } + return new String(result); + } + + private void initCache() { + boolean isInitialized = false; + final File dataFile = bundleContext.getDataFile(""); + if (dataFile != null) { + cache = + new File(new File(dataFile, cacheKey), bundle.getSymbolicName()); + if (!cache.exists()) { + isInitialized = cache.mkdirs(); + } + else { + isInitialized = true; + } + } + if (!isInitialized) { + Log.error("Cannot initialize cache!", null); + } + } + + private byte[] read(final String name, final File file) { + int length = (int) file.length(); + + InputStream in = null; + try { + byte[] classbytes = new byte[length]; + int bytesread = 0; + int readcount; + + in = new FileInputStream(file); + + if (length > 0) { + classbytes = new byte[length]; + for (; bytesread < length; bytesread += readcount) { + readcount = in.read(classbytes, bytesread, length - bytesread); + if (readcount <= 0) /* if we didn't read anything */ + break; /* leave the loop */ + } + } else /* BundleEntry does not know its own length! */{ + length = BUFFER_SIZE; + classbytes = new byte[length]; + readloop: while (true) { + for (; bytesread < length; bytesread += readcount) { + readcount = in.read(classbytes, bytesread, length - bytesread); + if (readcount <= 0) /* if we didn't read anything */ + break readloop; /* leave the loop */ + } + byte[] oldbytes = classbytes; + length += BUFFER_SIZE; + classbytes = new byte[length]; + System.arraycopy(oldbytes, 0, classbytes, 0, bytesread); + } + } + if (classbytes.length > bytesread) { + byte[] oldbytes = classbytes; + classbytes = new byte[bytesread]; + System.arraycopy(oldbytes, 0, classbytes, 0, bytesread); + } + return classbytes; + } + catch (final IOException e) { + Log.error(MessageFormat.format( + "for [{0}]: Cannot read [1] from cache!", bundle + .getSymbolicName(), name), e); + return null; + } + finally { + if (in != null) { + try { + in.close(); + } + catch (final IOException e) { + Log.error(MessageFormat.format( + "for [{0}]: Cannot close cache file for [1]!", bundle + .getSymbolicName(), name), e); + } + } + } + } + + private void write(final String name) { + // TODO Think about synchronization !!! + FileOutputStream out = null; + try { + out = new FileOutputStream(new File(cache, name)); + out.write(cachedClasses.get(name)); + out.close(); + if (Log.isDebugEnabled()) { + Log.debug(MessageFormat.format( + "for [{0}]: Written {1} to cache.", bundle + .getSymbolicName(), name)); + } + } + catch (final IOException e) { + Log.error(MessageFormat.format( + "for [{0}]: Cannot write [1] to cache!", bundle + .getSymbolicName(), name), e); + } + finally { + if (out != null) { + try { + out.close(); + } + catch (final IOException e) { + Log.error(MessageFormat.format( + "for [{0}]: Cannot close cache file for [1]!", bundle + .getSymbolicName(), name), e); + } + } + } + } +} diff --git a/bundles/org.eclipse.equinox.weaving.caching/src/org/eclipse/equinox/weaving/internal/caching/IBundleConstants.java b/bundles/org.eclipse.equinox.weaving.caching/src/org/eclipse/equinox/weaving/internal/caching/IBundleConstants.java new file mode 100644 index 000000000..14476ceae --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching/src/org/eclipse/equinox/weaving/internal/caching/IBundleConstants.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2008 Heiko Seeberger and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Heiko Seeberger - initial implementation + *******************************************************************************/ + +package org.eclipse.equinox.weaving.internal.caching; + +/** + * Constants for org.aspectj.osgi.service.caching". + * + * @author Heiko Seeberger + */ +public interface IBundleConstants { + + /** + * The symbolic name for this bundle: "org.aspectj.osgi.service.caching". + */ + public static final String BUNDLE_SYMBOLIC_NAME = + "org.aspectj.osgi.service.caching"; //$NON-NLS-1$ +} diff --git a/bundles/org.eclipse.equinox.weaving.caching/src/org/eclipse/equinox/weaving/internal/caching/Log.java b/bundles/org.eclipse.equinox.weaving.caching/src/org/eclipse/equinox/weaving/internal/caching/Log.java new file mode 100644 index 000000000..7a9e2f60d --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching/src/org/eclipse/equinox/weaving/internal/caching/Log.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2008 Heiko Seeberger and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Heiko Seeberger - initial implementation + *******************************************************************************/ + +package org.eclipse.equinox.weaving.internal.caching; + +import static org.eclipse.equinox.weaving.internal.caching.IBundleConstants.BUNDLE_SYMBOLIC_NAME; + +/** + * Logging utility. + * + * @author Heiko Seeberger + */ +public class Log { + + static boolean debugEnabled = false; + + private static final String PREFIX = "[" + BUNDLE_SYMBOLIC_NAME + "] "; //$NON-NLS-1$ //$NON-NLS-2$ + + /** + * Logging debug information. + * + * @param message + * The tracing message, optional. + */ + public static void debug(final String message) { + if (debugEnabled) { + if (message != null) { + System.out.println(PREFIX + message); + } + } + } + + /** + * Logging an error. + * + * @param message + * The error message, optional. + * @param t + * The Throwable for this error, optional. + */ + public static void error(final String message, final Throwable t) { + if (message != null) { + System.err.println(PREFIX + message); + } + if (t != null) { + t.printStackTrace(System.err); + } + } + + /** + * Shows debug toggle state. + * + * @return true, if debug is enabled, else false. + */ + public static boolean isDebugEnabled() { + return debugEnabled; + } +} diff --git a/bundles/org.eclipse.equinox.weaving.caching/src/org/eclipse/equinox/weaving/internal/caching/SingletonCachingService.java b/bundles/org.eclipse.equinox.weaving.caching/src/org/eclipse/equinox/weaving/internal/caching/SingletonCachingService.java new file mode 100644 index 000000000..764af442c --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.caching/src/org/eclipse/equinox/weaving/internal/caching/SingletonCachingService.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2008 Heiko Seeberger and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Heiko Seeberger - initial implementation + *******************************************************************************/ + +package org.eclipse.equinox.weaving.internal.caching; + +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.equinox.service.weaving.ICachingService; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleEvent; +import org.osgi.framework.SynchronousBundleListener; + +/** + * {@link ICachingService} used as "singleton" OSGi service by + * "org.aspectj.osgi". + * + * @author Heiko Seeberger + */ +public class SingletonCachingService extends BaseCachingService { + + private final Map<String, BundleCachingService> bundleCachingServices = + new HashMap<String, BundleCachingService>(); + + private final BundleContext bundleContext; + + /** + * @param bundleContext + * Must not be null! + * @throws IllegalArgumentException + * if given bundleContext is null. + */ + public SingletonCachingService(final BundleContext bundleContext) { + if (bundleContext == null) { + throw new IllegalArgumentException( + "Argument \"bundleContext\" must not be null!"); + } + this.bundleContext = bundleContext; + + this.bundleContext.addBundleListener(new SynchronousBundleListener() { + public void bundleChanged(BundleEvent event) { + if (event.getType() == BundleEvent.UNINSTALLED) { + stopBundleCachingService(event); + } + } + }); + } + + /** + * Looks for a stored {@link BaseCachingService} for the given bundle. If + * this exits it is returned, else created and stored. + * + * @see org.eclipse.equinox.service.weaving.ICachingService#getInstance(java.lang.ClassLoader, + * org.osgi.framework.Bundle, java.lang.String) + */ + @Override + public synchronized ICachingService getInstance( + final ClassLoader classLoader, final Bundle bundle, String key) { + + if (bundle == null) { + throw new IllegalArgumentException( + "Argument \"bundle\" must not be null!"); + } + + BundleCachingService bundleCachingService = + bundleCachingServices.get(bundle.getSymbolicName()); + + key = key == null || key.length() == 0 ? "defaultCache" : key; + + if (bundleCachingService == null) { + + bundleCachingService = + new BundleCachingService(bundleContext, bundle, key); + bundleCachingServices.put(bundle.getSymbolicName(), + bundleCachingService); + + if (Log.isDebugEnabled()) { + Log.debug(MessageFormat.format( + "Created BundleCachingService for [{0}].", bundle + .getSymbolicName())); + } + } + + return bundleCachingService; + } + + /** + * Stops all individual bundle services. + */ + public synchronized void stop() { + for (final BundleCachingService bundleCachingService : bundleCachingServices + .values()) { + bundleCachingService.stop(); + } + bundleCachingServices.clear(); + } + + /** + * Stops individual bundle caching service if the bundle is uninstalled + */ + protected void stopBundleCachingService(BundleEvent event) { + String symbolicName = event.getBundle().getSymbolicName(); + BundleCachingService bundleCachingService = bundleCachingServices.get(symbolicName); + if (bundleCachingService != null) { + bundleCachingService.stop(); + bundleCachingServices.remove(symbolicName); + } + } + +} diff --git a/bundles/org.eclipse.equinox.weaving.hook/.classpath b/bundles/org.eclipse.equinox.weaving.hook/.classpath new file mode 100644 index 000000000..a9648dd85 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry excluding="org/aspectj/weaver/osgi/hooks/AspectJBundleWatcherHook.java|org/aspectj/weaver/osgi/hooks/AspectJBundleFileWrapperFactoryHook.java|org/aspectj/weaver/osgi/hooks/AspectJHookConfigurator.java|org/aspectj/weaver/osgi/hooks/AspectJClassLoadingHook.java|org/aspectj/weaver/osgi/hooks/AspectJClassLoadingStatsHook.java|org/aspectj/osgi/hooks/AspectJHookConfigurator.java|org/aspectj/osgi/hooks/AspectJClassLoadingHook.java|org/aspectj/osgi/hooks/AspectJBundleFileWrapperFactoryHook.java|org/aspectj/osgi/hooks/AspectJBundleWatcherHook.java|org/aspectj/osgi/hooks/AspectJClassLoadingStatsHook.java" kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.3"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/bundles/org.eclipse.equinox.weaving.hook/.cvsignore b/bundles/org.eclipse.equinox.weaving.hook/.cvsignore new file mode 100644 index 000000000..ba077a403 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/.cvsignore @@ -0,0 +1 @@ +bin diff --git a/bundles/org.eclipse.equinox.weaving.hook/.options b/bundles/org.eclipse.equinox.weaving.hook/.options new file mode 100644 index 000000000..1b6f040ff --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/.options @@ -0,0 +1,6 @@ +org.aspectj.osgi/debug=false +org.aspectj.osgi/debug/bundle=false +org.aspectj.osgi/debug/weave=false +org.aspectj.osgi/debug/cache=false +org.aspectj.osgi/debug/supplements=false +org.aspectj.osgi/debug/bundleName= diff --git a/bundles/org.eclipse.equinox.weaving.hook/.project b/bundles/org.eclipse.equinox.weaving.hook/.project new file mode 100644 index 000000000..ccdd43984 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.equinox.weaving.hook</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/bundles/org.eclipse.equinox.weaving.hook/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.equinox.weaving.hook/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..3121c2dbc --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +#Fri Oct 13 09:40:18 BST 2006 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.1 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.3 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=ignore +org.eclipse.jdt.core.compiler.source=1.3 diff --git a/bundles/org.eclipse.equinox.weaving.hook/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.equinox.weaving.hook/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 000000000..320731eb0 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,3 @@ +#Fri Oct 13 09:40:18 BST 2006 +eclipse.preferences.version=1 +internal.default.compliance=default diff --git a/bundles/org.eclipse.equinox.weaving.hook/All OSGi Tests (AOSGi).launch b/bundles/org.eclipse.equinox.weaving.hook/All OSGi Tests (AOSGi).launch new file mode 100644 index 000000000..86e1c8e6a --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/All OSGi Tests (AOSGi).launch @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?><launchConfiguration type="org.eclipse.pde.ui.JunitLaunchConfig"> +<stringAttribute key="application" value="org.eclipse.pde.junit.runtime.coretestapplication"/> +<booleanAttribute key="askclear" value="false"/> +<booleanAttribute key="automaticAdd" value="true"/> +<booleanAttribute key="automaticValidate" value="false"/> +<stringAttribute key="bootstrap" value=""/> +<stringAttribute key="checked" value="[NONE]"/> +<booleanAttribute key="clearConfig" value="true"/> +<booleanAttribute key="clearws" value="true"/> +<stringAttribute key="configLocation" value=""/> +<booleanAttribute key="default" value="true"/> +<booleanAttribute key="includeFragments" value="false"/> +<booleanAttribute key="includeOptional" value="true"/> +<stringAttribute key="location" value="c:\temp\test-workspaces"/> +<stringAttribute key="location1" value="c:\temp\test-workspaces"/> +<stringAttribute key="location2" value="d:\work\workspaces\runtime-test-workspace"/> +<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/> +<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/> +<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/> +<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/> +<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit3"/> +<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.osgi.tests.AutomatedTests"/> +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.osgi.tests"/> +<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/> +<stringAttribute key="pde.version" value="3.3"/> +<stringAttribute key="product" value="org.eclipse.platform.ide"/> +<stringAttribute key="templateConfig" value="C:\workspaces\aspects-equinox-incubator\org.aspectj.osgi\config.ini"/> +<booleanAttribute key="tracing" value="false"/> +<booleanAttribute key="useDefaultConfig" value="false"/> +<booleanAttribute key="useDefaultConfigArea" value="true"/> +<booleanAttribute key="useProduct" value="false"/> +</launchConfiguration>
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.weaving.hook/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.weaving.hook/META-INF/MANIFEST.MF new file mode 100644 index 000000000..f2ade9230 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/META-INF/MANIFEST.MF @@ -0,0 +1,8 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Aspect Weaving Hooks Plug-in (Incubation) +Bundle-SymbolicName: org.eclipse.equinox.weaving.hook +Bundle-Version: 1.0.0.qualifier +Fragment-Host: org.eclipse.osgi;bundle-version="[3.2.0,4.0.0)" +Export-Package: org.eclipse.equinox.service.weaving +Bundle-RequiredExecutionEnvironment: J2SE-1.3 diff --git a/bundles/org.eclipse.equinox.weaving.hook/build.properties b/bundles/org.eclipse.equinox.weaving.hook/build.properties new file mode 100644 index 000000000..a42e7f7fc --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/build.properties @@ -0,0 +1,6 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + hookconfigurators.properties,\ + .options diff --git a/bundles/org.eclipse.equinox.weaving.hook/config.ini b/bundles/org.eclipse.equinox.weaving.hook/config.ini new file mode 100644 index 000000000..a2b878aa7 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/config.ini @@ -0,0 +1,12 @@ +osgi.bundles=org.eclipse.equinox.common@2\:start,org.eclipse.update.configurator@3\:start,org.eclipse.core.runtime@start, org.aspectj.osgi.service.weaving@:start +osgi.bundles.defaultStartLevel=4 +osgi.framework=org.eclipse.osgi +osgi.configuration.cascaded=false +osgi.splashPath=platform:/base/plugins/org.eclipse.platform + +# AOSGi +osgi.framework.extensions=org.aspectj.osgi +org.aspectj.weaver.loadtime.configuration=META-INF/aop.xml;org/aspectj/aop.xml;META-INF/aop-ajc.xml +#aj.weaving.verbose=true +#org.aspectj.weaver.showWeaveInfo=true +org.aspectj.osgi.verbose=true
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.weaving.hook/hookconfigurators.properties b/bundles/org.eclipse.equinox.weaving.hook/hookconfigurators.properties new file mode 100644 index 000000000..8ade8522d --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/hookconfigurators.properties @@ -0,0 +1,2 @@ +hook.configurators= \ + org.eclipse.equinox.weaving.hooks.AspectJHook diff --git a/bundles/org.eclipse.equinox.weaving.hook/patches/org.eclipse.osgi_patch_20060509.txt b/bundles/org.eclipse.equinox.weaving.hook/patches/org.eclipse.osgi_patch_20060509.txt new file mode 100644 index 000000000..d03b0424b --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/patches/org.eclipse.osgi_patch_20060509.txt @@ -0,0 +1,594 @@ +### Eclipse Workspace Patch 1.0 +#P org.eclipse.osgi +Index: core/adaptor/org/eclipse/osgi/service/resolver/BundleDescription.java +=================================================================== +RCS file: /home/eclipse/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BundleDescription.java,v +retrieving revision 1.11 +diff -u -r1.11 BundleDescription.java +--- core/adaptor/org/eclipse/osgi/service/resolver/BundleDescription.java 17 Mar 2006 14:46:43 -0000 1.11 ++++ core/adaptor/org/eclipse/osgi/service/resolver/BundleDescription.java 9 May 2006 21:27:12 -0000 +@@ -227,4 +227,27 @@ + * @return the list of execution environments that are required. + */ + public String[] getExecutionEnvironments(); ++ ++ // AMC ++ /** ++ * Returns the supplemented import packages defined by the Supplement-Importer ++ * clause. ++ */ ++ public ImportPackageSpecification[] getSupplementedImportPackages(); ++ ++ /** ++ * Returns the supplemented export packages defined by the Supplement-Exporter ++ * clause. ++ */ ++ public ImportPackageSpecification[] getSupplementedExportPackages(); ++ ++ //end AMC ++ ++ //knibb ++ /** ++ * Returns the supplemented bundles defined by the Supplement-Bundle clause ++ */ ++ public BundleDescription[] getSupplementedBundles(); ++ //end knibb ++ + } +Index: core/framework/org/eclipse/osgi/framework/internal/core/Constants.java +=================================================================== +RCS file: /home/eclipse/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Constants.java,v +retrieving revision 1.29 +diff -u -r1.29 Constants.java +--- core/framework/org/eclipse/osgi/framework/internal/core/Constants.java 26 Oct 2005 17:58:14 -0000 1.29 ++++ core/framework/org/eclipse/osgi/framework/internal/core/Constants.java 9 May 2006 21:27:12 -0000 +@@ -268,4 +268,44 @@ + * @deprecated use {@link #ECLIPSE_LAZYSTART_EXCEPTIONS} + */ + public static final String ECLIPSE_AUTOSTART_EXCEPTIONS = ECLIPSE_LAZYSTART_EXCEPTIONS; ++ ++ ++ // Added by AMC ++ ++ /** ++ * Manifest header (named "Supplement-Importer") identifying the names ++ * (and optionally, version numbers) of the packages that the bundle supplements. ++ * All importers of one of these packages will have the exported packages of this ++ * bundle added to their imports in addition. ++ * ++ * <p> ++ * The attribute value may be retrieved from the <code>Dictionary</code> ++ * object returned by the <code>Bundle.getHeaders</code> method. ++ */ ++ public static final String SUPPLEMENT_IMPORTER = "Eclipse-SupplementImporter"; //$NON-NLS-1$ ++ ++ /** ++ * Manifest header (named "Supplement-Exporter") identifying the names ++ * (and optionally, version numbers) of the packages that the bundle supplements. ++ * All exporters of one of these packages will have the exported packages of this bundle ++ * added to their imports list. ++ * ++ * <p> ++ * The attribute value may be retrieved from the <code>Dictionary</code> ++ * object returned by the <code>Bundle.getHeaders</code> method. ++ */ ++ public static final String SUPPLEMENT_EXPORTER = "Eclipse-SupplementExporter"; //$NON-NLS-1$ ++ ++ //knibb ++ /** ++ * Manifest header (named "Supplement-Bundle") identifying the names ++ * (and optionally, version numbers) of any bundles supplemented by this bundle. ++ * All supplemented bundles will have all the exported packages of this bundle ++ * added to their imports list ++ * ++ * <p> ++ * The attribute value may be retrieved from the <code>Dictionary</code> ++ * object returned by the <code>Bundle.getHeaders</code> method. ++ */ ++ public static final String SUPPLEMENT_BUNDLE = "Eclipse-SupplementBundle"; //$NON-NLS-1$ + } +Index: resolver/src/org/eclipse/osgi/internal/resolver/StateBuilder.java +=================================================================== +RCS file: /home/eclipse/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateBuilder.java,v +retrieving revision 1.46 +diff -u -r1.46 StateBuilder.java +--- resolver/src/org/eclipse/osgi/internal/resolver/StateBuilder.java 24 Apr 2006 16:23:48 -0000 1.46 ++++ resolver/src/org/eclipse/osgi/internal/resolver/StateBuilder.java 9 May 2006 21:27:18 -0000 +@@ -101,6 +101,23 @@ + result.setGenericRequires(createGenericRequires(genericRequires)); + ManifestElement[] genericCapabilities = getGenericCapabilities(manifest, genericAliases); + result.setGenericCapabilities(createGenericCapabilities(genericCapabilities)); ++ ++ // AMC addition ++ ManifestElement[] supplementImporter = ManifestElement.parseHeader(Constants.SUPPLEMENT_IMPORTER, (String) manifest.get(Constants.SUPPLEMENT_IMPORTER)); ++ if (supplementImporter != null) ++ result.setSupplementedImportPackages(createPackageSpecification(supplementImporter,manifestVersion)); ++ ManifestElement[] supplementExporter = ManifestElement.parseHeader(Constants.SUPPLEMENT_EXPORTER, (String) manifest.get(Constants.SUPPLEMENT_EXPORTER)); ++ if (supplementExporter != null) ++ result.setSupplementedExportPackages(createPackageSpecification(supplementExporter,manifestVersion)); ++ // end AMC ++ ++ //knibb ++ ++ ManifestElement[] supplementBundle = ManifestElement.parseHeader(Constants.SUPPLEMENT_BUNDLE, (String) manifest.get(Constants.SUPPLEMENT_BUNDLE)); ++ if (supplementBundle != null) ++ result.setSupplementedBundles(createBundleSpecification(supplementBundle,manifestVersion)); ++ ++ //end knibb + return result; + } + +@@ -544,4 +561,46 @@ + if (!hostName.equals(Constants.SYSTEM_BUNDLE_SYMBOLICNAME) && !hostName.equals(Constants.getInternalSymbolicName())) + throw new BundleException(NLS.bind(StateMsg.HEADER_EXTENSION_ERROR, hostName)); + } +-} ++ ++ // AMC ++ ++ private static ImportPackageSpecification[] createPackageSpecification(ManifestElement[] packages, int manifestVersion) { ++ ImportPackageSpecificationImpl[] result = new ImportPackageSpecificationImpl[packages.length]; ++ for (int p = 0; p < packages.length; p++) { ++ String[] packagesNames = packages[p].getValueComponents(); ++ for (int i = 0; i < packagesNames.length; i++) { ++ ImportPackageSpecificationImpl spec = new ImportPackageSpecificationImpl(); ++ spec.setName(packagesNames[i]); ++ // set common attributes for both dynamic and static imports ++ spec.setVersionRange(getVersionRange(manifestVersion < 2 ? packages[p].getAttribute(Constants.PACKAGE_SPECIFICATION_VERSION) : packages[p].getAttribute(Constants.VERSION_ATTRIBUTE))); ++ spec.setBundleSymbolicName(packages[p].getAttribute(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE)); ++ spec.setBundleVersionRange(getVersionRange(packages[p].getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE))); ++ spec.setAttributes(getAttributes(packages[p],DEFINED_MATCHING_ATTRS)); ++ //spec.setPropagate(ManifestElement.getArrayFromList(packages[p].getDirective(Constants.GROUPING_DIRECTIVE))); ++ spec.setDirective(Constants.RESOLUTION_DIRECTIVE,getResolution(packages[p].getDirective(Constants.RESOLUTION_DIRECTIVE))); ++ result[p] = spec; ++ } ++ } ++ return result; ++ } ++ //End AMC ++ ++ //knibb ++ ++ private static BundleDescription[] createBundleSpecification(ManifestElement[] bundles, int manifestVersion) { ++ BundleDescriptionImpl[] result = new BundleDescriptionImpl[bundles.length]; ++ for (int b=0; b<bundles.length; b++) { ++ String[] bundleNames = bundles[b].getValueComponents(); ++ for(int i=0; i<bundleNames.length; i++) { ++ BundleDescriptionImpl spec = new BundleDescriptionImpl(); ++ spec.setName(bundleNames[i]); ++ //TODO incomplete - only matches bundle name at this time ++ result[b] = spec; ++ } ++ } ++ return result; ++ } ++ ++ ++ //end knibb ++} +\ No newline at end of file +Index: resolver/src/org/eclipse/osgi/internal/resolver/BundleSpecificationImpl.java +=================================================================== +RCS file: /home/eclipse/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleSpecificationImpl.java,v +retrieving revision 1.6 +diff -u -r1.6 BundleSpecificationImpl.java +--- resolver/src/org/eclipse/osgi/internal/resolver/BundleSpecificationImpl.java 12 Sep 2005 16:44:01 -0000 1.6 ++++ resolver/src/org/eclipse/osgi/internal/resolver/BundleSpecificationImpl.java 9 May 2006 21:27:17 -0000 +@@ -18,6 +18,14 @@ + private boolean exported; + private boolean optional; + ++ // AMC ++ public BundleSpecificationImpl() { /* empty */ } ++ ++ public BundleSpecificationImpl(String name) { ++ setName(name); ++ } ++ // End AMC ++ + protected void setExported(boolean exported) { + this.exported = exported; + } +Index: resolver/src/org/eclipse/osgi/internal/resolver/BundleDescriptionImpl.java +=================================================================== +RCS file: /home/eclipse/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleDescriptionImpl.java,v +retrieving revision 1.35 +diff -u -r1.35 BundleDescriptionImpl.java +--- resolver/src/org/eclipse/osgi/internal/resolver/BundleDescriptionImpl.java 17 Mar 2006 14:46:42 -0000 1.35 ++++ resolver/src/org/eclipse/osgi/internal/resolver/BundleDescriptionImpl.java 9 May 2006 21:27:17 -0000 +@@ -91,6 +91,35 @@ + return EMPTY_IMPORTS; + return lazyData.importPackages; + } ++ ++ // AMC ++ ++ public ImportPackageSpecification[] getSupplementedImportPackages() { ++ fullyLoad(); ++ if (lazyData.supplementedImports == null) ++ return new ImportPackageSpecification[0]; ++ return lazyData.supplementedImports; ++ } ++ ++ public ImportPackageSpecification[] getSupplementedExportPackages() { ++ fullyLoad(); ++ if (lazyData.supplementedExports == null) ++ return new ImportPackageSpecification[0]; ++ return lazyData.supplementedExports; ++ } ++ ++ // END AMC ++ ++ //knibb ++ ++ public BundleDescription[] getSupplementedBundles() { ++ fullyLoad(); ++ if (lazyData.SupplementedBundles == null) ++ return new BundleDescription[0]; ++ return lazyData.SupplementedBundles; ++ } ++ ++ //end knibb + + public BundleSpecification[] getRequiredBundles() { + fullyLoad(); +@@ -224,6 +253,31 @@ + } + } + ++ // AMC ++ ++ protected void setSupplementedImportPackages(ImportPackageSpecification[] supplementedImports) { ++ checkLazyData(); ++ lazyData.supplementedImports = supplementedImports; ++ } ++ ++ ++ protected void setSupplementedExportPackages(ImportPackageSpecification[] supplementedExports) { ++ checkLazyData(); ++ lazyData.supplementedExports = supplementedExports; ++ } ++ ++ // END AMC ++ ++ //knibb ++ ++ protected void setSupplementedBundles(BundleDescription[] supplementedBundles) { ++ checkLazyData(); ++ lazyData.SupplementedBundles = supplementedBundles; ++ } ++ ++ //end knibb ++ ++ + protected void setRequiredBundles(BundleSpecification[] requiredBundles) { + checkLazyData(); + lazyData.requiredBundles = requiredBundles; +@@ -543,5 +597,11 @@ + String[] executionEnvironments; + + HashMap dynamicStamps; ++ ++ // AMC ++ ImportPackageSpecification[] supplementedImports; ++ ImportPackageSpecification[] supplementedExports; ++ //knibb ++ BundleDescription[] SupplementedBundles; + } + } +Index: resolver/src/org/eclipse/osgi/internal/module/ResolverBundle.java +=================================================================== +RCS file: /home/eclipse/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverBundle.java,v +retrieving revision 1.20 +diff -u -r1.20 ResolverBundle.java +--- resolver/src/org/eclipse/osgi/internal/module/ResolverBundle.java 3 May 2006 13:35:59 -0000 1.20 ++++ resolver/src/org/eclipse/osgi/internal/module/ResolverBundle.java 9 May 2006 21:27:14 -0000 +@@ -252,6 +252,16 @@ + return allRequires[i]; + return null; + } ++ ++ // AMC ++ void addRequired(BundleConstraint required) { ++ BundleConstraint[] newRequires = new BundleConstraint[requires.length + 1]; ++ System.arraycopy(requires,0,newRequires,0,requires.length); ++ newRequires[requires.length] = required; ++ requires = newRequires; ++ } ++ ++ // End AMC + + public BundleDescription getBundle() { + return (BundleDescription) getBaseDescription(); +@@ -494,4 +504,4 @@ + int getRefs() { + return refs == null ? 0 : refs.size(); + } +-} ++} +\ No newline at end of file +Index: resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java +=================================================================== +RCS file: /home/eclipse/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java,v +retrieving revision 1.35 +diff -u -r1.35 ResolverImpl.java +--- resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java 17 Apr 2006 20:22:58 -0000 1.35 ++++ resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java 9 May 2006 21:27:16 -0000 +@@ -15,6 +15,7 @@ + import org.eclipse.osgi.framework.debug.Debug; + import org.eclipse.osgi.framework.debug.FrameworkDebugOptions; + import org.eclipse.osgi.internal.resolver.BundleDescriptionImpl; ++import org.eclipse.osgi.internal.resolver.BundleSpecificationImpl; + import org.eclipse.osgi.service.resolver.*; + import org.eclipse.osgi.util.ManifestElement; + import org.osgi.framework.*; +@@ -29,6 +30,7 @@ + private static final String OPTION_GENERICS = RESOLVER + "/generics"; //$NON-NLS-1$ + private static final String OPTION_GROUPING = RESOLVER + "/grouping"; //$NON-NLS-1$ + private static final String OPTION_CYCLES = RESOLVER + "/cycles"; //$NON-NLS-1$ ++ private static final String OPTION_SUPPLEMENTS = RESOLVER + "/supplements"; //$NON-NLS-1$ + public static boolean DEBUG = false; + public static boolean DEBUG_WIRING = false; + public static boolean DEBUG_IMPORTS = false; +@@ -571,6 +573,7 @@ + + // This method will attempt to resolve the supplied bundle and any bundles that it is dependent on + private boolean resolveBundle(ResolverBundle bundle, ArrayList cycle) { ++// System.out.println("ResolverImpl.resolveBundle() bundle=" + bundle.getName()); + if (bundle.isFragment()) + return false; + if (!bundle.isResolvable()) { +@@ -646,6 +649,100 @@ + } + } + } ++ ++ // AMC ++// System.err.println("? ResolverImpl.resolveBundle() bundle=" + bundle); //$NON-NLS-1$ ++ if (!failed) { ++ // XXX this feels horribly inefficient... ++ // Iterate thru resolver bundles looking for any supplementors of packages that this ++ // bundle imports or exports. If we find a match, resolve it as a required bundle of ++ // this bundle ++ // Exports first ++ ResolverExport[] exports = bundle.getExportPackages(); ++ outerExport: for (Iterator iter = resolverBundles.iterator(); iter.hasNext(); ) { ++ Object[] suppliers = (Object[]) iter.next(); ++ //suppliers is an array of ResolverBundle objects. ResolverBundle is a subclass of VersionSupplier ++ //so suppliers has type VersionSupplier[] ++ //unfortunately this results in a ClassCastException so that is why this is an Object[] and not VersionSupplier[] ++ for (int s = 0; s < suppliers.length; s++) { ++ //the cast from Object to VersionSupplier is made here ++ VersionSupplier supplier = (VersionSupplier) suppliers[s]; ++ BundleDescription desc = supplier.getBundle(); ++ ImportPackageSpecification[] supplements = desc.getSupplementedExportPackages(); ++ for (int i = 0; i < supplements.length; i++) { ++ for (int e = 0; e < exports.length; e++) { ++ if (supplements[i].getName().equals(exports[e].getName())) { ++ // it's a match ++ if(Debug.DEBUG_SUPPLEMENTS) ++ System.out.println("export " + exports[i] + " supplemented by " + desc); //$NON-NLS-1$//$NON-NLS-2$ ++ // add suppliers[s].getBundle as a required bundle for me... ++ addRequired(bundle,supplier.getBundle(), cycle); ++ continue outerExport; ++ } ++ } ++ } ++ } ++ } ++ // Then imports ++ ResolverImport[] imports = bundle.getImportPackages(); ++ outer: for (Iterator iter = resolverBundles.iterator(); iter.hasNext();) { ++ Object[] suppliers = (Object[]) iter.next(); ++ for (int s = 0; s < suppliers.length; s++) { ++ VersionSupplier supplier = (VersionSupplier) suppliers[s]; ++ BundleDescription desc = supplier.getBundle(); ++ ImportPackageSpecification[] supplements = desc.getSupplementedImportPackages(); ++ for (int i = 0; i < supplements.length; i++) { ++ for (int j = 0; j < imports.length; j++) { ++ ImportPackageSpecification possibleMatch = (ImportPackageSpecification) imports[j].getVersionConstraint(); ++ if (possibleMatch.getName().equals(supplements[i].getName())) { ++ // we have a match ++ if(Debug.DEBUG_SUPPLEMENTS) ++ System.out.println("import " + imports[j] + " supplemented by " + desc); //$NON-NLS-1$ //$NON-NLS-2$ ++ addRequired(bundle,supplier.getBundle(), cycle); ++ continue outer; ++ } ++ } ++ } ++ } ++ } ++ } ++ // END AMC ++ ++ //knibb ++ //now check for any other bundles which supplement this bundle ++ //TODO - would be usefull to have an exclusion mechanism here (e.g. you could then say someting like "supplement all bundles, except....") ++ if(!failed) { ++ String myName = bundle.getName(); ++ for (Iterator iter = resolverBundles.iterator(); iter.hasNext();) { ++ Object[] suppliers = (Object[]) iter.next(); ++ outerBundles: for(int s=0; s < suppliers.length; s++){ ++ VersionSupplier supplier = (VersionSupplier) suppliers[s]; ++ BundleDescription desc = supplier.getBundle(); ++ //don't want to supplement ourselves so break if desc and bundle are the same ++ if(bundle.getBundle().equals(desc)){ ++ continue outerBundles; ++ } ++ //supplemtor should not supplement any bundle on which it depends ++ BundleSpecification[] bundlesRequiredBySupplementor = desc.getRequiredBundles(); ++ for(int i=0; i<bundlesRequiredBySupplementor.length; i++){ ++ if(bundlesRequiredBySupplementor[i].getName().equals( myName )) ++ continue outerBundles; //avoid circular dependacy - do not allow a bundle to supplement any bundle on which it depends ++ } ++ BundleDescription[] supplemented = desc.getSupplementedBundles(); //the list of bundles it (desc) supplements ++ for(int i=0; i<supplemented.length; i++){ ++// if ( myName.equals(supplemented[i].getName())){ ++ if ( equals_wild(supplemented[i].getName(), myName)){ ++ addRequired(bundle, desc, cycle); ++ if(Debug.DEBUG_SUPPLEMENTS) ++ System.out.println("bundle Supplement-Bundle: " + bundle + " supplemeted by [" + desc +"]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ ++ } ++ } ++ } ++ } ++ } ++ ++ //end knibb ++ + // Need to check that all mandatory imports are wired. If they are then + // set the bundle RESOLVED, otherwise set it back to UNRESOLVED + if (failed) { +@@ -666,6 +763,16 @@ + return bundle.getState() != ResolverBundle.UNRESOLVED; + } + ++ // AMC ++ private void addRequired(ResolverBundle toBundle, BundleDescription toBeAdded, ArrayList cycle) { ++ // TODO ++ BundleSpecification spec = new BundleSpecificationImpl(toBeAdded.getName()); ++ BundleConstraint constraint = new BundleConstraint(toBundle,spec); ++ if (resolveRequire(constraint, cycle)) { ++ toBundle.addRequired(constraint); ++ } ++ } ++ + private boolean resolveGenericReq(GenericConstraint constraint, ArrayList cycle) { + if (DEBUG_REQUIRES) + ResolverImpl.log("Trying to resolve: " + constraint.getBundle() + ", " + constraint.getVersionConstraint()); //$NON-NLS-1$ //$NON-NLS-2$ +@@ -1328,6 +1435,25 @@ + VersionHashMap getResolverExports() { + return resolverExports; + } ++ ++ //knibb ++ //test if two Strings are equal ++ //with wild card support - only supports strings ending in * ++ private boolean equals_wild(String input, String match){ ++ if(input.equals(match)){ ++ //its a match so just return true ++ return true; ++ } ++ if(input.endsWith("*")==false){ ++ //no wildcards are being used here ++ return false; ++ } ++ String wild_in = input.substring(0, input.length()-1); ++ if(match.startsWith(wild_in)) ++ return true; ++ ++ return false; ++ } + + public void setSelectionPolicy(Comparator selectionPolicy) { + this.selectionPolicy = selectionPolicy; +Index: resolver/src/org/eclipse/osgi/internal/module/VersionHashMap.java +=================================================================== +RCS file: /home/eclipse/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/VersionHashMap.java,v +retrieving revision 1.5 +diff -u -r1.5 VersionHashMap.java +--- resolver/src/org/eclipse/osgi/internal/module/VersionHashMap.java 23 Jan 2006 19:13:00 -0000 1.5 ++++ resolver/src/org/eclipse/osgi/internal/module/VersionHashMap.java 9 May 2006 21:27:16 -0000 +@@ -28,6 +28,14 @@ + for (int i = 0; i < versionSuppliers.length; i++) + put(versionSuppliers[i].getName(), versionSuppliers[i]); + } ++ ++ // AMC ++ ++ Iterator iterator() { ++ return internal.values().iterator(); ++ } ++ ++ // END AMC + + public void put(Object key, Object value) { + super.put(key, value); +Index: .options +=================================================================== +RCS file: /home/eclipse/org.eclipse.osgi/.options,v +retrieving revision 1.14 +diff -u -r1.14 .options +--- .options 1 May 2006 17:08:49 -0000 1.14 ++++ .options 9 May 2006 21:27:12 -0000 +@@ -23,6 +23,9 @@ + # Debug the loading of message bundles + org.eclipse.osgi/debug/messageBundles=false + ++# Debug supplements mechanism ++org.eclipse.osgi/debug/supplements=false ++ + # Eclipse adaptor options + org.eclipse.osgi/eclipseadaptor/debug = false + org.eclipse.osgi/eclipseadaptor/debug/location = false +Index: core/framework/org/eclipse/osgi/framework/debug/Debug.java +=================================================================== +RCS file: /home/eclipse/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/debug/Debug.java,v +retrieving revision 1.17 +diff -u -r1.17 Debug.java +--- core/framework/org/eclipse/osgi/framework/debug/Debug.java 1 May 2006 15:37:20 -0000 1.17 ++++ core/framework/org/eclipse/osgi/framework/debug/Debug.java 9 May 2006 21:27:12 -0000 +@@ -90,6 +90,12 @@ + public static boolean MONITOR_ACTIVATION = false; // "monitor/bundles" + + /** ++ * Show info about the supplements mechanism ++ */ ++// public static boolean DEBUG_SUPPLEMENTS = Boolean.getBoolean("org.eclipse.osgi.showSupplementsInfo"); //$NON-NLS-1$ //$NON-NLS-2$ ++ public static boolean DEBUG_SUPPLEMENTS = false; // "debug/supplements" ++ ++ /** + * Base debug option key (org.eclispe.osgi). + */ + public static final String ECLIPSE_OSGI = "org.eclipse.osgi"; //$NON-NLS-1$ +@@ -150,6 +156,10 @@ + * Message bundles Debug option key. + */ + public static final String OPTION_DEBUG_MESSAGE_BUNDLES = ECLIPSE_OSGI + "/debug/messageBundles"; //$NON-NLS-1$ ++ /** ++ * Supplements mechansism Debug option key. ++ */ ++ public static final String OPTION_DEBUG_SUPPLEMENTS = ECLIPSE_OSGI + "/debug/supplements"; //$NON-NLS-1$ + + static { + FrameworkDebugOptions dbgOptions = FrameworkDebugOptions.getDefault(); +@@ -168,6 +178,7 @@ + DEBUG_PACKAGEADMIN = dbgOptions.getBooleanOption(OPTION_DEBUG_PACKAGEADMIN, false); + DEBUG_PACKAGEADMIN_TIMING = dbgOptions.getBooleanOption(OPTION_DEBUG_PACKAGEADMIN_TIMING, false) || dbgOptions.getBooleanOption("org.eclipse.core.runtime/debug", false); //$NON-NLS-1$ + DEBUG_MESSAGE_BUNDLES = dbgOptions.getBooleanOption(OPTION_DEBUG_MESSAGE_BUNDLES, false); ++ DEBUG_SUPPLEMENTS = dbgOptions.getBooleanOption(OPTION_DEBUG_SUPPLEMENTS, false); + MONITOR_ACTIVATION = dbgOptions.getBooleanOption(OPTION_MONITOR_ACTIVATION, false); + } + } +@@ -351,4 +362,4 @@ + } + } + +-} ++} +\ No newline at end of file +Index: defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/ClasspathManager.java +=================================================================== +RCS file: /home/eclipse/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/ClasspathManager.java,v +retrieving revision 1.6 +diff -u -r1.6 ClasspathManager.java +--- defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/ClasspathManager.java 1 May 2006 14:14:24 -0000 1.6 ++++ defaultAdaptor/src/org/eclipse/osgi/baseadaptor/loader/ClasspathManager.java 9 May 2006 21:27:14 -0000 +@@ -68,6 +68,10 @@ + * </p> + */ + public void initialize() { ++// String bundleName = data.getSymbolicName(); ++// if (bundleName.equals("org.eclipse.osgi.aspectj.tests")) { ++// System.out.println("? ClasspathManager.initialize() bundle=" + bundleName); ++// } + entries = buildClasspath(classpath, this, data, classloader.getDomain()); + ClassLoadingHook[] hooks = data.getAdaptor().getHookRegistry().getClassLoadingHooks(); + for (int i = 0; i < hooks.length; i++) +@@ -530,4 +534,4 @@ + return classloader; + } + +-} ++} +\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.weaving.hook/readme.txt b/bundles/org.eclipse.equinox.weaving.hook/readme.txt new file mode 100644 index 000000000..a5fcf7b48 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/readme.txt @@ -0,0 +1,15 @@ +This version works with Eclipse 3.2 Final only. Checkout projects org.aspectj.osgi, +org.aspectj.osgi.service.weaving and org.eclipse.osgi_3.2.0. The OSGi bundle is +needed to run the org.aspectj.osgi Framework Extension bundle fragment as a +source project (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143696). + +To run the accompanying tests checkout all the projects in aspects/tests and +open the WeavingTest.lauch configuration. + +To run the demos checkout the projects in aspects/demos. +- HelloWorld: run HelloWorldTest in the demo.hello bundle as a JUnit Plug-in +test with the config.ini in the org.aspectj.osgi project. +- Tooltip: run "Tooltip Demo.launch" in demo.eclipse.tooltip as an +Eclipse Application using the config.ini in the same project. +- Tracing: run "Eclipse Tracing Demo.launch" in demo.eclipse.tooltip as an +Eclipse Application using the config.ini in the same project.
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/service/weaving/ICachingService.java b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/service/weaving/ICachingService.java new file mode 100644 index 000000000..df251b4be --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/service/weaving/ICachingService.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + * Matthew Webster Eclipse 3.2 changes + *******************************************************************************/ + +package org.eclipse.equinox.service.weaving; + +import java.net.URL; + +import org.osgi.framework.Bundle; + +public interface ICachingService { + + public ICachingService getInstance(ClassLoader classLoader, Bundle bundle, String key); + + public byte[] findStoredClass(String namespace, URL sourceFileURL, String name); + + public boolean storeClass(String namespace, URL sourceFileURL, Class clazz, byte[] classbytes); + +} diff --git a/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/service/weaving/IWeavingService.java b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/service/weaving/IWeavingService.java new file mode 100644 index 000000000..72f568168 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/service/weaving/IWeavingService.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + * Matthew Webster Eclipse 3.2 changes + *******************************************************************************/ + +package org.eclipse.equinox.service.weaving; + +import java.io.IOException; + +import org.eclipse.osgi.service.resolver.BundleDescription; +import org.eclipse.osgi.service.resolver.State; +import org.osgi.framework.Bundle; + +public interface IWeavingService { + + public IWeavingService getInstance(ClassLoader loader, Bundle bundle, + State resolverState, BundleDescription bundleDesciption, + SupplementerRegistry supplementerRegistry); + + public byte[] preProcess(String name, byte[] classbytes, ClassLoader loader) + throws IOException; + + public String getKey(); + + public boolean generatedClassesExistFor(ClassLoader loader, String className); + + public void flushGeneratedClasses(ClassLoader loader); + +} diff --git a/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/service/weaving/SupplementerRegistry.java b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/service/weaving/SupplementerRegistry.java new file mode 100644 index 000000000..d0fdea180 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/service/weaving/SupplementerRegistry.java @@ -0,0 +1,259 @@ +/******************************************************************************* + * Copyright (c) 2008 Martin Lippert and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Matthew Webster initial implementation + * Martin Lippert supplementing mechanism reworked + *******************************************************************************/ + +package org.eclipse.equinox.service.weaving; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.eclipse.equinox.weaving.hooks.AbstractAspectJHook; +import org.eclipse.equinox.weaving.hooks.Supplementer; +import org.eclipse.osgi.util.ManifestElement; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; +import org.osgi.service.packageadmin.PackageAdmin; + +public class SupplementerRegistry { + + /** + * Manifest header (named "Supplement-Importer") identifying the names + * (and optionally, version numbers) of the packages that the bundle supplements. + * All importers of one of these packages will have the exported packages of this + * bundle added to their imports in addition. + * + * <p> + * The attribute value may be retrieved from the <code>Dictionary</code> + * object returned by the <code>Bundle.getHeaders</code> method. + */ + public static final String SUPPLEMENT_IMPORTER = "Eclipse-SupplementImporter"; //$NON-NLS-1$ + + /** + * Manifest header (named "Supplement-Exporter") identifying the names + * (and optionally, version numbers) of the packages that the bundle supplements. + * All exporters of one of these packages will have the exported packages of this bundle + * added to their imports list. + * + * <p> + * The attribute value may be retrieved from the <code>Dictionary</code> + * object returned by the <code>Bundle.getHeaders</code> method. + */ + public static final String SUPPLEMENT_EXPORTER = "Eclipse-SupplementExporter"; //$NON-NLS-1$ + + //knibb + /** + * Manifest header (named "Supplement-Bundle") identifying the names + * (and optionally, version numbers) of any bundles supplemented by this bundle. + * All supplemented bundles will have all the exported packages of this bundle + * added to their imports list + * + * <p> + * The attribute value may be retrieved from the <code>Dictionary</code> + * object returned by the <code>Bundle.getHeaders</code> method. + */ + public static final String SUPPLEMENT_BUNDLE = "Eclipse-SupplementBundle"; //$NON-NLS-1$ + + private final Map supplementers; // keys of type String (symbolic name of supplementer bundle), values of type Supplementer + private BundleContext context; + private PackageAdmin packageAdmin; + + public SupplementerRegistry() { + this.supplementers = new HashMap(); + } + + public void setBundleContext(BundleContext context) { + this.context = context; + } + + public void setPackageAdmin(PackageAdmin packageAdmin) { + this.packageAdmin = packageAdmin; + } + + public void addSupplementer(Bundle bundle) { + Dictionary manifest = bundle.getHeaders(); + try { + // First analyze which supplementers already exists for this bundle + ManifestElement[] imports = ManifestElement.parseHeader(Constants.IMPORT_PACKAGE, (String) manifest.get(Constants.IMPORT_PACKAGE)); + ManifestElement[] exports = ManifestElement.parseHeader(Constants.EXPORT_PACKAGE, (String) manifest.get(Constants.EXPORT_PACKAGE)); + List supplementers = getSupplementers(bundle.getSymbolicName(), imports, exports); + if (supplementers.size() > 0) { + this.addSupplementedBundle(bundle, supplementers); + } + + // Second analyze if this bundle itself is a supplementer + ManifestElement[] supplementBundle = ManifestElement.parseHeader(SUPPLEMENT_BUNDLE, (String) manifest.get(SUPPLEMENT_BUNDLE)); + ManifestElement[] supplementImporter = ManifestElement.parseHeader(SUPPLEMENT_IMPORTER, (String) manifest.get(SUPPLEMENT_IMPORTER)); + ManifestElement[] supplementExporter = ManifestElement.parseHeader(SUPPLEMENT_EXPORTER, (String) manifest.get(SUPPLEMENT_EXPORTER)); + + if (supplementBundle != null || supplementImporter != null || supplementExporter != null) { + Supplementer newSupplementer = new Supplementer(bundle, supplementBundle, supplementImporter, supplementExporter); + + this.supplementers.put(bundle.getSymbolicName(), newSupplementer); + resupplementInstalledBundles(newSupplementer); + } + } + catch (BundleException e) { + } + } + + public void removeSupplementer(Bundle bundle) { + // if this bundle is itself supplemented by others, remove the bundle from those lists + removeSupplementedBundle(bundle); + + // if this bundle supplements other bundles, remove this supplementer and update the other bundles + if (supplementers.containsKey(bundle.getSymbolicName())) { + Supplementer supplementer = (Supplementer) supplementers.get(bundle.getSymbolicName()); + supplementers.remove(bundle.getSymbolicName()); + if (AbstractAspectJHook.verbose) System.err.println("[org.aspectj.osgi] info removing supplementer " + bundle.getSymbolicName()); + + Bundle[] supplementedBundles = supplementer.getSupplementedBundles(); + for (int i = 0; i < supplementedBundles.length; i++) { + Bundle supplementedBundle = supplementedBundles[i]; + if (supplementedBundle != null) { + updateInstalledBundle(supplementedBundle); + } + } + } + } + + public List getSupplementers (String symbolicName, ManifestElement[] imports, ManifestElement[] exports) { + List result = Collections.EMPTY_LIST; + + if (supplementers.size() > 0) { + result = new LinkedList(); + for (Iterator i = supplementers.values().iterator(); i.hasNext();) { + Supplementer supplementer = (Supplementer) i.next(); + if (isSupplementerMatching(symbolicName, imports, exports, supplementer)) { + result.add(supplementer.getSymbolicName()); + } + } + } + + return result; + } + + public Bundle[] getSupplementers(Bundle bundle) { + List result = Collections.EMPTY_LIST; + + if (supplementers.size() > 0) { + result = new ArrayList(); + for (Iterator i = supplementers.values().iterator(); i.hasNext();) { + Supplementer supplementer = (Supplementer) i.next(); + if (supplementer.isSupplemented(bundle)) { + result.add(supplementer.getSupplementerBundle()); + } + } + } + + return (Bundle[]) result.toArray(new Bundle[result.size()]); + } + + public void addSupplementedBundle(Bundle supplementedBundle, List supplementers) { + for (Iterator iterator = supplementers.iterator(); iterator.hasNext();) { + String supplementersName = (String) iterator.next(); + if (this.supplementers.containsKey(supplementersName)) { + Supplementer supplementer = (Supplementer) this.supplementers.get(supplementersName); + supplementer.addSupplementedBundle(supplementedBundle); + } + } + } + + public void removeSupplementedBundle(Bundle bundle) { + for (Iterator iterator = this.supplementers.values().iterator(); iterator.hasNext();) { + Supplementer supplementer = (Supplementer) iterator.next(); + supplementer.removeSupplementedBundle(bundle); + } + } + + private boolean isSupplementerMatching(String symbolicName, + ManifestElement[] imports, ManifestElement[] exports, Supplementer supplementer) { + String supplementerName = supplementer.getSymbolicName(); + if (!supplementerName.equals(symbolicName)) { + if (supplementer.matchSupplementer(symbolicName) + || (imports != null && supplementer.matchesSupplementImporter(imports)) + || (exports != null && supplementer.matchesSupplementExporter(exports))) { + return true; + } + } + return false; + } + + private void resupplementInstalledBundles(Supplementer supplementer) { + Bundle[] installedBundles = context.getBundles(); + + for (int i = 0; i < installedBundles.length; i++) { + try { + Bundle bundle = installedBundles[i]; + + if (bundle.getSymbolicName().equals(supplementer.getSymbolicName())) { + continue; + } + + Dictionary manifest = bundle.getHeaders(); + ManifestElement[] imports = ManifestElement.parseHeader(Constants.IMPORT_PACKAGE, (String) manifest.get(Constants.IMPORT_PACKAGE)); + ManifestElement[] exports = ManifestElement.parseHeader(Constants.EXPORT_PACKAGE, (String) manifest.get(Constants.EXPORT_PACKAGE)); + + if (isSupplementerMatching(bundle.getSymbolicName(), imports, exports, supplementer)) { + boolean alreadyRequired = false; + ManifestElement[] requires = ManifestElement.parseHeader(Constants.REQUIRE_BUNDLE, (String) manifest.get(Constants.REQUIRE_BUNDLE)); + if (requires != null) { + for (int j = 0; j < requires.length; j++) { + if (requires[j].getValue().equals(supplementer.getSymbolicName())) { + alreadyRequired = true; + } + } + } + + if (!alreadyRequired) { + updateInstalledBundle(bundle); + } + } + + } catch (BundleException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + private void updateInstalledBundle(Bundle bundle) { + + String symbolicName = bundle.getSymbolicName(); + + if (symbolicName.equals("org.eclipse.osgi")) return; + if (symbolicName.equals("org.aspectj.osgi")) return; + if (symbolicName.startsWith("org.eclipse.update")) return; + if (symbolicName.startsWith("org.eclipse.core.runtime")) return; + if (symbolicName.startsWith("org.aspectj.osgi.service")) return; + if (symbolicName.startsWith("org.eclipse.equinox")) return; + + if (AbstractAspectJHook.verbose) System.err.println("[org.aspectj.osgi] info triggering update for re-supplementing " + symbolicName); + + try { + int initialstate = (bundle.getState() | (Bundle.ACTIVE | Bundle.STARTING)); + if (initialstate != 0 && packageAdmin != null && packageAdmin.getBundleType(bundle) != PackageAdmin.BUNDLE_TYPE_FRAGMENT) + bundle.stop(Bundle.STOP_TRANSIENT); + bundle.update(); + } + catch (BundleException e) { + e.printStackTrace(); + } + } + +} diff --git a/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/adaptors/AspectJAdaptor.java b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/adaptors/AspectJAdaptor.java new file mode 100644 index 000000000..fefc30956 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/adaptors/AspectJAdaptor.java @@ -0,0 +1,189 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + * Matthew Webster Eclipse 3.2 changes + * Martin Lippert minor changes and bugfixes + *******************************************************************************/ +package org.eclipse.equinox.weaving.adaptors; + +import java.io.IOException; +import java.net.URL; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.equinox.service.weaving.ICachingService; +import org.eclipse.equinox.service.weaving.IWeavingService; +import org.eclipse.equinox.weaving.hooks.AspectJBundleFile; +import org.eclipse.osgi.baseadaptor.BaseData; +import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile; +import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader; +import org.eclipse.osgi.framework.internal.core.BundleFragment; +import org.eclipse.osgi.framework.internal.core.BundleHost; +import org.osgi.framework.Bundle; + +public class AspectJAdaptor implements IAspectJAdaptor { + + private boolean initialized = false; + private BaseData data; + private AspectJAdaptorFactory factory; + private BaseClassLoader baseLoader; + private Bundle bundle; + private String symbolicName; + private IWeavingService weavingService; + private ICachingService cachingService; + + private static ThreadLocalSet identifyRecursionSet = new ThreadLocalSet(); + + private static class ThreadLocalSet extends ThreadLocal { + + public void put(Object obj) { + Set set = (Set) get(); + if (set.contains(obj)) { + throw new RuntimeException(obj.toString()); + } + set.add(obj); + } + + public void remove(Object obj) { + Set set = (Set) get(); + if (!set.contains(obj)) { + throw new RuntimeException(obj.toString()); + } + set.remove(obj); + } + + public boolean contains(Object obj) { + Set set = (Set) get(); + return set.contains(obj); + } + + protected Object initialValue() { + return new HashSet(); + } + } + + public AspectJAdaptor (BaseData baseData, AspectJAdaptorFactory serviceFactory, BaseClassLoader baseClassLoader, IWeavingService weavingService, ICachingService cachingService) { + this.data = baseData; + this.factory = serviceFactory; + this.symbolicName = baseData.getLocation(); + if (Debug.DEBUG_GENERAL) Debug.println("- AspectJAdaptor.AspectJAdaptor() bundle=" + symbolicName); + } + + private void initialize () { + synchronized(this) { + if (initialized) return; + + this.bundle = data.getBundle(); + this.symbolicName = data.getSymbolicName(); + if (!identifyRecursionSet.contains(this)) { + identifyRecursionSet.put(this); + + if (Debug.DEBUG_GENERAL) Debug.println("> AspectJAdaptor.initialize() bundle=" + symbolicName + ", baseLoader=" + baseLoader); + + if (symbolicName.startsWith("org.aspectj")) { + if (Debug.DEBUG_GENERAL) Debug.println("- AspectJAdaptor.initialize() symbolicName=" + symbolicName + ", baseLoader=" + baseLoader); + } + else if (baseLoader != null) { + weavingService = factory.getWeavingService(baseLoader); + cachingService = factory.getCachingService(baseLoader,bundle,weavingService); + } + else if (bundle instanceof BundleFragment) { + BundleFragment fragment = (BundleFragment)bundle; + BundleHost host = (BundleHost)factory.getHost(fragment); + if (Debug.DEBUG_GENERAL) Debug.println("- AspectJAdaptor.initialize() symbolicName=" + symbolicName + ", host=" + host); + + BaseData hostData = (BaseData)host.getBundleData(); + // System.err.println("? AspectJAdaptor.initialize() bundleData=" + hostData); + BundleFile bundleFile = hostData.getBundleFile(); + if (bundleFile instanceof AspectJBundleFile) { + AspectJBundleFile hostFile = (AspectJBundleFile)bundleFile; + // System.err.println("? AspectJAdaptor.initialize() bundleFile=" + hostFile); + AspectJAdaptor hostAdaptor = (AspectJAdaptor)hostFile.getAdaptor(); + // System.err.println("? AspectJAdaptor.initialize() bundleFile=" + hostAdaptor); + weavingService = hostAdaptor.weavingService; + cachingService = factory.getCachingService(hostAdaptor.baseLoader,bundle,weavingService); + } + } + else { + if (Debug.DEBUG_GENERAL) Debug.println("W AspectJAdaptor.initialize() symbolicName=" + symbolicName + ", baseLoader=" + baseLoader); + } + initialized = true; + identifyRecursionSet.remove(this); + } + + if (Debug.DEBUG_GENERAL) Debug.println("< AspectJAdaptor.initialize() weavingService=" + (weavingService != null) + ", cachingService=" + (cachingService != null)); + } + } + + public void setBaseClassLoader (BaseClassLoader baseClassLoader) { + this.baseLoader = baseClassLoader; + + if (Debug.DEBUG_GENERAL) Debug.println("- AspectJAdaptor.setBaseClassLoader() bundle=" + symbolicName + ", baseLoader=" + baseLoader); + } + + public byte[] findClass (String name, URL sourceFileURL) { + if (Debug.DEBUG_CACHE) Debug.println("> AspectJAdaptor.findClass() bundle=" + symbolicName + ", url=" + sourceFileURL + ", name=" + name); + byte[] bytes = null; + + initialize(); + if (cachingService != null) { + bytes = cachingService.findStoredClass("",sourceFileURL,name); + } + + if (Debug.DEBUG_CACHE) Debug.println("< AspectJAdaptor.findClass() bytes=" + bytes); + return bytes; + } + + public byte[] weaveClass (String name, byte[] bytes) { + if (Debug.DEBUG_WEAVE) Debug.println("> AspectJAdaptor.weaveClass() bundle=" + symbolicName + ", name=" + name + ", bytes=" + bytes.length); + byte[] newBytes = null; + + initialize(); + if (/*shouldWeave(bytes) && */ weavingService != null){ + try { + newBytes = weavingService.preProcess(name,bytes,(ClassLoader)baseLoader); + } + catch (IOException ex) { + throw new ClassFormatError(ex.toString()); + } + } + + if (Debug.DEBUG_WEAVE) Debug.println("< AspectJAdaptor.weaveClass() newBytes=" + newBytes); + return newBytes; + } + + public boolean storeClass (String name, URL sourceFileURL, Class clazz, byte[] classbytes) { + if (Debug.DEBUG_CACHE) Debug.println("> AspectJAdaptor.storeClass() bundle=" + symbolicName + ", url=" + sourceFileURL + ", name=" + name + ", clazz=" + clazz); + boolean stored = false; + + initialize(); + if (cachingService != null) { + //have we generated a closure? + //If so we cannot store in shared cache (as closure will be lost for future runs) + if (weavingService != null && weavingService.generatedClassesExistFor((ClassLoader)baseLoader,name)) { + weavingService.flushGeneratedClasses((ClassLoader)baseLoader); + if (Debug.DEBUG_CACHE) Debug.println("- AspectJAdaptor.storeClass() generatedClassesExistFor=true"); +// return clazz; + } + else{ + stored = cachingService.storeClass("",sourceFileURL,clazz,classbytes); + if(!stored){ + if (Debug.DEBUG_CACHE) Debug.println("E AspectJHook.storeClass() bundle=" + symbolicName + ", name=" + name); + } + } + } + if (Debug.DEBUG_CACHE) Debug.println("< AspectJAdaptor.storeClass() stored=" + stored); + return stored; + } + + public String toString () { + return "AspectJAdaptor[" + symbolicName + "]"; + } + +}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/adaptors/AspectJAdaptorFactory.java b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/adaptors/AspectJAdaptorFactory.java new file mode 100644 index 000000000..a9535a916 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/adaptors/AspectJAdaptorFactory.java @@ -0,0 +1,153 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + * Matthew Webster Eclipse 3.2 changes + *******************************************************************************/ +package org.eclipse.equinox.weaving.adaptors; + +import org.eclipse.equinox.service.weaving.ICachingService; +import org.eclipse.equinox.service.weaving.IWeavingService; +import org.eclipse.equinox.service.weaving.SupplementerRegistry; +import org.eclipse.osgi.baseadaptor.BaseData; +import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader; +import org.eclipse.osgi.service.resolver.BundleDescription; +import org.eclipse.osgi.service.resolver.State; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceEvent; +import org.osgi.framework.ServiceListener; +import org.osgi.framework.ServiceReference; +import org.osgi.service.packageadmin.PackageAdmin; + +public class AspectJAdaptorFactory { + + private BundleContext bundleContext; + private IWeavingService singletonWeavingService; + private ICachingService singletonCachingService; + private PackageAdmin packageAdminService; + private SupplementerRegistry supplementerRegistry; + + public AspectJAdaptorFactory () { + } + + public void initialize (BundleContext context, SupplementerRegistry supplementerRegistry) { + if (Debug.DEBUG_GENERAL) Debug.println("> AspectJAdaptorFactory.initialize() context=" + context); + this.bundleContext = context; + this.supplementerRegistry = supplementerRegistry; + + String weavingFilter = "(objectclass="+IWeavingService.class.getName()+")"; + String cachingFilter = "(objectclass="+ICachingService.class.getName()+")"; + /* + * Add listeners to listen for the + * registration of the weaving and caching services + */ + ServiceListener weavingListener = new ServiceListener() { + + public void serviceChanged(ServiceEvent event) { + if(event.getType() == ServiceEvent.REGISTERED) { +// System.err.println("ServiceListener.serviceChanged() event=" + event); + initializeWeavingService(); + } + } + + }; + + ServiceListener cachingListener = new ServiceListener(){ + + public void serviceChanged(ServiceEvent event) { + if(event.getType() == ServiceEvent.REGISTERED) { +// System.err.println("ServiceListener.serviceChanged() event=" + event); + initializeCachingService(); + } + } + + }; + + try { + bundleContext.addServiceListener(weavingListener,weavingFilter); + bundleContext.addServiceListener(cachingListener,cachingFilter); + } + catch (Exception ex) { + ex.printStackTrace(); + } + + initializePackageAdminService(context); + + if (Debug.DEBUG_GENERAL) Debug.println("< AspectJAdaptorFactory.initialize() weavingListener=" + weavingListener + ", cachingListener=" + cachingListener); + } + + protected void initializeWeavingService () { + if (Debug.DEBUG_GENERAL) Debug.println("> AspectJAdaptorFactory.initializeWeavingService()"); + ServiceReference ref = bundleContext.getServiceReference(IWeavingService.class.getName()); + if (ref!=null){ + singletonWeavingService = (IWeavingService)bundleContext.getService(ref); + } + if (Debug.DEBUG_GENERAL) Debug.println("< AspectJAdaptorFactory.initializeWeavingService() weavingService=" + singletonWeavingService); + } + + protected IWeavingService getWeavingService (BaseClassLoader loader) { + if (Debug.DEBUG_WEAVE) Debug.println("> AspectJAdaptorFactory.getWeavingService() baseClassLoader=" + loader); + IWeavingService weavingService = null; + + if (singletonWeavingService != null) { + BaseData baseData = loader.getClasspathManager().getBaseData(); + State state = baseData.getAdaptor().getState(); + Bundle bundle = baseData.getBundle(); + BundleDescription bundleDescription = state.getBundle(bundle.getBundleId()); + weavingService = singletonWeavingService.getInstance((ClassLoader)loader, bundle, state, bundleDescription, supplementerRegistry); + } + if (Debug.DEBUG_WEAVE) Debug.println("< AspectJAdaptorFactory.getWeavingService() service=" + weavingService); + return weavingService; + } + + protected void initializeCachingService () { + if (Debug.DEBUG_CACHE) Debug.println("> AspectJAdaptorFactory.initializeCachingService()"); + ServiceReference ref = bundleContext.getServiceReference(ICachingService.class.getName()); + if (ref != null){ + singletonCachingService = (ICachingService)bundleContext.getService(ref); + } + if (Debug.DEBUG_CACHE) Debug.println("< AspectJAdaptorFactory.initializeCachingService() singletonCachingService=" + singletonCachingService); + } + + protected ICachingService getCachingService (BaseClassLoader loader, Bundle bundle, IWeavingService weavingService) { + if (Debug.DEBUG_CACHE) Debug.println("> AspectJAdaptorFactory.getCachingService() bundle=" + bundle + ", weavingService=" + weavingService); + ICachingService service = null; + String key = ""; + + if (weavingService != null) { + key = weavingService.getKey(); + } + if (singletonCachingService != null) { + service = singletonCachingService.getInstance((ClassLoader)loader,bundle,key); + } + if (Debug.DEBUG_CACHE) Debug.println("< AspectJAdaptorFactory.getCachingService() service=" + service + ", key='" + key + "'"); + return service; + } + + private void initializePackageAdminService (BundleContext context) { + if (Debug.DEBUG_GENERAL) Debug.println("> AspectJAdaptorFactory.initializePackageAdminService() context=" + context); + + ServiceReference ref = context.getServiceReference(PackageAdmin.class.getName()); + if (ref != null) { + packageAdminService = (PackageAdmin)context.getService(ref); + } + + if (Debug.DEBUG_GENERAL) Debug.println("< AspectJAdaptorFactory.initializePackageAdminService() " + packageAdminService); + } + + public Bundle getHost (Bundle fragment) { + if (Debug.DEBUG_GENERAL) Debug.println("> AspectJAdaptorFactory.getHost() fragment=" + fragment); + + Bundle host = null; + if (packageAdminService != null) host = packageAdminService.getHosts(fragment)[0]; + + if (Debug.DEBUG_GENERAL) Debug.println("< AspectJAdaptorFactory.getHost() " + host); + return host; + } +} diff --git a/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/adaptors/Debug.java b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/adaptors/Debug.java new file mode 100644 index 000000000..d045a5c9f --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/adaptors/Debug.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Matthew Webster initial implementation + *******************************************************************************/ + +package org.eclipse.equinox.weaving.adaptors; + +import org.eclipse.osgi.framework.debug.FrameworkDebugOptions; + +public class Debug { + + public static boolean DEBUG_GENERAL; + public static boolean DEBUG_BUNDLE; + public static boolean DEBUG_WEAVE; + public static boolean DEBUG_CACHE; + public static boolean DEBUG_SUPPLEMENTS; + + private static String bundleName; + + public static boolean bundleNameMatches (String name) { + return name.equals(bundleName); + } + + public static final String ASPECTJ_OSGI = "org.aspectj.osgi"; + public static final String OPTION_DEBUG_GENERAL = ASPECTJ_OSGI + "/debug"; + public static final String OPTION_DEBUG_BUNDLE = ASPECTJ_OSGI + "/debug/bundle"; + public static final String OPTION_DEBUG_WEAVE = ASPECTJ_OSGI + "/debug/weave"; + public static final String OPTION_DEBUG_CACHE = ASPECTJ_OSGI + "/debug/cache"; + public static final String OPTION_DEBUG_BUNDLENAME = ASPECTJ_OSGI + "/debug/bundleName"; + public static final String OPTION_DEBUG_SUPPLEMENTS = ASPECTJ_OSGI + "/debug/supplements"; + + static { + FrameworkDebugOptions fdo = FrameworkDebugOptions.getDefault(); + if (fdo != null) { + DEBUG_GENERAL = fdo.getBooleanOption(OPTION_DEBUG_GENERAL,false); + DEBUG_BUNDLE = fdo.getBooleanOption(OPTION_DEBUG_BUNDLE,false); + DEBUG_WEAVE = fdo.getBooleanOption(OPTION_DEBUG_WEAVE,false); + DEBUG_CACHE = fdo.getBooleanOption(OPTION_DEBUG_CACHE,false); + bundleName = fdo.getOption(OPTION_DEBUG_BUNDLENAME,""); + DEBUG_SUPPLEMENTS = fdo.getBooleanOption(OPTION_DEBUG_SUPPLEMENTS,false); + } + } + + public static void println (String s) { + /*if (s.indexOf("org.eclipse.osgi.tests") != -1)*/ System.err.println(s); + } +} diff --git a/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/adaptors/IAspectJAdaptor.java b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/adaptors/IAspectJAdaptor.java new file mode 100644 index 000000000..c6acb5af2 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/adaptors/IAspectJAdaptor.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + * Matthew Webster Eclipse 3.2 changes + *******************************************************************************/ +package org.eclipse.equinox.weaving.adaptors; + +import java.net.URL; + +import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader; + +public interface IAspectJAdaptor { + + public void setBaseClassLoader (BaseClassLoader baseClassLoader); + + public byte[] findClass (String name, URL sourceFileURL); + + public byte[] weaveClass (String name, byte[] bytes); + + public boolean storeClass (String name, URL sourceFileURL, Class clazz, byte[] classbytes); + +} diff --git a/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/AbstractAJBundleFile.java b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/AbstractAJBundleFile.java new file mode 100644 index 000000000..b2d0fe4c2 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/AbstractAJBundleFile.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + * Matthew Webster Eclipse 3.2 changes + *******************************************************************************/ + +package org.eclipse.equinox.weaving.hooks; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; + +import org.eclipse.equinox.weaving.adaptors.IAspectJAdaptor; +import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry; +import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile; + +public abstract class AbstractAJBundleFile extends BundleFile { + + protected IAspectJAdaptor adaptor; + protected BundleFile delegate; + + public AbstractAJBundleFile (IAspectJAdaptor aspectjAdaptor, BundleFile bundleFile) { + super(bundleFile.getBaseFile()); + this.adaptor = aspectjAdaptor; + this.delegate = bundleFile; + } + + public File getBaseFile() { + File baseFile = delegate.getBaseFile(); + return baseFile; + } + + /** + * @deprecated + */ + public URL getResourceURL(String path, long hostBundleID, int index) { + return delegate.getResourceURL(path, hostBundleID, index); + } + + /** + * @deprecated + */ + public URL getResourceURL(String path, long hostBundleID) { + return delegate.getResourceURL(path, hostBundleID); + } + + public void close() throws IOException { + delegate.close(); + } + + public boolean containsDir(String dir) { + return delegate.containsDir(dir); + } + + public BundleEntry getEntry(String path) { + return delegate.getEntry(path); + } + + public Enumeration getEntryPaths(String path) { + return delegate.getEntryPaths(path); + } + + public File getFile(String path, boolean nativeCode) { + return delegate.getFile(path, nativeCode); + } + + public void open() throws IOException { + delegate.open(); + } + + public IAspectJAdaptor getAdaptor() { + return adaptor; + } + +} diff --git a/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/AbstractAspectJHook.java b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/AbstractAspectJHook.java new file mode 100644 index 000000000..89f1465ef --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/AbstractAspectJHook.java @@ -0,0 +1,169 @@ +/******************************************************************************* + * Copyright (c) 2006, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Matthew Webster initial implementation + * Martin Lippert supplementing mechanism reworked + *******************************************************************************/ + +package org.eclipse.equinox.weaving.hooks; + +import java.io.IOException; +import java.net.URL; +import java.net.URLConnection; +import java.security.ProtectionDomain; +import java.util.ArrayList; +import java.util.Properties; + +import org.eclipse.equinox.service.weaving.SupplementerRegistry; +import org.eclipse.osgi.baseadaptor.BaseAdaptor; +import org.eclipse.osgi.baseadaptor.BaseData; +import org.eclipse.osgi.baseadaptor.HookConfigurator; +import org.eclipse.osgi.baseadaptor.HookRegistry; +import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry; +import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile; +import org.eclipse.osgi.baseadaptor.hooks.AdaptorHook; +import org.eclipse.osgi.baseadaptor.hooks.BundleFileWrapperFactoryHook; +import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook; +import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingStatsHook; +import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader; +import org.eclipse.osgi.baseadaptor.loader.ClasspathEntry; +import org.eclipse.osgi.baseadaptor.loader.ClasspathManager; +import org.eclipse.osgi.framework.adaptor.BundleProtectionDomain; +import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate; +import org.eclipse.osgi.framework.log.FrameworkLog; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; + +public abstract class AbstractAspectJHook implements HookConfigurator, AdaptorHook, BundleFileWrapperFactoryHook , ClassLoadingHook, ClassLoadingStatsHook { + + public static boolean verbose = Boolean.getBoolean("org.aspectj.osgi.verbose"); + + private SupplementerRegistry supplementerRegistry; + + public void addHooks (HookRegistry hooks) { + if (verbose) System.err.println("[org.aspectj.osgi] info adding AspectJ hooks ..."); + + supplementerRegistry = new SupplementerRegistry(); + + hooks.addAdaptorHook(this); + hooks.addClassLoadingHook(this); + hooks.addBundleFileWrapperFactoryHook(this); + hooks.addClassLoadingStatsHook(this); + hooks.addStorageHook(new AspectJStorageHook(supplementerRegistry)); + } + + public SupplementerRegistry getSupplementerRegistry() { + return this.supplementerRegistry; + } + + public BundleFile wrapBundleFile(BundleFile bundleFile, Object content, BaseData data, boolean base) throws IOException { + // TODO Auto-generated method stub + return null; + } + + public boolean addClassPathEntry(ArrayList cpEntries, String cp, ClasspathManager hostmanager, BaseData sourcedata, ProtectionDomain sourcedomain) { + // TODO Auto-generated method stub + return false; + } + + public BaseClassLoader createClassLoader(ClassLoader parent, ClassLoaderDelegate delegate, BundleProtectionDomain domain, BaseData data, String[] bundleclasspath) { + // TODO Auto-generated method stub + return null; + } + + public String findLibrary(BaseData data, String libName) { + // TODO Auto-generated method stub + return null; + } + + public ClassLoader getBundleClassLoaderParent() { + // TODO Auto-generated method stub + return null; + } + + public void initializedClassLoader(BaseClassLoader baseClassLoader, BaseData data) { + // TODO Auto-generated method stub + + } + + public byte[] processClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) { + // TODO Auto-generated method stub + return null; + } + + public void addProperties(Properties properties) { + // TODO Auto-generated method stub + + } + + public FrameworkLog createFrameworkLog() { + // TODO Auto-generated method stub + return null; + } + + public void frameworkStart(BundleContext context) throws BundleException { + // TODO Auto-generated method stub + + } + + public void frameworkStop(BundleContext context) throws BundleException { + // TODO Auto-generated method stub + + } + + public void frameworkStopping(BundleContext context) { + // TODO Auto-generated method stub + + } + + public void handleRuntimeError(Throwable error) { + // TODO Auto-generated method stub + + } + + public void initialize(BaseAdaptor adaptor) { + // TODO Auto-generated method stub + + } + + public URLConnection mapLocationToURLConnection(String location) throws IOException { + // TODO Auto-generated method stub + return null; + } + + public boolean matchDNChain(String pattern, String[] dnChain) { + // TODO Auto-generated method stub + return false; + } + + public void postFindLocalClass(String name, Class clazz, ClasspathManager manager) { + // TODO Auto-generated method stub + + } + + public void postFindLocalResource(String name, URL resource, ClasspathManager manager) { + // TODO Auto-generated method stub + + } + + public void preFindLocalClass(String name, ClasspathManager manager) throws ClassNotFoundException { + // TODO Auto-generated method stub + + } + + public void preFindLocalResource(String name, ClasspathManager manager) { + // TODO Auto-generated method stub + + } + + public void recordClassDefine(String name, Class clazz, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) { + // TODO Auto-generated method stub + + } + +} diff --git a/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/AspectJBundleEntry.java b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/AspectJBundleEntry.java new file mode 100644 index 000000000..96320eee9 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/AspectJBundleEntry.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + * Matthew Webster Eclipse 3.2 changes + * Martin Lippert minor changes and bugfixes + *******************************************************************************/ + +package org.eclipse.equinox.weaving.hooks; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import org.eclipse.equinox.weaving.adaptors.IAspectJAdaptor; +import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry; + +public class AspectJBundleEntry extends BundleEntry { + + private IAspectJAdaptor adaptor; + private String name; + private byte[] bytes; + private URL bundleFileURL; + private BundleEntry delegate; + + public AspectJBundleEntry (IAspectJAdaptor aspectjAdaptor, BundleEntry delegate, URL url) { + this.adaptor = aspectjAdaptor; + this.bundleFileURL = url; + this.delegate = delegate; + } + + public AspectJBundleEntry (IAspectJAdaptor aspectjAdaptor, BundleEntry delegate, String name, byte[] bytes, URL url) { + this(aspectjAdaptor, delegate, url); + this.name = name; + this.bytes = bytes; + } + + public URL getBundleFileURL () { + return bundleFileURL; + } + + public IAspectJAdaptor getAdaptor() { + return adaptor; + } + + public URL getFileURL() { + if (bytes == null) return delegate.getFileURL(); + else return null; + } + + public InputStream getInputStream() throws IOException { + // this always returns the original stream of the delegate to + // allow getResourceAsStream to be used even in the context of + // caching with J9 class sharing + // + // class loading uses getBytes instead (where the caching is considered) + return delegate.getInputStream(); + } + + public byte[] getBytes() throws IOException { + if (bytes == null) return delegate.getBytes(); + return bytes; + } + + public URL getLocalURL() { + if (bytes == null) return delegate.getLocalURL(); + else return null; + } + + public String getName() { + if (bytes == null) return delegate.getName(); + else return name; + } + + public long getSize() { + if (delegate != null) return delegate.getSize(); + else return bytes.length; + } + + public long getTime() { + if (delegate != null) return delegate.getTime(); + else return 0; + } + + public boolean isCached() { + return bytes != null; + } + +} diff --git a/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/AspectJBundleFile.java b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/AspectJBundleFile.java new file mode 100644 index 000000000..78ca3a5a8 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/AspectJBundleFile.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + * Matthew Webster Eclipse 3.2 changes + *******************************************************************************/ + +package org.eclipse.equinox.weaving.hooks; + +import java.io.IOException; +import java.net.URL; + +import org.eclipse.equinox.weaving.adaptors.Debug; +import org.eclipse.equinox.weaving.adaptors.IAspectJAdaptor; +import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry; +import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile; + +public class AspectJBundleFile extends AbstractAJBundleFile { + + private URL url; + + public AspectJBundleFile (IAspectJAdaptor aa, BundleFile bundleFile) throws IOException { + super(aa,bundleFile); + this.url = delegate.getBaseFile().toURL(); + } + + public URL getURL () { + return url; + } + + public BundleEntry getEntry(String path) { + if (Debug.DEBUG_BUNDLE) Debug.println("> AspectJBundleFile.getEntry() path=" + path + ", url=" + url); + BundleEntry entry; + if (path.endsWith(".class")) { + int offset = path.lastIndexOf('.'); + String name = path.substring(0,offset).replace('/','.'); + byte[] bytes = adaptor.findClass(name,url); + if (bytes == null) { + entry = delegate.getEntry(path); + if (entry != null) { + entry = new AspectJBundleEntry(adaptor,entry, url); + if (Debug.DEBUG_BUNDLE) Debug.println("- AspectJBundleFile.getEntry() path=" + path + ", entry=" + entry); + } + } + else entry = new AspectJBundleEntry(adaptor,delegate.getEntry(path), path,bytes, url); + } + else { + entry = delegate.getEntry(path); + } + + if (Debug.DEBUG_BUNDLE) Debug.println("< AspectJBundleFile.getEntry() entry=" + entry); + return entry; + } + +} diff --git a/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/AspectJHook.java b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/AspectJHook.java new file mode 100644 index 000000000..e6f65b3c5 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/AspectJHook.java @@ -0,0 +1,174 @@ +/******************************************************************************* + * Copyright (c) 2006, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + * Matthew Webster Eclipse 3.2 changes + * Martin Lippert supplementing mechanism reworked + *******************************************************************************/ +package org.eclipse.equinox.weaving.hooks; + +import java.io.IOException; +import java.net.URL; + +import org.eclipse.equinox.weaving.adaptors.AspectJAdaptor; +import org.eclipse.equinox.weaving.adaptors.AspectJAdaptorFactory; +import org.eclipse.equinox.weaving.adaptors.Debug; +import org.eclipse.equinox.weaving.adaptors.IAspectJAdaptor; +import org.eclipse.osgi.baseadaptor.BaseData; +import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry; +import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile; +import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader; +import org.eclipse.osgi.baseadaptor.loader.ClasspathEntry; +import org.eclipse.osgi.baseadaptor.loader.ClasspathManager; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; +import org.osgi.framework.ServiceReference; +import org.osgi.service.packageadmin.PackageAdmin; + +public class AspectJHook extends AbstractAspectJHook { + + private BundleContext bundleContext; + private AspectJAdaptorFactory adaptorFactory; + + public AspectJHook () { + if (Debug.DEBUG_GENERAL) Debug.println("- AspectJHook.<init>()"); + adaptorFactory = new AspectJAdaptorFactory(); + } + + private void initialize (BundleContext context) { + if (Debug.DEBUG_GENERAL) Debug.println("> AspectJHook.initialize() context=" + context); + + this.bundleContext = context; + adaptorFactory.initialize(context, getSupplementerRegistry()); + + ServiceReference serviceReference = context.getServiceReference(PackageAdmin.class.getName()); + PackageAdmin packageAdmin = (PackageAdmin) context.getService(serviceReference); + + getSupplementerRegistry().setBundleContext(context); + getSupplementerRegistry().setPackageAdmin(packageAdmin); + context.addBundleListener(new SupplementBundleListener(getSupplementerRegistry())); + + if (Debug.DEBUG_GENERAL) Debug.println("< AspectJHook.initialize() adaptorFactory=" + adaptorFactory); + } + + public void frameworkStart(BundleContext context) throws BundleException { +// Debug.println("? AspectJHook.frameworkStart() context=" + context + ", fdo=" + FrameworkDebugOptions.getDefault()); + initialize(context); + } + + public void recordClassDefine(String name, Class clazz, byte[] classbytes, + ClasspathEntry classpathEntry, BundleEntry entry, + ClasspathManager manager) { + if (entry instanceof AspectJBundleEntry) { + AspectJBundleEntry ajBundleEntry = (AspectJBundleEntry)entry; + IAspectJAdaptor adaptor = ajBundleEntry.getAdaptor(); + URL sourceFileURL = ajBundleEntry.getBundleFileURL(); + adaptor.storeClass(name,sourceFileURL,clazz,classbytes); + } + } + + public void initializedClassLoader(BaseClassLoader baseClassLoader, + BaseData data) { + if (Debug.DEBUG_GENERAL) Debug.println("> AspectJHook.initializedClassLoader() bundle=" + data.getSymbolicName() + ", loader=" + baseClassLoader + ", data=" + data + ", bundleFile=" + data.getBundleFile()); + IAspectJAdaptor adaptor = null; + BundleFile bundleFile = data.getBundleFile(); + if (bundleFile instanceof BaseAjBundleFile) { + BaseAjBundleFile baseBundleFile = (BaseAjBundleFile)bundleFile; + adaptor = baseBundleFile.getAdaptor(); + adaptor.setBaseClassLoader(baseClassLoader); + } + + if (Debug.DEBUG_GENERAL) Debug.println("< AspectJHook.initializedClassLoader() adaptor=" + adaptor); + } + + public byte[] processClass(String name, byte[] classbytes, + ClasspathEntry classpathEntry, BundleEntry entry, + ClasspathManager manager) { + byte[] newClassytes = null; + if (entry instanceof AspectJBundleEntry) { + AspectJBundleEntry ajBundleEntry = (AspectJBundleEntry)entry; + if (!ajBundleEntry.isCached()) { + IAspectJAdaptor adaptor = ajBundleEntry.getAdaptor(); + newClassytes = adaptor.weaveClass(name,classbytes); + } + } + return newClassytes; + } + + public BundleFile wrapBundleFile(BundleFile bundleFile, Object content, + BaseData data, boolean base) throws IOException { + BundleFile wrapped = null; + if (Debug.DEBUG_BUNDLE) Debug.println("> AspectJBundleFileWrapperFactoryHook.wrapBundleFile() bundle=" + data.getSymbolicName() + " bundleFile=" + bundleFile + ", content=" + content + ", data=" + data + ", base=" + base + ", baseFile=" + bundleFile.getBaseFile()); + +// IAspectJAdaptor adaptor = null; +// if (base) { +// adaptor = createAspectJAdaptor(data); +// } +// else if (bundleContext != null) { +// adaptor = getAspectJAdaptor(data); +// } +// +// if (adaptor != null) { +// if (bundleFile instanceof DirBundleFile) { +// wrapped = new BaseAjBundleFile(adaptor,bundleFile); +// } +// else { +// wrapped = new AspectJBundleFile(adaptor,bundleFile); +// } +// } +// if (Debug.DEBUG_BUNDLE) Debug.println("< AspectJBundleFileWrapperFactoryHook.wrapBundleFile() wrapped=" + wrapped + ", adaptor=" + adaptor); + + if (base) { + IAspectJAdaptor adaptor = createAspectJAdaptor(data); + if (adaptor != null) { + wrapped = new BaseAjBundleFile(adaptor, bundleFile); + } + } + else { + IAspectJAdaptor adaptor = null; + if (bundleContext != null) { + adaptor = getAspectJAdaptor(data); + if (Debug.DEBUG_BUNDLE) Debug.println("- AspectJBundleFileWrapperFactoryHook.wrapBundleFile() adaptor=" + adaptor); +// if (adaptor == null) throw new RuntimeException(data.getSymbolicName()); + } + if (adaptor != null) { + wrapped = new AspectJBundleFile(adaptor,bundleFile); + } + } + if (Debug.DEBUG_BUNDLE) Debug.println("< AspectJBundleFileWrapperFactoryHook.wrapBundleFile() wrapped=" + wrapped); + return wrapped; + } + + private IAspectJAdaptor createAspectJAdaptor (BaseData baseData) { + if (Debug.DEBUG_GENERAL) Debug.println("> AspectJHook.createAspectJAdaptor() location=" + baseData.getLocation()); + IAspectJAdaptor adaptor = null; + + if (adaptorFactory != null) { + adaptor = new AspectJAdaptor(baseData,adaptorFactory,null,null,null); + } + else { + if (Debug.DEBUG_GENERAL) Debug.println("- AspectJHook.createAspectJAdaptor() factory=" + adaptorFactory); + } + + if (Debug.DEBUG_GENERAL) Debug.println("< AspectJHook.createAspectJAdaptor() adaptor=" + adaptor); + return adaptor; + } + + private IAspectJAdaptor getAspectJAdaptor (BaseData data) { + IAspectJAdaptor adaptor = null; + + BundleFile bundleFile = data.getBundleFile(); + if (bundleFile instanceof BaseAjBundleFile) { + BaseAjBundleFile baseBundleFile = (BaseAjBundleFile)bundleFile; + adaptor = baseBundleFile.getAdaptor(); + } + + return adaptor; + } + +} diff --git a/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/AspectJStorageHook.java b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/AspectJStorageHook.java new file mode 100644 index 000000000..3e59880f4 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/AspectJStorageHook.java @@ -0,0 +1,220 @@ +/******************************************************************************* + * Copyright (c) 2006, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Matthew Webster initial implementation + * Martin Lippert supplementing mechanism reworked + *******************************************************************************/ + +package org.eclipse.equinox.weaving.hooks; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.Dictionary; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.runtime.internal.adaptor.CachedManifest; +import org.eclipse.equinox.service.weaving.SupplementerRegistry; +import org.eclipse.equinox.weaving.adaptors.Debug; +import org.eclipse.osgi.baseadaptor.BaseData; +import org.eclipse.osgi.baseadaptor.hooks.StorageHook; +import org.eclipse.osgi.framework.util.Headers; +import org.eclipse.osgi.framework.util.KeyedElement; +import org.eclipse.osgi.util.ManifestElement; +import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; + +public class AspectJStorageHook implements StorageHook { + + public static final String KEY = AspectJStorageHook.class.getName(); + public static final int HASHCODE = KEY.hashCode(); + + private BaseData bundleData; + private final SupplementerRegistry supplementerRegistry; + + + public AspectJStorageHook(SupplementerRegistry supplementerRegistry) { + if (Debug.DEBUG_SUPPLEMENTS) Debug.println("- AspectJStorageHook.AspectJStorageHook()"); + this.supplementerRegistry = supplementerRegistry; + } + + public AspectJStorageHook(BaseData bd, SupplementerRegistry supplementerRegistry) { + if (Debug.DEBUG_SUPPLEMENTS) Debug.println("- AspectJStorageHook.AspectJStorageHook() baseDate=" + bd); + this.bundleData = bd; + this.supplementerRegistry = supplementerRegistry; + } + + private String getSymbolicName () { + return (bundleData == null)? "root" : bundleData.getSymbolicName(); + } + + public void copy(StorageHook storageHook) { + // TODO Auto-generated method stub + } + + public StorageHook create(BaseData bundledata) throws BundleException { +// System.err.println("? AbstractAspectJHook.create()"); + // TODO Auto-generated method stub +// StorageHook result; + final StorageHook hook = new AspectJStorageHook(bundledata, supplementerRegistry); +//// if (bundledata.getSymbolicName().equals("demo.hello")) { +// InvocationHandler ih = new InvocationHandler() { +// public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args) throws Throwable { +// System.err.println("? " + method.getName()); +// return method.invoke(hook,args); +// } +// }; +// result = (StorageHook)Proxy.newProxyInstance(getClass().getClassLoader(),new Class[] { StorageHook.class }, ih); +//// } +//// else { +//// result = hook; +//// } +// return result; + return hook; + } + + public boolean forgetStartLevelChange(int startlevel) { + // TODO Auto-generated method stub + return false; + } + + public boolean forgetStatusChange(int status) { + // TODO Auto-generated method stub + return false; + } + + public Dictionary getManifest(boolean firstLoad) throws BundleException { +// System.err.println("? AspectJStorageHook.getManifest() " + this + " firstLoad=" + firstLoad); + // TODO Auto-generated method stub + return null; + } + + public int getStorageVersion() { + // TODO Auto-generated method stub + return 0; + } + + public void initialize(Dictionary manifest) throws BundleException { +// System.err.println("? AspectJStorageHook.initialize() " + this + " manifest=" + manifest); + if (Debug.DEBUG_SUPPLEMENTS) Debug.println("> AspectJStorageHook.initialize() " + getSymbolicName()); + try { + ManifestElement[] imports = ManifestElement.parseHeader(Constants.IMPORT_PACKAGE, (String) manifest.get(Constants.IMPORT_PACKAGE)); + ManifestElement[] exports = ManifestElement.parseHeader(Constants.EXPORT_PACKAGE, (String) manifest.get(Constants.EXPORT_PACKAGE)); + List supplementers = supplementerRegistry.getSupplementers(bundleData.getSymbolicName(), imports, exports); + if (!supplementers.isEmpty()) { + if (Debug.DEBUG_SUPPLEMENTS) Debug.println("- AspectJStorageHook.initialize() " + getSymbolicName() + " supplementers=" + supplementers); + if (!getSymbolicName().equals("org.eclipse.osgi") +// && !getSymbolicName().startsWith("org.eclipse.core") +// && !getSymbolicName().startsWith("org.eclipse.equinox") + && !getSymbolicName().startsWith("org.eclipse.team.ui") + && !getSymbolicName().startsWith("org.eclipse.update") + ) { + if (addRequiredBundles(supplementers)) { + if (AbstractAspectJHook.verbose) System.err.println("[org.aspectj.osgi] info supplementing " + getSymbolicName() + " with " + supplementers); + } + else { + if (AbstractAspectJHook.verbose) System.err.println("[org.aspectj.osgi] info not supplementing " + getSymbolicName()); + } + } + else { + if (AbstractAspectJHook.verbose) System.err.println("[org.aspectj.osgi] info cannot supplement " + getSymbolicName()); + } + } + } + catch (Exception ex) { + ex.printStackTrace(); + } + if (Debug.DEBUG_SUPPLEMENTS) Debug.println("< AspectJStorageHook.initialize() "); + } + + private boolean addRequiredBundles (List bundles) throws BundleException { + Dictionary manifest = bundleData.getManifest(); + manifest = ((CachedManifest)manifest).getManifest(); + + if (manifest != null) { + String value = (String)manifest.get(Constants.REQUIRE_BUNDLE); + for (Iterator i = bundles.iterator(); i.hasNext();) { + String name = (String)i.next(); + if (value == null) value = name; + else value += "," + name; + } + + if (Debug.DEBUG_SUPPLEMENTS) Debug.println("- AspectJStorageHook.addRequiredBundles() " + bundleData.getSymbolicName() + " ,manifest=" + manifest.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(manifest)) + ", value=" + value); + setHeader((Headers)manifest,Constants.REQUIRE_BUNDLE,value,true); + } + + return true; + } + + private Object setHeader(Headers manifest, Object key, Object value, boolean replace) throws BundleException { + try { + /* In Eclipse 3.3 we must use reflection to allow the manifest to be modified */ + if (readOnly != null) { + readOnly.set(manifest,new Boolean(false)); + } + + return manifest.set(Constants.REQUIRE_BUNDLE,value,true); + } + catch (IllegalAccessException ex) { + throw new BundleException(key + "=" + value,ex); + } + } + + private static Field readOnly; + + static { + try { + readOnly = Headers.class.getDeclaredField("readOnly"); + readOnly.setAccessible(true); + } + catch (Exception ex) { + if (Debug.DEBUG_SUPPLEMENTS) ex.printStackTrace(); + } + } + + public StorageHook load(BaseData bundledata, DataInputStream is) throws IOException { + if (Debug.DEBUG_SUPPLEMENTS) Debug.println("- AspectJStorageHook.load() " + getSymbolicName() + " bundleData=" + bundledata); + return new AspectJStorageHook(bundledata, supplementerRegistry); + } + + public boolean matchDNChain(String pattern) { + // TODO Auto-generated method stub +// System.err.println("? AspectJStorageHook.matchDNChain() " + getSymbolicName() + " pattern=" + pattern); + return false; + } + + public void save(DataOutputStream os) throws IOException { + // TODO Auto-generated method stub + if (Debug.DEBUG_SUPPLEMENTS) Debug.println("- AspectJStorageHook.save() " + getSymbolicName()); + } + + public void validate() throws IllegalArgumentException { + // TODO Auto-generated method stub +// System.err.println("? AspectJStorageHook.validate()"); + } + + public boolean compare(KeyedElement other) { + // TODO Auto-generated method stub + return other.getKey() == KEY; + } + + public Object getKey() { + return KEY; + } + + public int getKeyHashCode() { + return HASHCODE; + } + + public String toString () { + return "AspectJStorageHook[" + getSymbolicName() + "]"; + } + +} diff --git a/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/BaseAjBundleFile.java b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/BaseAjBundleFile.java new file mode 100644 index 000000000..df674d8aa --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/BaseAjBundleFile.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + * Matthew Webster Eclipse 3.2 changes + *******************************************************************************/ + +package org.eclipse.equinox.weaving.hooks; + +import java.io.IOException; + +import org.eclipse.equinox.weaving.adaptors.IAspectJAdaptor; +import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile; + +public class BaseAjBundleFile extends AspectJBundleFile { + + public BaseAjBundleFile (IAspectJAdaptor aspectjAdaptor, BundleFile bundleFile) throws IOException { + super(aspectjAdaptor,bundleFile); + } +} diff --git a/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/SupplementBundleListener.java b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/SupplementBundleListener.java new file mode 100644 index 000000000..a5ed6a481 --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/SupplementBundleListener.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2008 Martin Lippert and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Martin Lippert initial implementation + *******************************************************************************/ + +package org.eclipse.equinox.weaving.hooks; + +import org.eclipse.equinox.service.weaving.SupplementerRegistry; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleEvent; +import org.osgi.framework.SynchronousBundleListener; + +public class SupplementBundleListener implements SynchronousBundleListener { + + private final SupplementerRegistry supplementerRegistry; + + public SupplementBundleListener(SupplementerRegistry supplementerRegistry) { + this.supplementerRegistry = supplementerRegistry; + } + + public void bundleChanged(BundleEvent event) { + Bundle bundle = event.getBundle(); + if (event.getType() == BundleEvent.INSTALLED) { + supplementerRegistry.addSupplementer(bundle); + } + else if (event.getType() == BundleEvent.UNINSTALLED) { + supplementerRegistry.removeSupplementer(bundle); + } + else if (event.getType() == BundleEvent.UPDATED) { + supplementerRegistry.removeSupplementer(bundle); + supplementerRegistry.addSupplementer(bundle); + } + } + +} diff --git a/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/Supplementer.java b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/Supplementer.java new file mode 100644 index 000000000..005d88b1a --- /dev/null +++ b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/weaving/hooks/Supplementer.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2008 Martin Lippert and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + * Martin Lippert supplementing mechanism reworked + *******************************************************************************/ + +package org.eclipse.equinox.weaving.hooks; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.osgi.util.ManifestElement; +import org.osgi.framework.Bundle; + +public class Supplementer { + + private ManifestElement[] supplementBundle; + private ManifestElement[] supplementImporter; + private ManifestElement[] supplementExporter; + private Bundle supplementer; + private List supplementedBundles; // elements of type Bundle + + public Supplementer(Bundle bundle, + ManifestElement[] supplementBundle, + ManifestElement[] supplementImporter, + ManifestElement[] supplementExporter) { + this.supplementer = bundle; + this.supplementBundle = supplementBundle; + this.supplementImporter = supplementImporter; + this.supplementExporter = supplementExporter; + this.supplementedBundles = new ArrayList(); + } + + public Bundle getSupplementerBundle() { + return supplementer; + } + + public String getSymbolicName() { + return supplementer.getSymbolicName(); + } + + public void addSupplementedBundle(Bundle supplementedBundle) { + this.supplementedBundles.add(supplementedBundle); + } + + public void removeSupplementedBundle(Bundle supplementedBundle) { + this.supplementedBundles.remove(supplementedBundle); + } + + public Bundle[] getSupplementedBundles() { + return (Bundle[]) supplementedBundles.toArray(new Bundle[supplementedBundles.size()]); + } + + public boolean isSupplemented(Bundle bundle) { + return supplementedBundles.contains(bundle); + } + + public boolean matchSupplementer(String symbolicName) { + boolean matches = false; + + if (supplementBundle != null) for (int i = 0; !matches && i < supplementBundle.length; i++) { + ManifestElement bundle = supplementBundle[i]; + if (equals_wild(bundle.getValue(),symbolicName)) matches = true; + } + + return matches; + } + + public boolean matchesSupplementImporter(ManifestElement[] imports) { + boolean matches = false; + + if (supplementImporter != null) for (int i = 0; !matches && i < supplementImporter.length; i++) { + ManifestElement supplementImport = supplementImporter[i]; + for (int j = 0; !matches && j < imports.length; j++) { + ManifestElement importPackage = imports[j]; + if (supplementImport.getValue().equals(importPackage.getValue())) matches = true; + } + } + + return matches; + } + + public boolean matchesSupplementExporter(ManifestElement[] exports) { + boolean matches = false; + + if (supplementExporter != null) for (int i = 0; !matches && i < supplementExporter.length; i++) { + ManifestElement supplementExport = supplementExporter[i]; + for (int j = 0; !matches && j < exports.length; j++) { + ManifestElement exportPackage = exports[j]; + if (supplementExport.getValue().equals(exportPackage.getValue())) matches = true; + } + } + + return matches; + } + + //knibb + //test if two Strings are equal + //with wild card support - only supports strings ending in * + private boolean equals_wild(String input, String match){ + if(input.equals(match)){ + //its a match so just return true + return true; + } + if(input.endsWith("*")==false){ + //no wildcards are being used here + return false; + } + String wild_in = input.substring(0, input.length()-1); + if(match.startsWith(wild_in)) + return true; + + return false; + } + +} |