initial commit in accordance with CQ 3784
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/.classpath b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/.classpath
new file mode 100644
index 0000000..987380a
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/.classpath
@@ -0,0 +1,8 @@
+<?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="con" path="OTRE"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/.project b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/.project
new file mode 100644
index 0000000..12e57b3
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/.project
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.objectteams.otdt.compiler.adaptor</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.objectteams.otdt.builder.OTJBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.objectteams.otdt.OTJavaNature</nature>
+ </natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..3b91683
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,85 @@
+#Sun Nov 09 02:20:07 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.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=disabled
+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=ignore
+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=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+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=warning
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+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=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=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=warning
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+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.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.5
+org.objectteams.otdt.compiler.option.joinpoint_queries=disabled
+org.objectteams.otdt.compiler.option.scoped_keywords=enabled
+org.objectteams.otdt.compiler.problem.abstract_potential_relevant_role=warning
+org.objectteams.otdt.compiler.problem.basecall=warning
+org.objectteams.otdt.compiler.problem.binding_conventions=error
+org.objectteams.otdt.compiler.problem.decapsulation=warning
+org.objectteams.otdt.compiler.problem.deprecated_path_syntax=warning
+org.objectteams.otdt.compiler.problem.effectless_fieldaccess=warning
+org.objectteams.otdt.compiler.problem.fragile_callin=warning
+org.objectteams.otdt.compiler.problem.incomplete_build=error
+org.objectteams.otdt.compiler.problem.inferred_callout=error
+org.objectteams.otdt.compiler.problem.potential_ambiguous_playedby=warning
+org.objectteams.otdt.compiler.problem.unsafe_liftctor=warning
+org.objectteams.otdt.compiler.problem.unsafe_role_instantiation=warning
+org.objectteams.otdt.compiler.problem.unused_parammap=warning
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..b43819b
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/META-INF/MANIFEST.MF
@@ -0,0 +1,16 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: OT/J Compiler Adaptor Plug-in
+Bundle-SymbolicName: org.eclipse.objectteams.otdt.compiler.adaptor;singleton:=true
+Bundle-Version: 1.4.0.qualifier
+Bundle-Vendor: objectteams.org
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.jdt.core;bundle-version="[3.4.2.vOTDT_r124,4.0.0)",
+ org.eclipse.objectteams.otequinox,
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ org.eclipse.pde.core,
+ org.eclipse.objectteams.otdt
+Export-Package: org.eclipse.objectteams.otdt.internal.compiler.adaptor
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Bundle-ActivationPolicy: lazy
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/build.properties b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/build.properties
new file mode 100644
index 0000000..e9863e2
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/plugin.xml b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/plugin.xml
new file mode 100644
index 0000000..36e2732
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/plugin.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+ <extension
+ point="org.eclipse.objectteams.otequinox.aspectBindings">
+ <aspectBinding
+ icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/calloutbinding_obj.gif">
+ <basePlugin
+ icon="platform:/plugin/org.eclipse.pde.ui/icons/obj16/plugin_obj.gif"
+ id="org.eclipse.jdt.core"/>
+ <team
+ activation="ALL_THREADS"
+ class="org.eclipse.objectteams.otdt.internal.compiler.adaptor.AdaptorActivator"
+ icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/team_obj.gif"/>
+ <team
+ activation="NONE"
+ class="org.eclipse.objectteams.otdt.internal.compiler.adaptor.BuildManager"
+ icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/team_obj.gif"
+ superclass="org.eclipse.objectteams.otdt.internal.compiler.adaptor.CompilationThreadWatcher"/>
+ <team
+ activation="NONE"
+ class="org.eclipse.objectteams.otdt.internal.compiler.adaptor.CompilationThreadWatcher"
+ icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/team_obj.gif"/>
+ <team
+ activation="NONE"
+ class="org.eclipse.objectteams.otdt.internal.compiler.adaptor.BaseImportChecker"
+ icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/team_obj.gif"
+ superclass="org.eclipse.objectteams.otdt.internal.compiler.adaptor.CompilationThreadWatcher"/>
+ <team
+ activation="NONE"
+ class="org.eclipse.objectteams.otdt.internal.compiler.adaptor.RoleReuseGuard"
+ icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/team_obj.gif">
+ </team>
+ <team
+ activation="NONE"
+ class="org.eclipse.objectteams.otdt.internal.compiler.adaptor.PlainProjectWatcher"
+ icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/team_obj.gif"
+ superclass="org.eclipse.objectteams.otdt.internal.compiler.adaptor.CompilationThreadWatcher">
+ </team>
+ </aspectBinding>
+ <aspectBinding
+ icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/calloutbinding_obj.gif">
+ <basePlugin
+ icon="platform:/plugin/org.eclipse.pde.ui/icons/obj16/plugin_obj.gif"
+ id="org.eclipse.pde.core">
+ </basePlugin>
+ <team
+ activation="ALL_THREADS"
+ class="org.eclipse.objectteams.otdt.internal.compiler.adaptor.PDEAdaptor"
+ icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/team_obj.gif">
+ </team>
+ </aspectBinding>
+ <aspectBinding
+ icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/calloutbinding_obj.gif">
+ <basePlugin
+ icon="platform:/plugin/org.eclipse.pde.ui/icons/obj16/plugin_obj.gif"
+ id="org.eclipse.core.resources">
+ </basePlugin>
+ <team
+ activation="ALL_THREADS"
+ class="org.eclipse.objectteams.otdt.internal.compiler.adaptor.ResourceProjectAdaptor"
+ icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/team_obj.gif">
+ </team>
+ </aspectBinding>
+ </extension>
+
+</plugin>
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/AdaptedBaseBundle.java b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/AdaptedBaseBundle.java
new file mode 100644
index 0000000..fa33586
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/AdaptedBaseBundle.java
@@ -0,0 +1,115 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2007 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * 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
+ * $Id: AdaptedBaseBundle.java 23451 2010-02-04 20:33:32Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otdt.internal.compiler.adaptor;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Objects of this class encode the information about aspectBindings
+ * affecting a given type/package within a base bundle.
+ *
+ * @author stephan
+ * @since 1.1.5
+ */
+public class AdaptedBaseBundle
+{
+ // the Object-value is used as a time stamp for reloading after the reader has been reloaded:
+ private HashMap<AspectBindingReader,Object> readers= new HashMap<AspectBindingReader, Object>();
+
+
+ /** Symbolic name of this base bundle. */
+ String symbolicName;
+ /** Teams adapting this base bundle. */
+ Set<String> adaptingTeams;
+
+ /** Does this aspect bundle have one or more split packages? */
+ public boolean hasPackageSplit = false;
+
+ public AdaptedBaseBundle(String symbolicName,
+ AspectBindingReader reader)
+ {
+ this.symbolicName = symbolicName;
+ this.adaptingTeams= reader.getTeamsForBase(symbolicName);
+ this.readers.put(reader, reader.token);
+ }
+ public boolean isAdaptedBy(String teamName) {
+ checkReload();
+ for (String aTeam : adaptingTeams)
+ if (aTeam.equals(teamName))
+ return true;
+ return false;
+ }
+
+ public String getSymbolicName() {
+ return this.symbolicName;
+ }
+
+ public synchronized boolean merge(AdaptedBaseBundle otherData) {
+ if (this.symbolicName.equals(otherData.symbolicName)) {
+ this.adaptingTeams.addAll(otherData.adaptingTeams);
+ this.readers.putAll(otherData.readers);
+ return true;
+ } else {
+ // different base bundle but same package: split package
+ return false;
+ }
+ }
+
+ /** Check whether the AspectBindingReader has been reloaded, and if so,
+ * also reload our data (adaptingTeams) from the reader. */
+ private void checkReload() {
+ synchronized (this.readers) {
+ boolean reloadNeeded= false;
+ for (Map.Entry<AspectBindingReader,Object> readerEntry : this.readers.entrySet()) {
+ AspectBindingReader reader= readerEntry.getKey();
+ if (readerEntry.getValue() != reader.token) {
+ // token changed means: reader has reloaded.
+ reloadNeeded= true;
+ this.readers.put(reader, reader.token);
+ }
+ }
+ if (!reloadNeeded)
+ return;
+ // perform the reload:
+ HashSet<String> newSet= new HashSet<String>();
+ for (AspectBindingReader reader: this.readers.keySet())
+ newSet.addAll(reader.getTeamsForBase(this.symbolicName));
+ this.adaptingTeams= newSet; // only now assign, because querying the readers might call back into this!
+ }
+ }
+
+ @SuppressWarnings("nls")
+ @Override
+ public String toString() {
+ String result= "bundle "+this.symbolicName+" is adapted by";
+ if (this.adaptingTeams == null)
+ return result+" (null)";
+ if (this.adaptingTeams.isEmpty())
+ return result+" no teams";
+ for (String aTeam : this.adaptingTeams) {
+ result+= "\n\t"+aTeam;
+ }
+ return result;
+ }
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/AdaptorActivator.java b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/AdaptorActivator.java
new file mode 100644
index 0000000..59e30c1
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/AdaptorActivator.java
@@ -0,0 +1,371 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2007 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * 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
+ * $Id: AdaptorActivator.java 23451 2010-02-04 20:33:32Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otdt.internal.compiler.adaptor;
+
+import static org.eclipse.core.resources.IncrementalProjectBuilder.FULL_BUILD;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import org.eclipse.core.internal.resources.Project;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.IAccessRule;
+import org.eclipse.jdt.core.IClasspathAttribute;
+import org.eclipse.jdt.core.IClasspathContainer;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.WorkingCopyOwner;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.SourceElementParser;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.util.ObjectVector;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
+import org.eclipse.jdt.internal.core.ClasspathAccessRule;
+import org.eclipse.jdt.internal.core.CompilationUnit;
+import org.eclipse.pde.internal.core.RequiredPluginsClasspathContainer;
+import org.objectteams.LiftingVetoException;
+import org.objectteams.Team;
+import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
+import org.eclipse.objectteams.otdt.core.compiler.OTNameUtils;
+
+import base org.eclipse.jdt.core.JavaCore;
+import base org.eclipse.jdt.internal.core.CompilationUnitProblemFinder;
+import base org.eclipse.jdt.internal.core.JavaProject;
+import base org.eclipse.jdt.internal.core.builder.IncrementalImageBuilder;
+import base org.eclipse.jdt.internal.core.builder.JavaBuilder;
+import base org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.copyinheritance.CopyInheritance;
+
+/**
+ * This team is activated via the OT/Equinox transformer plugin.
+ * It controls the activation of the BuildManager and BaseImportChecker teams.
+ *
+ * Control entry for BuildManager: IncrementalImageBuilder.
+ * Control entries for BaseImportChecker: JavaBuilder and CompilationUnitProblemFinder
+ * @author stephan
+ */
+@SuppressWarnings("restriction")
+public team class AdaptorActivator
+{
+ /**
+ * Name of classpath attributes denoting the base bundle from which a classpath entry originates.
+ * Persistently stored so we can later associate aspect binding data to that classpath entry.
+ */
+ public static final String CPENTRY_ATTR_ORIGIN_BASE_BUNDLE = "org.eclipse.objectteams.originBaseBundle"; //$NON-NLS-1$
+
+ /**
+ * Copy of a constant from PDECore to reduce dependencies (must be compared with .equals())).
+ */
+ public static final IPath REQUIRED_PLUGINS_CONTAINER_PATH = new Path("org.eclipse.pde.core.requiredPlugins"); //$NON-NLS-1$
+
+
+ public static AdaptorActivator instance;
+ public AdaptorActivator() {
+ instance= this;
+ }
+
+ /**
+ * Pass the AspectBindingReader from a JavaProject to its RequiredPluginsClasspathContainer,
+ * and pass aspect binding data from the reader to individual classpath entries having a
+ * originBaseBundle attribute.
+ */
+ @SuppressWarnings("decapsulation") // base class is final
+ protected class JavaCore playedBy JavaCore
+ {
+ IClasspathAttribute newClasspathAttribute(String name, String value) -> IClasspathAttribute newClasspathAttribute(String name, String value);
+
+// (see TODO above) Attention:
+// this solution would require partial array lifting if an element throws LiftingVetoException:
+// void setClasspathContainer(OTEquinoxProject[] javaProjects, IClasspathContainer[] container)
+ void setClasspathContainer(IJavaProject[] javaProjects, IClasspathContainer[] containers)
+ <- before void setClasspathContainer(IPath container, IJavaProject[] affectedProjects, IClasspathContainer[] respectiveContainers, IProgressMonitor pm)
+ with { javaProjects <- affectedProjects,
+ containers <- respectiveContainers
+ }
+// static void setClasspathContainer(OTEquinoxProject[] javaProject, IClasspathContainer[] container)
+ static void setClasspathContainer(IJavaProject[] javaProjects, IClasspathContainer[] containers)
+ {
+ try {
+ for (int i=0; i<javaProjects.length; i++) {
+ Project project= (Project)javaProjects[i].getProject();
+ if ( containers[i] != null
+ && REQUIRED_PLUGINS_CONTAINER_PATH.equals(containers[i].getPath())
+ && ProjectUtil.isOTPluginProject(project)) // avoid LiftingVetoException
+ {
+ AspectBindingReader aspectBindingReader = ResourceProjectAdaptor.getDefault().getAspectBindingReader(project);
+ if (PDEAdaptor.instance != null)
+ //otherwise PDEAdaptor has not been activated yet (PDE neither) hoping this can be ignored.
+ PDEAdaptor.instance.setAspectBindingReader(aspectBindingReader, (RequiredPluginsClasspathContainer)containers[i]);
+ else
+ org.eclipse.jdt.core.JavaCore.getJavaCore().getLog().log(new Status(Status.WARNING, "org.eclipse.objectteams.otdt.internal.compiler.adaptor", //$NON-NLS-1$
+ "PDEAdaptor not yet initialized while setting classpath for "+project.getName())); //$NON-NLS-1$
+ }
+ }
+ } catch (LiftingVetoException lve) {
+ // ignore, aspect just didn't apply
+ } catch (Throwable t) {
+ org.eclipse.jdt.core.JavaCore.getJavaCore().getLog().log(new Status(Status.ERROR, "org.eclipse.objectteams.otdt.internal.compiler.adaptor", "Error initializing AspectBindingReader", t)); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ void addBaseBundleAttribute(IAccessRule[] accessRules, IClasspathAttribute[] extraAttributes)
+ <- replace IClasspathEntry newLibraryEntry(IPath path1, IPath path2, IPath path3, IAccessRule[] accessRules, IClasspathAttribute[] extraAttributes, boolean isExported)
+ when (accessRules != null && accessRules.length > 0)
+ with { accessRules <- accessRules, extraAttributes <- extraAttributes }
+
+ void addBaseBundleAttribute(IAccessRule[] accessRules, IClasspathAttribute[] extraAttributes)
+ <- replace IClasspathEntry newProjectEntry(IPath path, IAccessRule[] accessRules, boolean combineAccessRules, IClasspathAttribute[] extraAttributes, boolean isExported)
+ when (accessRules != null && accessRules.length > 0)
+ with { accessRules <- accessRules, extraAttributes <- extraAttributes }
+
+ /**
+ * when creating a new classpath entry for a require plugin, check whether this plugin is affected by aspect bindings.
+ * If so, add a classpath attribute to denote the base plugin from which this entry originates.
+ * If a package is split among several plugins, a rule may carry one aspectBindingData for each part of the split.
+ */
+ static callin void addBaseBundleAttribute(IAccessRule[] accessRules, IClasspathAttribute[] extraAttributes) {
+ if (accessRules[0] instanceof ClasspathAccessRule) {
+ Object[] datas = ((ClasspathAccessRule)accessRules[0]).aspectBindingData;
+ int i = 0;
+ if (datas != null)
+ for (Object data : datas)
+ if (data instanceof AdaptedBaseBundle) {
+ // note: more than one data is rather infrequent, no need to optimize array copying
+ int len = extraAttributes.length;
+ System.arraycopy(extraAttributes, 0, extraAttributes=new IClasspathAttribute[len+1], 1, len);
+ String baseBundleName = ((AdaptedBaseBundle) data).getSymbolicName();
+ extraAttributes[0] = newClasspathAttribute(CPENTRY_ATTR_ORIGIN_BASE_BUNDLE+(i++), baseBundleName);
+ }
+ }
+ base.addBaseBundleAttribute(accessRules, extraAttributes);
+ }
+ }
+
+ /**
+ * When a JavaProject computes its package fragment roots from its classpath entries,
+ * enhance the classpath entries with aspect binding data, using the classpath attribute
+ * to determine the corresponding base bundle.
+ *
+ * @author stephan
+ * @since 1.2.5
+ */
+ protected class CPEntryEnhancer playedBy JavaProject {
+
+ IProject getProject() -> IProject getProject();
+
+ @SuppressWarnings("rawtypes")
+ void enhanceCPEntry(IClasspathEntry[] resolvedEntries)
+ <- before void computePackageFragmentRoots(IClasspathEntry[] resolvedEntries, ObjectVector accumulatedRoots,
+ HashSet rootIDs, IClasspathEntry referringEntry,
+ boolean retrieveExportedRoots, Map rootToResolvedEntries);
+
+ /**
+ * @param entry the entry to enhance
+ * @throws LiftingVetoException when the project is not an OT/Equinox project.
+ */
+ void enhanceCPEntry(IClasspathEntry[] entries) throws LiftingVetoException
+ {
+ IProject project = getProject();
+ AspectBindingReader reader = ResourceProjectAdaptor.getDefault().getAspectBindingReader((Project)project);
+ for (IClasspathEntry entry : entries) {
+ IClasspathAttribute[] attributes = entry.getExtraAttributes();
+ attributes_loop:
+ for (IClasspathAttribute attribute : attributes) {
+ if (attribute.getName().startsWith(CPENTRY_ATTR_ORIGIN_BASE_BUNDLE)) {
+ AdaptedBaseBundle aspectBindingData = reader.getAdaptationInfo(attribute.getValue());
+ if (aspectBindingData == null) continue; // means reader and attr are inconsistent
+ rules_loop:
+ for (IAccessRule rule : entry.getAccessRules())
+ if (rule instanceof ClasspathAccessRule)
+ if (!PDEAdaptor.addAspectBindingData((ClasspathAccessRule)rule, aspectBindingData))
+ break rules_loop; // when not adding assume all rules share the same aspect data
+ break attributes_loop;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Interface to the controlling builder. Tasks:
+ * <ul>
+ * <li>Life-cycle management for the BuildManager</li>
+ * <li>cflow like bracket [initializeBuilder,cleanup]
+ * for temporary activation of BaseImportChecker.
+ * Note, that build() is not a suitable join point,
+ * because javaProject is not yes assigned.</li>
+ * </ul>
+ */
+ protected class JavaBuilderObserver playedBy JavaBuilder
+ {
+ @SuppressWarnings("decapsulation")
+ Project getProject() -> get JavaProject javaProject
+ with { result <- (Project)javaProject.getProject() }
+
+ Team projectWatcher= null;
+
+ // initialize local data structures when a full build is started:
+ void initialize(int kind) <- after int initializeBuilder(int kind, boolean forBuild);
+ void initialize(int kind) {
+ if (kind == FULL_BUILD)
+ manager.initializeDependencyStorage();
+ try {
+ this.projectWatcher= ResourceProjectAdaptor.getDefault().getChecker(getProject());
+ } catch (LiftingVetoException lve) {
+ this.projectWatcher= new PlainProjectWatcher();
+ }
+ this.projectWatcher.activate();
+ }
+
+ cleanup <- after cleanup;
+ void cleanup() {
+ if (this.projectWatcher != null)
+ this.projectWatcher.deactivate();
+ this.projectWatcher= null;
+ }
+
+ // need to recompute the classpath if aspect binding data have changed:
+ @SuppressWarnings("decapsulation")
+ boolean aspectBindingHasChanged() <- replace boolean hasClasspathChanged();
+ @SuppressWarnings("basecall")
+ callin boolean aspectBindingHasChanged() {
+ try {
+ if (ResourceProjectAdaptor.getDefault().hasAspectDataChanged(getProject()))
+ return true;
+ } catch (LiftingVetoException lve) {
+ // thrown while lifting project, means that javaProject is not OT-Project.
+ }
+ return base.aspectBindingHasChanged();
+ }
+
+ }
+
+ /**
+ * This role observes another entry into the compiler to activate a BaseImportChecker if needed.
+ */
+ protected class CompilationUnitProblemFinder playedBy CompilationUnitProblemFinder
+ {
+ @SuppressWarnings("rawtypes")
+ void activateChecker(ICompilationUnit unitElement)
+ <- replace CompilationUnitDeclaration process(CompilationUnit unitElement,
+ SourceElementParser parser,
+ WorkingCopyOwner workingCopyOwner,
+ HashMap problems,
+ boolean creatingAST,
+ int reconcileFlags,
+ IProgressMonitor monitor)
+ with { unitElement <- unitElement }
+
+ static callin void activateChecker(ICompilationUnit unitElement)
+ throws JavaModelException
+ {
+ within (getChecker(unitElement))
+ base.activateChecker(unitElement);
+ }
+
+ static Team getChecker(ICompilationUnit unitElement) {
+ try {
+ Project project= ProjectUtil.safeGetOTPluginProject(unitElement);
+ if (project != null) {
+ Team baseChecker= ResourceProjectAdaptor.getDefault().getChecker(project);
+ if (baseChecker != null)
+ return baseChecker;
+ }
+ } catch (LiftingVetoException lve) {
+ // shouldn't happen, have checked above.
+ }
+ return new PlainProjectWatcher(); // fallback for non OT-Plugin projects
+ }
+ }
+
+ private BuildManager manager = new BuildManager();
+
+ /**
+ * This role observes the IncrementalImageBuilder.
+ * It enables all callins of BuildManager only while
+ * performing an incremental build (method build(deltas)).
+ */
+ protected class BuilderGuard playedBy IncrementalImageBuilder
+ {
+ build <- replace build;
+ callin boolean build(SimpleLookupTable deltas)
+ {
+ // Activation only for this thread/control flow:
+ within (manager) {
+ return base.build(deltas);
+ }
+ }
+ }
+
+ /**
+ * This role class simply tracks all executions of CopyInheritance.copyRole(..)
+ *
+ * Purpose: collect data for recompiling sub-teams if tsuper roles have been changed.
+ */
+ protected class CopyInheritanceObserver playedBy CopyInheritance
+ {
+ // This trigger applies to source and binary tsupers being copied into source:
+ void observeCopyRole(ReferenceBinding superRole, char[] subTeamFileName)
+ <- after TypeDeclaration copyRole(ReferenceBinding tsuperRole,
+ boolean isNestedType,
+ TypeDeclaration subTeamDecl,
+ boolean isTsuperTeam)
+ base when (result != null)
+ with { superRole <- tsuperRole,
+ subTeamFileName <- subTeamDecl.compilationResult.getFileName() }
+
+ // static for optimization: avoid lifting.
+ static void observeCopyRole(ReferenceBinding superRole, char[] subTeamFileName)
+ {
+ if (superRole.enclosingType().id == IOTConstants.T_OrgObjectTeamsTeam)
+ return;
+ if (subTeamFileName == null || subTeamFileName[0] != '/')
+ return; // only useful if an absolute path is given.
+
+ // no need to recompile these:
+ char[] superRoleName = superRole.internalName();
+ if ( BuildManager.isPredefinedRole(superRoleName)
+ || OTNameUtils.isTSuperMarkerInterface(superRoleName))
+ return;
+ AdaptorActivator.this.manager.recordCopiedRole(superRole.attributeName(), subTeamFileName);
+ }
+
+ @SuppressWarnings("decapsulation")
+ boolean shouldPreserveBinary(ReferenceBinding role, CompilationResult cResult)
+ <-replace boolean shouldPreserveBinaryRole(ReferenceBinding role, CompilationResult cResult);
+ static callin boolean shouldPreserveBinary(ReferenceBinding role, CompilationResult cResult)
+ {
+ if (!base.shouldPreserveBinary(role, cResult))
+ return false;
+ if (!AdaptorActivator.this.manager.isActive())
+ return true;
+ return AdaptorActivator.this.manager.shouldPreserveBinaryRole(role, cResult);
+ }
+ }
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/AspectBindingReader.java b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/AspectBindingReader.java
new file mode 100644
index 0000000..bae44d0
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/AspectBindingReader.java
@@ -0,0 +1,364 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2007 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * 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
+ * $Id: AspectBindingReader.java 23451 2010-02-04 20:33:32Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otdt.internal.compiler.adaptor;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.IClasspathContainer;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.objectteams.otdt.core.ext.OTDTPlugin;
+import org.eclipse.pde.core.build.IBuild;
+import org.eclipse.pde.core.plugin.IPluginModelBase;
+import org.eclipse.pde.internal.core.ClasspathUtilCore;
+import org.eclipse.pde.internal.core.PDECore;
+import org.eclipse.pde.internal.core.PluginModelManager;
+import org.eclipse.pde.internal.core.RequiredPluginsClasspathContainer;
+import org.objectteams.LiftingVetoException;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * Utility to read the aspectBinding extension from a projects plugin.xml,
+ * in order to provide this information during compilation.
+ *
+ * References to an AspectBindingReader are passed along the full information flow
+ * from PDEAdaptor to BaseImportChecker as a source for fetching aspect binding information.
+ *
+ * @author stephan
+ * @since 1.1.5
+ */
+@SuppressWarnings("restriction")
+public class AspectBindingReader {
+
+ // XML-Structure of aspectBindings in plugin.xml:
+ private final static String ASPECT_BINDING = "aspectBinding"; //$NON-NLS-1$
+ private final static String BASE_PLUGIN = "basePlugin"; //$NON-NLS-1$
+ private final static String ID = "id"; //attribute //$NON-NLS-1$
+ private final static String FORCED_EXPORTS = "forcedExports"; //$NON-NLS-1$
+ private final static String TEAM = "team"; //$NON-NLS-1$
+ private final static String CLASS = "class"; //attribute //$NON-NLS-1$
+
+ private static final String SELF = "SELF"; //value //$NON-NLS-1$
+ // Note: we do NOT read the requiredFragment element, because when creating access rules
+ // the packages of the fragment will report the host bundle as their providingBundle.
+ // (see PDEAdaptor.RequiredPluginsClasspathContainer#updateRule())
+
+ private static SAXParserFactory fSAXFactory;
+
+ // == local cached storage: ==
+
+ // main date storage: teamClassName -> basePluginName*
+ private HashMap<String, HashSet<String>> team2basePlugins = null;
+
+ private HashMap<String, HashSet<String>> base2forcedExports = null;
+ private HashSet<String> teamsAdaptingSelf= new HashSet<String>();
+
+ // reverse info with more details: basePluginName -> AdaptedBaseBundle
+ private HashMap<String, AdaptedBaseBundle> adaptationInfos= new HashMap<String, AdaptedBaseBundle>();
+
+ private String project;
+ private IProject iProject;
+
+ /** This field serves as a time stamp to track whether an
+ * aspect binding reader has been reloaded. */
+ Object token;
+
+ private boolean hasChanges;
+
+ // for accessing objects of type IPluginModelBase:
+ PluginModelManager fPluginModelManager;
+
+ /**
+ * Create and initialize an AspectBindingReader, i.e., try to read aspect binding info from the project's plugin.xml.
+ *
+ * @param project the project whose aspect bindings should be analyzed.
+ * @throws LiftingVetoException if the project was not ready for reading plugin.xml.
+ */
+ public AspectBindingReader(IProject project) throws LiftingVetoException {
+ if (!this.readAspectBindings(project, getSaxParserFactory()))
+ throw new LiftingVetoException();
+ this.project= project.getName();
+ this.iProject= project;
+ this.fPluginModelManager = PDECore.getDefault().getModelManager();
+ }
+
+ /** Is the given team declared to adapt classes from its own plug-in ("self")? */
+ public boolean isAdaptingSelf(String teamName) {
+ return this.teamsAdaptingSelf.contains(teamName);
+ }
+
+ /** Get the base plug-in adapted by the given team. */
+ public Set<String> getBasePlugins(String teamName) {
+ if (this.team2basePlugins != null)
+ return this.team2basePlugins.get(teamName);
+ return null;
+ }
+
+ /** Is the bundle identified by this symbolic name an adapted base bundle.? */
+ public boolean isAdaptedBase(String symbolicName) {
+ return this.adaptationInfos.containsKey(symbolicName);
+ }
+
+ /** Get the names of all teams that adapt the given base bundle. */
+ public Set<String> getTeamsForBase(String basePluginName) {
+ AdaptedBaseBundle info = this.adaptationInfos.get(basePluginName);
+ if (info == null)
+ return new HashSet<String>();
+ return info.adaptingTeams;
+ }
+
+ /** Get (lazily create) the detailed info for an adapted base bundle. */
+ public AdaptedBaseBundle getAdaptationInfo(String basePluginName) {
+ AdaptedBaseBundle result= this.adaptationInfos.get(basePluginName);
+ if (result == null) {
+ result= new AdaptedBaseBundle(basePluginName, this);
+ this.adaptationInfos.put(basePluginName, result);
+ }
+ return result;
+ }
+
+
+ /** Is the given package force-exported? */
+ public String getForcedExportingBase(String packageName) {
+ if (this.base2forcedExports == null)
+ return null;
+ for (Entry<String, HashSet<String>> entry: this.base2forcedExports.entrySet()) {
+ if (entry.getValue().contains(packageName))
+ return entry.getKey();
+ }
+ return null;
+ }
+
+ public HashSet<String> getForcedExports(String symbolicName) {
+ if (this.base2forcedExports == null)
+ return null;
+ return this.base2forcedExports.get(symbolicName);
+ }
+
+ static SAXParserFactory getSaxParserFactory() {
+ if (fSAXFactory == null)
+ fSAXFactory = SAXParserFactory.newInstance();
+ return fSAXFactory;
+ }
+
+
+ /** Read all the <aspectBinding> declarations from plugin.xml.
+ * @return whether or not reading plugin.xml was successful.
+ */
+ private boolean readAspectBindings (IProject project, SAXParserFactory factory) {
+ SAXParser parser;
+ try {
+ parser = factory.newSAXParser();
+ IFile file = project.getFile("plugin.xml"); //$NON-NLS-1$
+ if (!file.exists())
+ return false;
+ collectAspectBindings(file, parser);
+ this.token= new Object();
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return true;
+ }
+
+ /** Stage 1: remember which team declares to adapt classes from which base plug-in. */
+ void recordAspectBinding(String teamClass, String basePluginID) {
+ if (SELF.equals(basePluginID.toUpperCase())) {
+ this.teamsAdaptingSelf.add(teamClass);
+ return;
+ }
+ if (this.team2basePlugins == null)
+ this.team2basePlugins = new HashMap<String, HashSet<String>>();
+ HashSet<String> plugins = this.team2basePlugins.get(teamClass);
+ if (plugins == null) {
+ plugins = new HashSet<String>();
+ this.team2basePlugins.put(teamClass, plugins);
+ }
+ plugins.add(basePluginID);
+
+ // and store detailed reverse info:
+ AdaptedBaseBundle adaptationInfo = getAdaptationInfo(basePluginID);
+ adaptationInfo.adaptingTeams.add(teamClass);
+ }
+
+ void recordForcedExports(String basePlugin, String exports) {
+ if (this.base2forcedExports == null)
+ this.base2forcedExports= new HashMap<String, HashSet<String>>();
+ HashSet<String> baseExports= this.base2forcedExports.get(basePlugin);
+ if (baseExports == null)
+ this.base2forcedExports.put(basePlugin, baseExports= new HashSet<String>());
+ String[] singleExports= exports.split(","); //$NON-NLS-1$
+ for (int i = 0; i < singleExports.length; i++)
+ baseExports.add(singleExports[i].trim());
+ // TODO(SH): not yet checked: are the exports really packages of basePlugin?
+ }
+
+ void collectAspectBindings(IFile file, SAXParser parser) {
+ try {
+ parser.parse(file.getContents(), new DefaultHandler() {
+ String basePluginID = null;
+ ArrayList<String> teamClasses = null;
+ StringBuffer forcedExports= null;
+ @Override
+ public void startElement(String uri, String localName, String name, Attributes attributes)
+ throws SAXException
+ {
+ if (name.equals(ASPECT_BINDING))
+ this.teamClasses = new ArrayList<String>();
+ else if (this.teamClasses != null) { // within an aspectBinding element?
+ if (name.equals(BASE_PLUGIN)) {
+ this.basePluginID = attributes.getValue(ID);
+ } else if (name.equals(TEAM)) {
+ String teamClass = attributes.getValue(CLASS);
+ if (teamClass == null)
+ throw new SAXException("team element lacking \"class\" attribute"); //$NON-NLS-1$
+ this.teamClasses.add(teamClass);
+ } else if (name.equals(FORCED_EXPORTS)) {
+ this.forcedExports= new StringBuffer();
+ }
+ }
+ }
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException
+ {
+ if (this.forcedExports != null)
+ this.forcedExports.append(ch, start, length);
+ }
+ @Override
+ public void endElement(String uri, String localName, String name)
+ throws SAXException
+ {
+ if (name.equals(ASPECT_BINDING)) {
+ if (this.basePluginID == null)
+ throw new SAXException("aspectBinding missing a \"basePlugin\" element"); //$NON-NLS-1$
+ for (String teamClass : this.teamClasses)
+ recordAspectBinding(teamClass, this.basePluginID);
+ this.basePluginID = null;
+ this.teamClasses = null;
+ } else if (name.equals(FORCED_EXPORTS)) {
+ if (this.forcedExports != null && this.forcedExports.length() > 0)
+ recordForcedExports(this.basePluginID, this.forcedExports.toString());
+ this.forcedExports= null;
+ }
+ }
+ });
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ // ===== Below: Updating. =====
+
+ /** When plugin.xml has changed re-read our data and perhaps clear
+ * cached data in the JavaModelManager and RequirePluginsClasspathContainer. */
+ void reload() {
+ this.hasChanges= true;
+
+ HashMap<String,HashSet<String>> oldForcedExports= this.base2forcedExports;
+ HashMap<String,HashSet<String>> oldTeamBindings= this.team2basePlugins;
+ // clear internal storage:
+ this.team2basePlugins = null; // be sure to initialize new sets if needed, so we can compare sets using mapHasChanged
+ this.base2forcedExports = null;
+ this.adaptationInfos.clear(); // these two are created by default (and no need to compare old/new)
+ this.teamsAdaptingSelf.clear();
+
+ if (!this.readAspectBindings(this.iProject, getSaxParserFactory())) {
+ OTDTPlugin.getDefault().getLog().log(new Status(Status.ERROR, OTDTPlugin.PLUGIN_ID, "Unable to re-read plugin.xml!;")); //$NON-NLS-1$
+ return ;
+ }
+
+ // remove cached data if forced exports or team bindings have changed:
+ if ( mapHasChanged(oldForcedExports, this.base2forcedExports)
+ || mapHasChanged(oldTeamBindings, this.team2basePlugins))
+ {
+ resetRequiredPluginsClasspathContainer(this.iProject);
+ }
+ }
+
+ /** Destructively read the flag indicating changed aspect binding data. */
+ boolean fetchHasChanges() {
+ try {
+ return this.hasChanges;
+ } finally {
+ this.hasChanges= false;
+ }
+ }
+
+ private void resetRequiredPluginsClasspathContainer(IProject project) {
+ IJavaProject jProject = JavaCore.create(project);
+ IPluginModelBase model = fPluginModelManager.findModel(project);
+ try {
+ IBuild build = ClasspathUtilCore.getBuild(model);
+ RequiredPluginsClasspathContainer container = new RequiredPluginsClasspathContainer(model, build);
+ // this triggers recomputing the classpath:
+ JavaCore.setClasspathContainer(PDECore.REQUIRED_PLUGINS_CONTAINER_PATH, new IJavaProject[]{jProject}, new IClasspathContainer[] {container}, null);
+ // AspectBindingReader is automatically shared via the ResourceProjectAdaptor.OTEquinoxProject
+ // see org.eclipse.objectteams.otdt.internal.compiler.adaptor.AdaptorActivator.JavaCore.setClasspathContainer(..)
+ } catch (CoreException ce) {
+ OTDTPlugin.getExceptionHandler().logException("Failed to reload classpath container for "+project, ce); //$NON-NLS-1$
+ }
+ }
+
+ private <T> boolean mapHasChanged(HashMap<String,T> oldMap,
+ HashMap<String,T> newMap)
+ {
+ if (oldMap == null || newMap== null)
+ return oldMap != newMap; // null and non-null?
+ HashSet<String> newKeys= new HashSet<String>(newMap.keySet());
+ for (Map.Entry<String, T> oldEntry : oldMap.entrySet()) {
+ T newVal= newMap.get(oldEntry.getKey());
+ if (newVal == null)
+ return true; // removed entry
+ if (!newVal.equals(oldEntry.getValue()))
+ return true; // changed value (simple or complex)
+ newKeys.remove(oldEntry.getKey());
+ }
+ return !newKeys.isEmpty(); // added entries in newKeys?
+ }
+
+ // ===== Debug: =====
+ @SuppressWarnings("nls")
+ @Override
+ public String toString() {
+ String result= "AspectBindingReader for project "+this.project;
+ if (this.team2basePlugins != null)
+ result+= "\n\t known teams: "+this.team2basePlugins.size();
+ if (this.teamsAdaptingSelf != null)
+ result+= "\n\t self-adaption teams: "+this.teamsAdaptingSelf.size();
+ if (this.base2forcedExports != null)
+ result+= "\n\t plugins with forced exports: "+this.base2forcedExports.size();
+ return result;
+ }
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/BaseImportChecker.java b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/BaseImportChecker.java
new file mode 100644
index 0000000..c8f33cf
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/BaseImportChecker.java
@@ -0,0 +1,289 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2007 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * 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
+ * $Id: BaseImportChecker.java 23451 2010-02-04 20:33:32Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otdt.internal.compiler.adaptor;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.ImportReference;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Expression.DecapsulationState;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.jdt.internal.compiler.env.AccessRule;
+import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ImportBinding;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.objectteams.otdt.core.exceptions.InternalCompilerError;
+
+import base org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+import base org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+
+/**
+ * This team checks whether base-imports are backed up by proper aspectBinding declarations.
+ * (Only activated if the project has the PluginNature).
+ * This team is only temporarily instantiated/activated by AdaptorActivator.JavaProject(JavaProject).
+ *
+ * This team also handles the forcedExport declarations from aspectBindings extensions
+ * and correspondingly converts some diagnostics from forbiddenAccess to decapsulationByForcedExport.
+ *
+ * Other parts involved:
+ *
+ * + PDEAdaptor is responsible for adding aspectBindingData (of type AdaptedBaseBundle)
+ * to ClasspathAccessRules and adjusting the problemID
+ *
+ * + org.eclipse.jdt.internal.core.builder.NameEnvironment
+ * - computeClasspathLocations(IWorkspaceRoot, JavaProject, SimpleLookupTable)
+ * Feed AccessRuleSet from ClasspathEntry into ClasspathLocations like ClasspathDirectory.
+ *
+ * + org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment
+ * - setAccessRestriction(ReferenceBinding, AccessRestriction)
+ * - AccessRestriction getAccessRestriction(TypeBinding type)
+ * Pass AccessRestriction from sources like ClasspathDirectory.accessRuleSet into the compiler.
+ *
+ * @author stephan
+ * @since 1.1.2
+ */
+@SuppressWarnings("restriction")
+public team class BaseImportChecker extends CompilationThreadWatcher
+{
+ private AspectBindingReader aspectBindingReader;
+
+ public BaseImportChecker() {/* emtpy ctor for OT/Equinox */ }
+
+ /**
+ * @param aspectBindingReader must be non-null (and initialized).
+ */
+ public BaseImportChecker(AspectBindingReader aspectBindingReader) {
+ this.aspectBindingReader= aspectBindingReader;
+ }
+
+ /**
+ * If a forced exports exist convert some diagnostics from forbiddenAccess
+ * to decapsulationByForcedExport.
+ */
+ protected class ProblemReporter playedBy ProblemReporter
+ {
+ // imports via callout:
+ protected void baseImportInRegularClass(TypeDeclaration firstType, ImportReference reference)
+ -> void baseImportInRegularClass(TypeDeclaration firstType, ImportReference reference);
+ protected void illegalBaseImportNoAspectBinding(ImportReference ref, String teamName)
+ -> void illegalBaseImportNoAspectBinding(ImportReference ref, String teamName);
+ protected void illegalBaseImport(ImportReference ref, String expectedBasePlugin, String actualBasePlugin)
+ -> void illegalBaseImport(ImportReference ref, String expectedBasePlugin, String actualBasePlugin);
+ void illegalUseOfForcedExport(ReferenceBinding type, ASTNode reference)
+ -> void illegalUseOfForcedExport(ReferenceBinding type, ASTNode reference);
+ void decapsulationByForcedExport(ReferenceBinding type, ASTNode reference)
+ -> void decapsulationByForcedExport(ReferenceBinding type, ASTNode reference);
+ void baseImportFromSplitPackage(ImportReference ref, String expectedPlugin)
+ -> void baseImportFromSplitPackage(ImportReference ref, String expectedPlugin);
+
+
+ ReferenceContext getReferenceContext() -> get ReferenceContext referenceContext;
+
+ /** The callin entry into this role: analyze and report various access situations. */
+ @SuppressWarnings("basecall")
+ callin void forbiddenReference(TypeBinding type, ASTNode location, AccessRestriction restriction)
+ {
+ switch (restriction.getProblemId()) {
+ case IProblem.BaseclassDecapsulationForcedExport:
+ switch (getBaseclassDecapsulation(location)) {
+ case ALLOWED:
+ decapsulationByForcedExport((ReferenceBinding)type, location);
+ case REPORTED:
+ break;
+ default:
+ // no forced export for regular use!
+ illegalUseOfForcedExport((ReferenceBinding)type, location);
+ }
+ break;
+ case IProblem.AdaptedPluginAccess:
+ // not a real error but requires consistency check against aspectBinding:
+ if (location instanceof ImportReference) {
+ ImportReference imp= (ImportReference)location;
+ if (imp.isBase()) {
+ String teamName= getReferenceTeam();
+ if (teamName == null)
+ baseImportInRegularClass(getPublicType(), imp);
+
+ Set<String> basePlugins= aspectBindingReader.getBasePlugins(teamName);
+ if (basePlugins == null || basePlugins.isEmpty()) {
+ illegalBaseImportNoAspectBinding(imp, teamName);
+ return;
+ }
+ String baseString = flattenSet(basePlugins);
+ Set<String> actualBases = new HashSet<String>();
+ AccessRule rule= restriction.getAccessRule();
+ if (rule.aspectBindingData != null) {
+ for (Object data : rule.aspectBindingData) {
+ AdaptedBaseBundle info= (AdaptedBaseBundle) data;
+ if (info.isAdaptedBy(teamName)) {
+ // OK, no error
+ if (info.hasPackageSplit)
+ baseImportFromSplitPackage(imp, baseString); // just a warning
+ return;
+ }
+ actualBases.add(info.getSymbolicName());
+ }
+ }
+ illegalBaseImport(imp, baseString, flattenSet(actualBases));
+ }
+ }
+ break;
+ default:
+ base.forbiddenReference(type, location, restriction);
+ }
+ }
+ void forbiddenReference(TypeBinding type, ASTNode location, AccessRestriction restriction)
+ <- replace void forbiddenReference(TypeBinding type, ASTNode location, byte entryType, AccessRestriction restriction)
+ with { type <- type, location <- location, restriction <- restriction }
+
+ void forbiddenReference(TypeBinding type, ASTNode location, AccessRestriction restriction)
+ <- replace void forbiddenReference(MethodBinding method, ASTNode location, byte entryType, AccessRestriction restriction)
+ with { type <- method.declaringClass, location <- location, restriction <- restriction }
+
+ void forbiddenReference(TypeBinding type, ASTNode location, AccessRestriction restriction)
+ <- replace void forbiddenReference(FieldBinding field, ASTNode location, byte entryType, AccessRestriction restriction)
+ with { type <- field.declaringClass, location <- location, restriction <- restriction }
+
+
+ private DecapsulationState getBaseclassDecapsulation(ASTNode location) {
+ if (location instanceof Expression) {
+ if (location instanceof AllocationExpression)
+ return DecapsulationState.REPORTED; // base-ctor expression.
+ if (location instanceof MessageSend)
+ return DecapsulationState.REPORTED; // callout message send.
+ Expression expr= (Expression) location;
+ DecapsulationState result= expr.getBaseclassDecapsulation();
+ if (result == DecapsulationState.ALLOWED)
+ expr.tagReportedBaseclassDecapsulation();
+ return result;
+ }
+ if (location instanceof ImportReference) {
+ ImportReference impRef= (ImportReference)location;
+ if (impRef.isBase())
+ return DecapsulationState.ALLOWED; // always need to report
+ }
+ return DecapsulationState.NONE;
+ }
+ private String getReferenceTeam() {
+ TypeDeclaration type= getPublicType();
+ if (type != null && type.isTeam())
+ return new String(type.binding.readableName());
+ return null;
+ }
+ private TypeDeclaration getPublicType() {
+ ReferenceContext context= getReferenceContext();
+ if (context instanceof CompilationUnitDeclaration) {
+ CompilationUnitDeclaration unit= (CompilationUnitDeclaration)context;
+ if (unit.types == null) return null;
+ for (TypeDeclaration type : unit.types)
+ if (Flags.isPublic(type.modifiers))
+ return type;
+ }
+ return null;
+ }
+ }
+
+
+ protected class ImportTracker playedBy CompilationUnitScope
+ {
+ ReferenceBinding[] getTopLevelTypes() -> get ReferenceBinding[] topLevelTypes;
+ private // don't publically expose protected role ProblemReporter
+ ProblemReporter problemReporter() -> ProblemReporter problemReporter();
+
+ /** When setting the base imports to a CUScope, check for imports from undeclared plug-ins. */
+ void setBaseImports(ImportBinding[] resolvedBaseImports, int baseCount, ImportReference[] refs)
+ <- before void setBaseImports(ImportBinding[] resolvedBaseImports, int baseCount, ImportReference[] refs);
+ void setBaseImports(ImportBinding[] resolvedBaseImports, int baseCount, ImportReference[] refs)
+ {
+ if (baseCount == 0) return;
+ ReferenceBinding teamType = findMainType();
+ String teamName= (teamType != null)
+ ? new String(teamType.readableName()) : null;
+ for (int i=0; i<baseCount; i++) {
+ if (teamType == null) {
+ problemReporter().baseImportInRegularClass(null, refs[i]);
+ continue;
+ }
+ if (resolvedBaseImports[i].onDemand) // syntactically impossible
+ throw new InternalCompilerError("Ondemand base import not supported"); //$NON-NLS-1$
+ String basePlugins= null;
+ if (resolvedBaseImports[i].resolvedImport instanceof ReferenceBinding) {
+ ReferenceBinding importedType= (ReferenceBinding)resolvedBaseImports[i].resolvedImport;
+ if (!importedType.isValidBinding())
+ continue; // already reported
+ if (importedType.hasRestrictedAccess())
+ continue; // checked by forbiddenAccess()
+ if (aspectBindingReader.isAdaptingSelf(teamName)) {
+ char[][] current= CharOperation.splitOn('/', teamType.getFileName());
+ char[][] imported= CharOperation.splitOn('/', importedType.getFileName());
+ if (CharOperation.equals(current[1], imported[1]))
+ return;
+ basePlugins= "<self>"; //$NON-NLS-1$
+ }
+ }
+ if (basePlugins == null)
+ basePlugins= flattenSet(aspectBindingReader.getBasePlugins(teamName));
+ if (basePlugins != null)
+ problemReporter().illegalBaseImport(refs[i], basePlugins, null);
+ else
+ problemReporter().illegalBaseImportNoAspectBinding(refs[i], teamName);
+ }
+ }
+ private ReferenceBinding findMainType() {
+ ReferenceBinding[] toplevelTypes = getTopLevelTypes();
+ if (toplevelTypes != null)
+ for (ReferenceBinding referenceBinding : toplevelTypes)
+ if (referenceBinding.isPublic())
+ return referenceBinding;
+
+ return null;
+ }
+ }
+ @SuppressWarnings("nls")
+ String flattenSet(Set<String> stringSet) {
+ if (stringSet == null) return null;
+ Iterator<String> iterator = stringSet.iterator();
+ if (stringSet.size()==1) {
+ return iterator.next();
+ } else {
+ String result = "[";
+ while(true) {
+ result += iterator.next();
+ if (!iterator.hasNext()) break;
+ result += ", ";
+ }
+ return result + "]";
+ }
+ }
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/BuildManager.java b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/BuildManager.java
new file mode 100644
index 0000000..6be0534
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/BuildManager.java
@@ -0,0 +1,345 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * 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
+ * $Id: BuildManager.java 23451 2010-02-04 20:33:32Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otdt.internal.compiler.adaptor;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
+
+import base org.eclipse.jdt.core.compiler.CategorizedProblem;
+import base org.eclipse.jdt.internal.compiler.CompilationResult;
+import base org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; // base-class of a role file
+import base org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
+import base org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import base org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+import base org.eclipse.jdt.internal.compiler.problem.AbortType;
+import base org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import base org.eclipse.objectteams.otdt.internal.core.compiler.lifting.LiftingEnvironment;
+import base org.eclipse.jdt.internal.core.builder.IncrementalImageBuilder; // base-class of a role file
+
+/**
+ * This Team observes the build/compile process and advises the IncrementalImageBuilder,
+ * when and what to recompile due to OT-specific dependencies.
+ *
+ * @author stephan
+ * @version $Id: BuildManager.java 23451 2010-02-04 20:33:32Z stephan $
+ */
+@SuppressWarnings("restriction")
+public team class BuildManager extends CompilationThreadWatcher
+{
+ public static int DEBUG = 0; // levels: 0 nothing, 1 some, 2 more.
+
+ /** Remember the (one) ImageBuilder role. */
+ ImageBuilder builder = null;
+
+ // ====== Data common for all roles (incl. accessors and life-cycle). ======
+
+
+ /** Manage cross-ref table for copied roles:
+ * PRODUCER: RoleCopyTracker.trackCopyRole()
+ * CONSUMER: ClassFileChangeTracker.nonStructuralChange()
+ *
+ * ENCODING: RoleTypeName -> Set<TeamSourceFileName> */
+ HashMap<String, Set<String>> roleToSubTeams = new HashMap<String, Set<String>>();
+
+ void recordCopiedRole(char[] roleName, char[] subTeamSourceFileName) {
+ String roleString = new String(roleName);
+ Set<String> teams = roleToSubTeams.get(roleString);
+ if (teams == null)
+ roleToSubTeams.put(roleString, teams = new HashSet<String>());
+ teams.add(new String(subTeamSourceFileName));
+ if (DEBUG >= 2)
+ System.out.println("role "+roleString+" is COPIED to "+new String(subTeamSourceFileName)); //$NON-NLS-1$//$NON-NLS-2$
+ }
+// // debug helper
+// void printCopyTable() {
+// System.out.print("-------------------------");
+// for (Map.Entry<String, Set<String>> entry : roleToSubTeams.entrySet()) {
+// System.out.print("\nRole "+entry.getKey());
+// for (String value : entry.getValue()) {
+// System.out.print("\n\t"+value);
+// }
+// }
+// System.out.println("\n-------------------------");
+// }
+
+ /** If a tsuper role has non-structural changes, some sub-teams need to be recompiled.
+ * This set holds the teams to be recompiled.
+ *
+ * PRODUCERS: ClassFileChangeTracker.nonStructuralChange()
+ * ImageBuilder.shouldPreserveBinary() (during compile->finishedWith)
+ * CONSUMER: ImageBuilder.addAffectedTeamFiles()
+ *
+ * ENCODING: source file name
+ */
+ HashSet<String> teamsToRecompile = new HashSet<String>();
+
+ /** Get and clear the set of teams waiting for recompilation. */
+ HashSet<String> fetchTeamsToRecompile() {
+ HashSet<String> result = teamsToRecompile;
+ teamsToRecompile = new HashSet<String>();
+ return result;
+ }
+
+ /** If a tsuper role has non-structural changes, some sub-teams need to be recompiled.
+ * This set holds the roles that should NOT be preserved.
+ * PRODUCER: ClassFileChangeTracker.nonStructuralChange()
+ * CONSUMER: shouldPreserveBinary() (via shouldCandidateBePreserved())
+ *
+ * ENCODING: Qualified Type Name. p.T$I, canonical form, i.e., __OT__ prefixes removed.
+ */
+ HashSet<String> staleRoles = new HashSet<String>();
+
+ synchronized void initializeDependencyStorage() {
+ this.roleToSubTeams = new HashMap<String, Set<String>>();
+ this.teamsToRecompile = new HashSet<String>();
+ this.staleRoles = new HashSet<String>();
+ }
+
+ protected class BinaryType playedBy BinaryTypeBinding
+ {
+ /** Record if a given type depends on an unresolvable type.
+ * More specifically, we look for roles depending on unresolvable tsuper roles.
+ */
+ superInterfaces <- replace superInterfaces;
+ callin ReferenceBinding[] superInterfaces() {
+ try {
+ return base.superInterfaces();
+ } catch (AbortCompilation as Abort abort) {
+ abort.referencedBinaries.add(this);
+ throw abort;
+ }
+ }
+
+ // ==== Callouts: ====
+
+ char[][] compoundName() -> get char[][] compoundName;
+
+ // DEBUGGING:
+ String internalName() -> char[] internalName()
+ with { result <- new String(result) }
+ }
+
+ protected class ClassScope playedBy ClassScope
+ {
+ @SuppressWarnings("decapsulation")
+ void connectTypeHierarchy() <- replace void connectTypeHierarchy();
+ @SuppressWarnings("basecall")
+ callin void connectTypeHierarchy() {
+ try {
+ base.connectTypeHierarchy();
+ } catch (org.eclipse.jdt.internal.compiler.problem.AbortType at) {
+ TypeDeclaration referenceContext = referenceContext();
+ SourceTypeBinding sourceType = referenceContext.binding;
+ at.updateContext(referenceContext, referenceCompilationUnit().compilationResult);
+ referenceContext.ignoreFurtherInvestigation = true;
+ if (sourceType.superInterfaces == null)
+ sourceType.superInterfaces = TypeBinding.NO_SUPERINTERFACES; // TODO(SH): recurse?
+ // don't rethrow, marking ignoreFurtherInvestigation is enough abortion
+ }
+ }
+ TypeDeclaration referenceContext() -> get TypeDeclaration referenceContext;
+ CompilationUnitDeclaration referenceCompilationUnit() -> CompilationUnitDeclaration referenceCompilationUnit();
+ }
+
+ protected class LiftingEnv playedBy LiftingEnvironment
+ {
+ callin void init(TypeDeclaration teamType) {
+ try {
+ base.init(teamType);
+ } catch (org.eclipse.jdt.internal.compiler.problem.AbortType at) {
+ teamType.ignoreFurtherInvestigation = true;
+ BuildManager.this.teamsToRecompile.add(String.valueOf(teamType.compilationResult.fileName));
+ throw at; // TODO(SH): might want to mark certain AT-instances as recoverable?
+ }
+ }
+ init <- replace init;
+ }
+
+ /** This role helps to link Problem->Abort->BinaryType,
+ * in order to determine whether a problem was caused by an unresolvable tsuper role.
+ */
+ protected class Abort playedBy AbortCompilation
+ {
+ public List<BinaryType> referencedBinaries = new ArrayList<BinaryType>();
+
+ /** Trigger: this role has more to be updated from the context. */
+ void updateContext(ASTNode astNode, CompileResult unitResult)
+ <- after void updateContext(ASTNode astNode, CompilationResult unitResult);
+
+ /**
+ * If the current abort exception could possibly be fixed by a recompile,
+ * + convert the exception onto a less drastic AbortType
+ * + record the link Problem->Abort.
+ */
+ public void updateContext(ASTNode astNode, CompileResult unitResult) {
+ Problem problem = getProblem();
+ if ( problem != null
+ && problem.couldBeFixedByRecompile()
+ && unitResult.isReusingBinaryMember())
+ {
+ // convert AbortCompilation into AbortType
+ Abort abort = new AbortType(
+ new org.eclipse.jdt.internal.compiler.problem.AbortType(
+ unitResult, problem));
+ abort.referencedBinaries = this.referencedBinaries;
+ problem.abortException = abort;
+ RuntimeException ex = abort;
+ throw ex;
+ }
+ }
+
+ protected Problem getProblem() -> get CategorizedProblem problem;
+ }
+
+ protected class AbortType extends Abort playedBy AbortType
+ {
+// // FIXME : this ctor gives a VerifyError:
+// AbortType (CompileResult result, Problem problem) {
+// base(result, problem);
+// problem.abortException = this;
+// }
+ @Override
+ public void updateContext(ASTNode astNode, CompileResult unitResult) {
+ // no super call: would cause recursive creation of roles
+ Problem problem = getProblem();
+ if (problem != null) {
+ problem.abortException = this;
+ }
+ }
+ }
+
+ /** Intermediate purely callout role. */
+ protected class CompileResult playedBy CompilationResult
+ {
+ protected // don't publically export protected role Problem
+ Problem[] problems() -> get CategorizedProblem[] problems;
+
+ // TODO(SH): workaround for lowering problem concerning base call in ImageBuilder.shouldPreserveBinary()
+ boolean hasBinaryMember(char[] typeName) -> boolean hasBinaryMember(char[] typeName);
+
+ @SuppressWarnings({"decapsulation", "unchecked"})
+ protected
+ boolean isReusingBinaryMember() -> get ArrayList binaryMemberNames
+ with { result <- !(result == null || result.isEmpty()) }
+
+ char[] getFileName() -> char[] getFileName();
+ // debugging:
+ toString => toString;
+ }
+
+ /** Let a problem know about the associated exception. */
+ protected class Problem playedBy CategorizedProblem
+ {
+ public Abort abortException = null;
+ public char[] typeToRemove= null;
+
+ /** Certain problem reasons might be fixed by recompilation. */
+ protected boolean couldBeFixedByRecompile() {
+ switch (getID()) {
+ case IProblem.IsClassPathCorrect:
+ case IProblem.StaleTSuperRole:
+ case IProblem.StaleSubRole:
+ case IProblem.MissingRoleInBinaryTeam:
+ case IProblem.RoleFileInBinaryTeam:
+ case IProblem.CorruptBytecode:
+ case IProblem.MissingAccessorInBinary:
+ case IProblem.MismatchingRoleParts:
+ case IProblem.InconsistentlyResolvedRole:
+ case IProblem.NotGeneratingCallinBinding:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ int getID() -> int getID();
+ // debugging:
+ toString => getMessage;
+ }
+
+ /** Watch specific error reports. */
+ protected class ProblemReporter playedBy ProblemReporter {
+
+ // a missing role in a binary team means the binary team should probably be deleted.
+ void missingRoleInBinaryTeam(ReferenceBinding type)
+ <- replace void missingRoleInBinaryTeam(char[] roleName, ReferenceBinding enclosingTeam)
+ with { type <- enclosingTeam }
+
+ callin void missingRoleInBinaryTeam(ReferenceBinding type) {
+ ReferenceContext context= getReferenceContext();
+ try {
+ base.missingRoleInBinaryTeam(type);
+ } finally {
+ if (context != null && context.compilationResult() != null) {
+ int count= context.compilationResult().problemCount;
+ recordTypeToRemove(context.compilationResult().problems[count-1],
+ type.constantPoolName());
+ }
+ }
+ }
+
+ ReferenceContext getReferenceContext() -> get ReferenceContext referenceContext;
+ }
+
+ // ---- ImageBuilder is a role file ----
+
+
+ // ---- Team level features: ----
+ void recordTypeToRemove(CategorizedProblem as Problem prob, char[] roleName) {
+ prob.typeToRemove= roleName;
+ }
+
+ public static boolean isPredefinedRole(char[] roleName) {
+ int dollarPos = CharOperation.lastIndexOf('$', roleName);
+ if (dollarPos != -1)
+ roleName = CharOperation.subarray(roleName, dollarPos+1, -1);
+ return CharOperation.equals(roleName, IOTConstants.CONFINED)
+ || CharOperation.equals(roleName, IOTConstants.OTCONFINED)
+ || CharOperation.equals(roleName, IOTConstants.ICONFINED)
+ || CharOperation.equals(roleName, IOTConstants.IBOUNDBASE)
+ || CharOperation.equals(roleName, IOTConstants.ILOWERABLE);
+ }
+
+ /** Answer whether the given role type should be re-used (ask the ImageBuilder). */
+ public boolean shouldPreserveBinaryRole(ReferenceBinding role, CompilationResult as CompileResult cResult) {
+ if (builder == null)
+ return true;
+ return builder.shouldPreserveBinaryRole(role, cResult);
+ }
+
+ public String canonicalName(String roleName) {
+ return roleName.replace(IOTConstants.OT_DELIM, ""); //$NON-NLS-1$
+ }
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/BuildManager/ClassFileChangeTracker.java b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/BuildManager/ClassFileChangeTracker.java
new file mode 100644
index 0000000..f1d9b75
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/BuildManager/ClassFileChangeTracker.java
@@ -0,0 +1,62 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * 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
+ * $Id: ClassFileChangeTracker.java 23451 2010-02-04 20:33:32Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+team package org.eclipse.objectteams.otdt.internal.compiler.adaptor.BuildManager;
+
+import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
+
+
+/**
+ * This class tracks whenever a classfile has non-structural changes.
+ * In that case a re-compile is needed iff the class is a role of
+ * which copies exist in subteams within the workspace/project.
+ *
+ * @author stephan
+ */
+@SuppressWarnings("restriction")
+public class ClassFileChangeTracker playedBy ClassFileReader
+{
+ void nonStructuralChange(String className) <- after boolean hasStructuralChanges(byte[] newBytes)
+ when (!result)
+ with {className <- new String(base.getName())}
+
+ /** No structural changes where detected, yet bytes differ.*/
+ // static for optimization (avoid lifting).
+ protected static void nonStructuralChange(String className) {
+ className = className.replace('/', '.');
+ if (DEBUG >= 2)
+ System.out.println("Non-structural change for "+className); //$NON-NLS-1$
+ int dollarPos = className.lastIndexOf('$');
+ if (dollarPos == -1)
+ return; // not a role
+ String roleName = canonicalName(className.substring(dollarPos+1)); //excluding '$'
+ Set<String> teamSourceFileNames = BuildManager.this.roleToSubTeams.get(className);
+ if (teamSourceFileNames != null)
+ for (String teamSourceFileName : teamSourceFileNames) {
+ if (DEBUG > 0)
+ System.out.println("need to recompile "+teamSourceFileName); //$NON-NLS-1$
+ BuildManager.this.teamsToRecompile.add(teamSourceFileName);
+ String teamTypeName = teamSourceFileName.substring(0, teamSourceFileName.length()-5); // .java
+ // mark both parts (class/ifc) as stale:
+ BuildManager.this.staleRoles.add(teamTypeName+'$'+roleName);
+ BuildManager.this.staleRoles.add(teamTypeName+'$'+IOTConstants.OT_DELIM+roleName);
+ }
+ }
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/BuildManager/ImageBuilder.java b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/BuildManager/ImageBuilder.java
new file mode 100644
index 0000000..f434f76
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/BuildManager/ImageBuilder.java
@@ -0,0 +1,269 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * 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
+ * $Id: ImageBuilder.java 23451 2010-02-04 20:33:32Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+team package org.eclipse.objectteams.otdt.internal.compiler.adaptor.BuildManager;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.core.builder.SourceFile;
+import org.eclipse.jdt.internal.core.builder.WorkQueue;
+import org.eclipse.objectteams.otdt.core.compiler.OTNameUtils;
+
+/**
+ * @author stephan
+ */
+@SuppressWarnings("restriction")
+protected class ImageBuilder playedBy IncrementalImageBuilder
+{
+ ImageBuilder (IncrementalImageBuilder builder) {
+ BuildManager.this.builder = this;
+ }
+
+ // Set of teams being compiled due to our special request.
+ // don't preserve binary roles within such a team.
+ private HashSet<String> teamsForcedRecompilation = new HashSet<String>();
+ resetQueue:
+ void resetQueue() <- after void compile(SourceFile[] files);
+ void resetQueue() {
+ teamsForcedRecompilation.clear();
+ }
+
+ /**
+ * Trigger B1: During processing a type with errors ...
+ */
+ storeProblemsFor <- replace storeProblemsFor;
+
+ /** Before storing problems for a given source file, check whether the problem
+ * could be due to a binary role referring to a stale or missing tsuper-copy.
+ * In that case trigger recompilation.
+ * The binary file will be deleted later ...
+ */
+ callin void storeProblemsFor(SourceFile sourceFile, Problem[] problems)
+ throws org.eclipse.core.runtime.CoreException
+ {
+ if (sourceFile != null && problems != null && problems.length > 0) {
+ Problem[] remainingProblems = new Problem[problems.length];
+ int count = 0;
+ for (int i = 0; i < problems.length; i++) {
+ if (problems[i].couldBeFixedByRecompile()) {
+ // record the source file for recompilation:
+ ArrayList<SourceFile> sourceFiles = sourceFiles();
+ if (!sourceFiles.contains(sourceFile)) {
+ sourceFiles.add(sourceFile);
+ if (DEBUG>0)
+ System.out.println("Abort causes recompile of "+sourceFile); //$NON-NLS-1$
+ }
+ // don't add the problem to remainingProblems, because any IProblem.IsClassPathCorrect
+ // will abort this compilation! (we still think, we can fix this problem..)
+ char[] typePath= problems[i].typeToRemove;
+ if (typePath != null)
+ this.scheduleForRemoval(sourceFile, String.valueOf(typePath));
+ } else {
+ remainingProblems[count++] = problems[i];
+ }
+ }
+ if (count < problems.length)
+ System.arraycopy(remainingProblems, 0, problems = new Problem[count], 0, count);
+ }
+ base.storeProblemsFor(sourceFile, problems);
+ }
+
+ void scheduleForRemoval(SourceFile sourceFile, String typePath)
+ -> void scheduleForRemoval(SourceFile sourceFile, String typePath);
+
+ /**
+ * Trigger B2: During finishedWith() generated binary files are deleted, but some
+ * should perhaps be preserved...
+ */
+ shouldPreserveBinary <- replace shouldPreserveBinary;
+
+ /**
+ * If the given binary type is a re-used member (role) preserve the binary file,
+ * HOWEVER, if it has dependency problems do NOT preserve it.
+ *
+ * @param cResult
+ * @param sourceFolder
+ * @param packagePath
+ * @param binaryTypeName
+ * @return
+ */
+ callin boolean shouldPreserveBinary(CompileResult cResult,
+ IPath sourceFolder,
+ IPath packagePath,
+ char[] binaryTypeName)
+ {
+ // don't preserve re-used binary types with problems. They might be stale.
+ if (!base.shouldPreserveBinary(cResult, sourceFolder, packagePath, binaryTypeName))
+ return false;
+ return shouldPreserveBinaryRole(cResult, sourceFolder, packagePath, binaryTypeName);
+ }
+ /** Entry from AdaptorActivator.CopyInheritanceObserver (via BuildManager): */
+ protected boolean shouldPreserveBinaryRole(ReferenceBinding role, CompileResult cResult) {
+ String fileName = new String(cResult.getFileName());
+ IPath packagePath = new Path(fileName).removeLastSegments(1);
+ int packageDepth = role.getPackage().compoundName.length;
+ IPath sourceFolder = packagePath.removeLastSegments(packageDepth);
+ packagePath = packagePath.removeFirstSegments(sourceFolder.segmentCount());
+ char[][] roleName = CharOperation.splitOn('.', role.attributeName());
+ boolean result = shouldPreserveBinaryRole(cResult, sourceFolder, packagePath, roleName[roleName.length-1]); // Team$Role
+ if (!result)
+ scheduleForRemoval(findTeamSourceFile(fileName), new String(role.constantPoolName()));
+ return result;
+ }
+ /** Common implementation for the two entries above.
+ * Both clients when receiving a 'false' answer will remove the stale binary class.
+ * This will ensure that during the next cycle this type will be compiled from source.
+ */
+ boolean shouldPreserveBinaryRole(CompileResult cResult, IPath sourceFolder, IPath packagePath, char[] binaryTypeName)
+ {
+ // binary type with problem -> NO
+ if (binaryHasProblem(cResult.problems(), binaryTypeName))
+ return false;
+
+ String binaryTypeString = packagePath.toString()+"/"+new String(binaryTypeName);
+ if (DEBUG >= 2)
+ System.out.print("candidate for preserving: "+binaryTypeString); //$NON-NLS-1$
+
+ // predefined type -> YES
+ if (isPredefinedRole(binaryTypeName)) {
+ if (DEBUG >= 2)
+ System.out.println(" YES(predefined)."); //$NON-NLS-1$
+ return true;
+ }
+ // others: further investigate.
+ boolean shouldPreserve = shouldCandidateBePreserved(sourceFolder, binaryTypeString);
+ if (!shouldPreserve)
+ // propagate changes down to sub-teams:
+ ClassFileChangeTracker.nonStructuralChange(binaryTypeString);
+ return shouldPreserve;
+ }
+ /** Checks the following reasons against preserving:<ul>
+ * <li> the enclosing team is forced for recompilation (meaning: full recompilation)
+ * <li> the given type is a role known to be stale */
+ boolean shouldCandidateBePreserved(IPath sourceFolder, String binaryTypeString)
+ {
+ int dollarPos = binaryTypeString.lastIndexOf('$');
+ String enclosingRelativeFileString = binaryTypeString.substring(0, dollarPos)+".java"; //$NON-NLS-1$
+ String enclosingAbsoluteFileString = sourceFolder.append(enclosingRelativeFileString).toString();
+ for (String teamFileName : teamsForcedRecompilation) {
+ if (teamFileName.equals(enclosingAbsoluteFileString)) {
+ if (DEBUG >= 2)
+ System.out.println(" NO(forced)."); //$NON-NLS-1$
+ BuildManager.this.teamsToRecompile.add(teamFileName); // let binary roles be removed and try again.
+ return false;
+ }
+ }
+ binaryTypeString = sourceFolder.append(binaryTypeString).toString();
+ if (BuildManager.this.staleRoles.contains(binaryTypeString)) {
+ BuildManager.this.staleRoles.remove(binaryTypeString);
+ if (DEBUG >= 2)
+ System.out.println(" NO(changed).");
+ return false;
+ }
+
+ if (DEBUG >= 2)
+ System.out.println(" YES");
+ return true;
+ }
+
+ /** Is the given binary type known to have an unresolved dependency? */
+ boolean binaryHasProblem(Problem[] problems, char[] binaryTypeName) {
+ if (problems != null)
+ for (Problem problem : problems)
+ if (problem != null && problem.abortException != null) {
+ Abort abort = problem.abortException;
+ for (BinaryType binding : abort.referencedBinaries) {
+ char[][] compoundName = binding.compoundName();
+ if (CharOperation.equals(compoundName[compoundName.length-1], binaryTypeName))
+ return true;
+ }
+ }
+ // remove "__OT__" from binaryTypeName
+ char[] strippedName = OTNameUtils.removeOTDelim(binaryTypeName);
+ if (strippedName != binaryTypeName)
+ return binaryHasProblem(problems, strippedName);
+ return false;
+ }
+
+ // Trigger: after adding source files to compile,
+ // consider any roles which have been copied:
+ // if the source changed, all sub teams must be recompiled.
+ void addAffectedTeamFiles() <- after void addAffectedSourceFiles();
+
+ void addAffectedTeamFiles() {
+ // fetch sets of teams:
+ Set<String> teamFiles = fetchTeamsToRecompile();
+
+ ArrayList<SourceFile> sourceFiles = sourceFiles();
+
+ // add all relevant teams to sourceFiles:
+ for (String teamName : teamFiles) {
+ SourceFile teamFile = findTeamSourceFile(teamName);
+ if ( teamFile != null
+ && !sourceFiles.contains(teamFile))
+ {
+ if (DEBUG>0)
+ System.out.println("Scheduling for recompilation: teamFile "+teamFile+" for "+teamName); //$NON-NLS-1$ //$NON-NLS-2$
+ sourceFiles.add(teamFile);
+ teamsForcedRecompilation.add(teamName);
+ }
+ }
+ }
+ SourceFile findTeamSourceFile(String teamName) {
+ IWorkspace ws = ResourcesPlugin.getWorkspace();
+ IFile file = ws.getRoot().getFile(new Path(teamName));
+ return findSourceFile(file);
+ }
+
+ // ==== GENERAL ACCESS TO BASE ELEMENTS: ====
+
+ @SuppressWarnings("decapsulation")
+ SourceFile findSourceFile(IFile file) -> SourceFile findSourceFile(IFile file, boolean mustExist)
+ with { file -> file, true -> mustExist, result <- result }
+
+ @SuppressWarnings({"decapsulation", "unchecked"})
+ ArrayList<SourceFile> sourceFiles() -> get ArrayList<SourceFile> sourceFiles;
+
+ @SuppressWarnings("decapsulation")
+ WorkQueue getWorkQueue() -> get WorkQueue workQueue;
+
+ // ==== LOGGING ====
+ void logCompile(String msg) <- before void compile(SourceFile[] units)
+ with { msg <- "Starting" }
+
+ logDone:
+ void logCompile(String msg) <- after void compile(SourceFile[] units)
+ with { msg <- "Done" }
+
+ void logCompile(String msg)
+ when (DEBUG > 0)
+ {
+ System.out.println("Incremental compilation: "+msg+" for "+getWorkQueue());
+ }
+
+ precedence resetQueue, logDone;
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/CompilationThreadWatcher.java b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/CompilationThreadWatcher.java
new file mode 100644
index 0000000..7b4ca0c
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/CompilationThreadWatcher.java
@@ -0,0 +1,48 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2008 Technical University Berlin, Germany.
+ *
+ * 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
+ * $Id: CompilationThreadWatcher.java 23451 2010-02-04 20:33:32Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otdt.internal.compiler.adaptor;
+
+import base org.eclipse.jdt.internal.compiler.ProcessTaskManager;
+
+/**
+ * This team observes the ProcessTaskManager in order to extend team activation
+ * of sub-teams to the processingTask once it is created.
+ *
+ * @author stephan
+ * @since 1.2.0
+ */
+@SuppressWarnings("restriction")
+public team class CompilationThreadWatcher
+{
+ protected class ProcessTaskManager playedBy ProcessTaskManager
+ {
+
+ @SuppressWarnings("decapsulation")
+ Thread getProcessingThread() -> get Thread processingThread;
+
+
+ extendActivation <- after setConfig;
+ void extendActivation() {
+ CompilationThreadWatcher.this.activate(getProcessingThread());
+ }
+
+
+ void cleanup() <- after void run();
+ void cleanup() { CompilationThreadWatcher.this.deactivate(); }
+
+ }
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/IllegalReusedBinaryRoleException.java b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/IllegalReusedBinaryRoleException.java
new file mode 100644
index 0000000..04f52fb
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/IllegalReusedBinaryRoleException.java
@@ -0,0 +1,29 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * 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
+ * $Id: IllegalReusedBinaryRoleException.java 23451 2010-02-04 20:33:32Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otdt.internal.compiler.adaptor;
+
+@SuppressWarnings("serial")
+public class IllegalReusedBinaryRoleException extends RuntimeException {
+ public IllegalReusedBinaryRoleException(String msg) {
+ super(msg);
+ }
+
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/PDEAdaptor.java b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/PDEAdaptor.java
new file mode 100644
index 0000000..ff3c448
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/PDEAdaptor.java
@@ -0,0 +1,273 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2007 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * 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
+ * $Id: PDEAdaptor.java 23451 2010-02-04 20:33:32Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otdt.internal.compiler.adaptor;
+
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.IAccessRule;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.core.ClasspathAccessRule;
+import org.eclipse.osgi.service.resolver.BundleDescription;
+import org.eclipse.osgi.service.resolver.ExportPackageDescription;
+import org.eclipse.osgi.service.resolver.StateHelper;
+import org.eclipse.pde.core.plugin.IPluginModelBase;
+import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase;
+
+import base org.eclipse.pde.internal.core.PDEClasspathContainer;
+import base org.eclipse.pde.internal.core.RequiredPluginsClasspathContainer;
+import base org.eclipse.pde.internal.core.PDEClasspathContainer.Rule;
+import base org.eclipse.pde.internal.core.bundle.BundlePluginModel;
+import base org.eclipse.pde.internal.core.plugin.WorkspaceExtensionsModel;
+
+/**
+ * Adapt classes from the PDE core as to feed information about aspectBindings
+ * into the compilation process (to be consumed by BaseImportChecker).
+ *
+ * Final target as expected by the BaseImportChecker:
+ * + aspectBindingData (of type AdaptedBaseBundle) have been added to ClasspathAccessRules
+ * and the problemID has been adjusted.
+ *
+ *
+ * @author stephan
+ * @since 1.1.5
+ */
+@SuppressWarnings("restriction")
+public team class PDEAdaptor
+{
+ static PDEAdaptor instance;
+
+ public PDEAdaptor() {
+ instance= this;
+ }
+
+ /**
+ * <ul>
+ * <li>Store aspectBinding info in Role objects.</li>
+ * <li>Add additional rules for forcedExports.</li>
+ * </ul>
+ */
+ protected class RequiredPluginsClasspathContainer
+ extends PDEClasspathContainer
+ playedBy RequiredPluginsClasspathContainer
+ {
+
+ protected AspectBindingReader aspectBindingReader;
+
+ void updateRule(String providingBundle, Rule rule)
+ <- after Rule getRule(StateHelper helper, BundleDescription desc, ExportPackageDescription export)
+ with { providingBundle <- export.getExporter().getSymbolicName(),
+ rule <- result
+ }
+ /** Handles adaptation info for exported packages, Rule role created via regular lifting. */
+ void updateRule(String providingBundle, Rule rule) {
+ if (aspectBindingReader != null && aspectBindingReader.isAdaptedBase(providingBundle)) {
+ // no merging because rule (base & role) are fresh instances
+ rule.aspectBindingData= aspectBindingReader.getAdaptationInfo(providingBundle);
+ }
+ }
+
+ @SuppressWarnings({ "decapsulation", "rawtypes" })
+ Rule[] addForcedExports(BundleDescription desc)
+ <- replace Rule[] getInclusions(Map map, BundleDescription desc)
+ with { desc <- desc }
+ /** Handles adaptation info for non-exported packages, Rule role explicitly created. */
+ callin Rule[] addForcedExports(BundleDescription desc)
+ {
+ Rule[] regularRules= base.addForcedExports(desc);
+ if (aspectBindingReader == null)
+ return regularRules; // done: no aspect bindings
+ HashSet<String> forcedExports= aspectBindingReader.getForcedExports(desc.getSymbolicName());
+ if (forcedExports == null)
+ return regularRules; // done: no forced exports
+
+ AdaptedBaseBundle aspectBindingData= aspectBindingReader.getAdaptationInfo(desc.getSymbolicName());
+ // create additional rules:
+ Rule[] additionalRules= new Rule[forcedExports.size()];
+ Iterator<String> exportIter= forcedExports.iterator();
+ for (int i = 0; i < additionalRules.length; i++)
+ additionalRules[i]= new Rule(this, aspectBindingData, exportIter.next());
+
+ // merge arrays:
+ int len1= regularRules.length, len2= additionalRules.length;
+ Rule[] result= new Rule[len1+len2];
+ System.arraycopy(additionalRules, 0, result, 0, len2);
+ System.arraycopy(regularRules, 0, result, len2, len1);
+
+ return result;
+ }
+
+ @SuppressWarnings("decapsulation")
+ protected
+ BundleModel getBundleModel() -> get IPluginModelBase fModel
+ with { result <- (BundlePluginModel)fModel }
+
+ // -- debug: --
+ String baseToString() => String toString();
+
+ @SuppressWarnings("nls")
+ @Override
+ public String toString() {
+ return "Role for "+baseToString()+" with aspectBindingReader\n "
+ + ((this.aspectBindingReader != null) ? this.aspectBindingReader.toString() : "null");
+ }
+ }
+
+ /**
+ * Synthetic rules representing adapted or forcedExports.
+ */
+ @SuppressWarnings("decapsulation")
+ protected class Rule playedBy Rule
+ {
+ void setPath(IPath path) -> set IPath path;
+
+ // intermediate storage between AspectBindingReader and ClasspathAccessRule:
+ protected AdaptedBaseBundle aspectBindingData;
+ protected boolean isForcedExport;
+
+ /** Ctor for force-exported packages (merely adapted packages instantiate via lifting ctor). */
+ protected Rule(RequiredPluginsClasspathContainer encl, AdaptedBaseBundle aspectBindingData, String packageName)
+ {
+ encl.base();
+ String pattern= packageName.replace('.', '/')+"/*"; //$NON-NLS-1$
+ setPath(new Path(pattern));
+ this.aspectBindingData= aspectBindingData;
+ this.isForcedExport= true;
+ }
+ // -- debug: --
+ String baseToString() => String toString();
+
+ @SuppressWarnings("nls")
+ @Override
+ public String toString() {
+ String result= baseToString();
+ if (this.isForcedExport)
+ result+= " (forced export)";
+ return result+" with aspect data\n "
+ + ((this.aspectBindingData == null) ? "null" : this.aspectBindingData.toString());
+ }
+ }
+
+ /** After converting Rules to IAccessRules transfer adaptation info and adjust problemId. */
+ protected class PDEClasspathContainer playedBy PDEClasspathContainer
+ {
+ void getAccessRules(Rule[] rules, IAccessRule[] accessRules)
+ <- after IAccessRule[] getAccessRules(Rule[] rules)
+ with { rules <- rules, accessRules <- result }
+ static void getAccessRules(Rule[] rules, IAccessRule[] accessRules) {
+ for (int i = 0; i < rules.length; i++) {
+ Rule rule = rules[i];
+ if (rule.aspectBindingData != null) {
+ ClasspathAccessRule classpathAccessRule = (ClasspathAccessRule)accessRules[i];
+ if (rule.isForcedExport) {
+ // don't let this rule leak to other clients
+ classpathAccessRule = new ClasspathAccessRule(classpathAccessRule.pattern, IProblem.BaseclassDecapsulationForcedExport);
+ classpathAccessRule.aspectBindingData = new Object[] { rule.aspectBindingData };
+ accessRules[i] = classpathAccessRule;
+ } else {
+ addAspectBindingData(classpathAccessRule, rule.aspectBindingData);
+ }
+ }
+ }
+ }
+ }
+ /**
+ * Add the given aspect binding data to the given access rule.
+ * @return: has data been added (vs. merged or already present)?
+ */
+ public static boolean addAspectBindingData(ClasspathAccessRule accessRule, AdaptedBaseBundle aspectBindingData) {
+ // nothing present yet?
+ if (accessRule.aspectBindingData == null) {
+ accessRule.aspectBindingData = new Object[] { aspectBindingData };
+ if (accessRule.problemId == 0)
+ accessRule.problemId= IProblem.AdaptedPluginAccess;
+ return true;
+ }
+ // exact binding data already present?
+ for (Object data : accessRule.aspectBindingData)
+ if (data == aspectBindingData)
+ return false;
+ // different binding data for the same base bundle present?
+ for (Object data : accessRule.aspectBindingData)
+ if (((AdaptedBaseBundle)data).merge(aspectBindingData))
+ return false;
+ // different base bundles, must be the case of split packages
+ for (Object data : accessRule.aspectBindingData)
+ ((AdaptedBaseBundle)data).hasPackageSplit = true;
+ aspectBindingData.hasPackageSplit = true;
+ int len = accessRule.aspectBindingData.length;
+ System.arraycopy(accessRule.aspectBindingData, 0, accessRule.aspectBindingData = new Object[len+1], 0, len);
+ accessRule.aspectBindingData[len] = aspectBindingData;
+ return true;
+ }
+
+ /** Helper role for updating aspect binding information. */
+ protected class BundleModel playedBy BundlePluginModel {
+ protected AspectBindingReader aspectBindingReader;
+
+ }
+
+ /**
+ * This role listens to updates on its base.
+ * If the associated bundle model has a role with a registered
+ * aspect binding reader, trigger reloading when the model has changed.
+ */
+ protected class ModelListener playedBy WorkspaceExtensionsModel {
+ void resetAspectReader() <- after void load(InputStream is, boolean reload);
+ void resetAspectReader () throws CoreException {
+ try {
+ BundleModel bundle= getFBundleModel();
+ if (bundle != null && bundle.aspectBindingReader != null)
+ bundle.aspectBindingReader.reload();
+ } catch (ClassCastException cce) {
+ // CCE could be thrown by parameter mapping of getFBundleModel().
+ }
+ }
+ /** This declaration is for documentation only: read the fBundleModel field.
+ * @return a BundleModel role
+ * @throws ClassCastException thrown when fBundleModel is not a BundlePluginModel.
+ */
+ abstract BundleModel getFBundleModel() throws ClassCastException;
+ @SuppressWarnings("decapsulation")
+ BundleModel getFBundleModel() -> get IBundlePluginModelBase fBundleModel
+ with { result <- (BundlePluginModel)fBundleModel }
+ }
+
+ /** Register an aspect binding reader for a given RequiredPluginsClasspathContainer. */
+ void setAspectBindingReader(AspectBindingReader aspectBindingReader,
+ RequiredPluginsClasspathContainer as RequiredPluginsClasspathContainer container)
+ {
+ container.aspectBindingReader= aspectBindingReader;
+ try {
+ // link bundle model and reader for updating lateron:
+ BundleModel bundle= container.getBundleModel();
+ if (bundle != null)
+ bundle.aspectBindingReader= aspectBindingReader;
+ } catch (ClassCastException cce) {
+ // can happen in param mapping of c-t-f, wrong model type, ignore.
+ }
+ }
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/PlainProjectWatcher.java b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/PlainProjectWatcher.java
new file mode 100644
index 0000000..d1258ce
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/PlainProjectWatcher.java
@@ -0,0 +1,57 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2007 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * 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
+ * $Id: PlainProjectWatcher.java 23451 2010-02-04 20:33:32Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otdt.internal.compiler.adaptor;
+
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+import base org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+
+/**
+ * This team advises the ProblemReporter for non-OT-Plugin projects.
+ * These projects must simply ignore `AccessRestrictions' with
+ * problemId AdaptedPluginAccess, which is not a real problem.
+ *
+ * @author stephan
+ * @since 1.1.5
+ */
+@SuppressWarnings("restriction")
+public team class PlainProjectWatcher extends CompilationThreadWatcher
+{
+ protected class ProblemReporter playedBy ProblemReporter
+ {
+ void forbiddenReference(AccessRestriction restriction)
+ <- replace void forbiddenReference(TypeBinding type, ASTNode location, byte entryType, AccessRestriction restriction),
+ void forbiddenReference(FieldBinding field, ASTNode location, byte entryType, AccessRestriction restriction),
+ void forbiddenReference(MethodBinding method, ASTNode location, byte entryType, AccessRestriction restriction)
+ with { restriction <- restriction }
+
+ @SuppressWarnings("basecall")
+ callin void forbiddenReference(AccessRestriction restriction) {
+ if (restriction.getProblemId() != IProblem.AdaptedPluginAccess)
+ base.forbiddenReference(restriction);
+ }
+ }
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/ProjectUtil.java b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/ProjectUtil.java
new file mode 100644
index 0000000..a7d4b5c
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/ProjectUtil.java
@@ -0,0 +1,63 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2007 Fraunhofer Gesellschaft, Munich, Germany,
+ * for its Fraunhofer Institute for Computer Architecture and Software
+ * Technology (FIRST), Berlin, Germany and Technical University Berlin,
+ * Germany.
+ *
+ * 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
+ * $Id: ProjectUtil.java 23451 2010-02-04 20:33:32Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Fraunhofer FIRST - Initial API and implementation
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otdt.internal.compiler.adaptor;
+
+import org.eclipse.core.internal.resources.Project;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.core.ExternalJavaProject;
+import org.eclipse.objectteams.otdt.core.ext.OTJavaNature;
+
+@SuppressWarnings("restriction")
+public class ProjectUtil {
+
+ static final String PLUGIN_ID = "org.eclipse.objectteams.otdt.internal.compiler.adaptor"; //$NON-NLS-1$
+
+ // Don't use API from from PDE, to reduce dependencies.
+ static final String PLUGIN_NATURE = "org.eclipse.pde.PluginNature"; //$NON-NLS-1$
+
+ public static Project safeGetOTPluginProject(ICompilationUnit unitElem) {
+ IJavaProject project= unitElem.getJavaProject();
+ if (ProjectUtil.isOTPluginProject(project.getProject()))
+ return (Project)project.getProject();
+ return null;
+ }
+
+ public static boolean isOTPluginProject(IProject project) {
+ if (project == null) return false;
+ try {
+ return project.hasNature(PLUGIN_NATURE)
+ && OTJavaNature.hasOTJavaNature(project);
+ } catch (CoreException e) {
+ if (!ExternalJavaProject.EXTERNAL_PROJECT_NAME.equals(project.getName())) // see JavaProject.hasJavaNature()
+ JavaCore.getJavaCore().getLog().log(new Status(IStatus.ERROR,
+ PLUGIN_ID,
+ "Error reading project natures", //$NON-NLS-1$
+ e));
+ return false;
+ }
+ }
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/ResourceProjectAdaptor.java b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/ResourceProjectAdaptor.java
new file mode 100644
index 0000000..333aa95
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/ResourceProjectAdaptor.java
@@ -0,0 +1,86 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2008, 2010 Technical University Berlin, Germany.
+ *
+ * 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
+ * $Id: ResourceProjectAdaptor.java 23451 2010-02-04 20:33:32Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otdt.internal.compiler.adaptor;
+
+import org.objectteams.LiftingVetoException;
+import org.objectteams.Team;
+
+import base org.eclipse.core.internal.resources.Project;
+
+/**
+ * Simple decoration of class Project from org.eclipse.core.resources.
+ *
+ * @author stephan
+ * @since 1.1.8
+ */
+@SuppressWarnings("restriction")
+public team class ResourceProjectAdaptor
+{
+ private static ResourceProjectAdaptor instance;
+ public ResourceProjectAdaptor() {
+ instance= this;
+ }
+ public static ResourceProjectAdaptor getDefault() { return instance; }
+
+ /** Associate an AspectBindingReader and a BaseImportChecker to each OT Plugin project. */
+ protected class OTEquinoxProject playedBy Project
+ {
+ protected AspectBindingReader aspectBindingReader;
+ protected BaseImportChecker checker;
+
+ /**
+ * Lifting constructor which refuses lifting for non OT-plugin projects,
+ * or if the project is not yet ready for reading plugin.xml.
+ */
+ public OTEquinoxProject(Project baseProject) {
+ try {
+ if (!ProjectUtil.isOTPluginProject(baseProject))
+ throw new org.objectteams.LiftingVetoException();
+ this.aspectBindingReader = new AspectBindingReader(baseProject); // may also throw LVE.
+ this.checker= new BaseImportChecker(this.aspectBindingReader);
+ } catch (LiftingVetoException lve) {
+ // no success: unregister this useless role
+ ResourceProjectAdaptor.this.unregisterRole(this, OTEquinoxProject.class);
+ throw lve; // will be caught in several clients within AdaptorActivator
+ }
+ }
+ /** ask for changes to determine if classpath has to be recomputed: */
+ protected boolean hasAspectDataChanged () {
+ return this.aspectBindingReader != null
+ && this.aspectBindingReader.fetchHasChanges();
+ }
+ }
+
+ // ======== API: =========
+
+ public Team getChecker(Project as OTEquinoxProject project)
+ throws LiftingVetoException
+ {
+ return project.checker;
+ }
+ public AspectBindingReader getAspectBindingReader(Project as OTEquinoxProject project)
+ throws LiftingVetoException
+ {
+ return project.aspectBindingReader;
+ }
+ public boolean hasAspectDataChanged(Project as OTEquinoxProject project)
+ throws LiftingVetoException
+ {
+ return project.hasAspectDataChanged();
+ }
+
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/RoleReuseGuard.java b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/RoleReuseGuard.java
new file mode 100644
index 0000000..6345187
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.compiler.adaptor/src/org/eclipse/objectteams/otdt/internal/compiler/adaptor/RoleReuseGuard.java
@@ -0,0 +1,197 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2006, 2010 Technical University Berlin, Germany.
+ *
+ * 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
+ * $Id: RoleReuseGuard.java 23451 2010-02-04 20:33:32Z stephan $
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otdt.internal.compiler.adaptor;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileStruct;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
+
+import base org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
+import base org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
+import base org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+import base org.eclipse.objectteams.otdt.internal.core.compiler.ast.RoleFileCache;
+import base org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.AbstractAttribute;
+import base org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.WordValueAttribute;
+
+/**
+ * This team avoids the situation that a source team when loading its RoFi cache
+ * loads a binary role which is neither purely copied nor a role file.
+ * Such roles are either stale (no longer present in the team) or in some other
+ * way conflict with a role currently being translated.
+ *
+ * By intervening in classfile lookup we prevent conflicting binaries to be
+ * stored by the LookupEnvironment.
+ *
+ * @author stephan
+ */
+@SuppressWarnings("restriction")
+public team class RoleReuseGuard
+{
+ public static int DEBUG = 2; // levels: 0 nothing, 1 some, 2 more.
+
+ // ==== the following roles communicate a cflow-dependency via this field: ====
+ static ThreadLocal<Object> isLoadingRolesOfSourceType = new ThreadLocal<Object>();
+
+ /** Reflect base super-class by a corresponding role super-class. */
+ protected class AbstractAttribute playedBy AbstractAttribute {
+ protected boolean nameEquals(char[] name) -> boolean nameEquals(char[] name);
+ }
+
+ /** This role is a trigger in UseCase A. */
+ protected class WordValueAttribute
+ extends AbstractAttribute
+ playedBy WordValueAttribute
+ {
+ void checkClassFlags(WordValueAttribute attr)
+ <- after WordValueAttribute readClassFlags(ClassFileStruct reader,
+ int readOffset,
+ int[] constantPoolOffsets)
+ with { attr <- result }
+
+ static void checkClassFlags(WordValueAttribute attr) {
+ if (RoleReuseGuard.isLoadingRolesOfSourceType.get() != null)
+ checkNonReusableRole(attr.getValue());
+ }
+ @SuppressWarnings("decapsulation")
+ protected
+ int getValue() -> get int _value;
+ toString => toString;
+ }
+
+ /** A pure cflow-guard. */
+ protected class RoFiTracker
+ playedBy RoleFileCache
+ {
+ @SuppressWarnings("decapsulation")
+ cflow <- replace readBinary;
+ @SuppressWarnings("basecall")
+ callin void cflow() {
+ Object save = isLoadingRolesOfSourceType.get();
+ isLoadingRolesOfSourceType.set(new Object());
+ try {
+ base.cflow();
+ } catch (IllegalReusedBinaryRoleException irbre) {
+ // do nothing. role could simply not be re-used.
+ } finally {
+ isLoadingRolesOfSourceType.set(save);
+ }
+ }
+ }
+
+ protected class SourceTypeBinding playedBy SourceTypeBinding
+ {
+ getMemberType <- replace getMemberType;
+ @SuppressWarnings("basecall")
+ callin ReferenceBinding getMemberType(char[] name) {
+ Object save = isLoadingRolesOfSourceType.get();
+ isLoadingRolesOfSourceType.set(new Object());
+ try {
+ return base.getMemberType(name);
+ } catch (IllegalReusedBinaryRoleException ex) {
+ if (DEBUG>0)
+ System.out.println("refused reusing type "+new String(name)); //$NON-NLS-1$
+ return null; // pretend type was not found.
+ } finally {
+ isLoadingRolesOfSourceType.set(save);
+ }
+ }
+ ReferenceBinding[] getSuperInterfaces() -> get ReferenceBinding[] superInterfaces;
+ void setSuperInterfaces(ReferenceBinding[] superIfcs) -> set ReferenceBinding[] superInterfaces;
+ }
+
+ protected class SafeEnvironment playedBy LookupEnvironment {
+ ReferenceBinding askForType(char[][] typeName)
+ <- replace ReferenceBinding askForType(char[][] typeName);
+ @SuppressWarnings("basecall")
+ callin ReferenceBinding askForType(char[][] typeName) {
+ try {
+ return base.askForType(typeName);
+ } catch (IllegalReusedBinaryRoleException irbre) {
+ if (DEBUG>0) {
+ String rn = new String(CharOperation.concatWith(typeName, '.'));
+ System.out.println("rejected binary role "+rn); //$NON-NLS-1$
+ }
+ return null;
+ }
+ }
+
+ void checkEnclosing(ReferenceBinding created)
+ <- after BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType,
+ PackageBinding packageBinding,
+ boolean needFieldsAndMethods,
+ AccessRestriction accessRestriction)
+ with { created <- result }
+
+ /**
+ * When reading a binary type as a member of a source type,
+ * check whether this is OK or whether the binary member
+ * should be discarded.
+ */
+ void checkEnclosing(ReferenceBinding type) {
+ ReferenceBinding enclosing = type.enclosingType();
+ if (enclosing != null && !enclosing.isBinaryBinding() && type.isRole()) {
+ int flags = type.roleModel.getExtraRoleFlags();
+ checkNonReusableRole(flags);
+ }
+ }
+ }
+
+
+ protected class BinaryType playedBy BinaryTypeBinding
+ {
+
+ // reverse the effect from SourceTypeBinding in case of nested lookup.
+ getMemberType <- replace getMemberType;
+ callin ReferenceBinding getMemberType(char[] name) {
+ Object save = isLoadingRolesOfSourceType.get();
+ isLoadingRolesOfSourceType.remove();
+ try {
+ return base.getMemberType(name);
+ } finally {
+ isLoadingRolesOfSourceType.set(save);
+ }
+ }
+
+ // ==== Callouts: ====
+
+ // DEBUGGING:
+ String internalName() -> char[] internalName()
+ with { result <- new String(result) }
+ }
+
+
+ /** Trigger of UseCase A. */
+ static void checkNonReusableRole(int otClassFlags)
+ throws IllegalReusedBinaryRoleException
+ {
+ if ((otClassFlags & IOTConstants.OT_CLASS_ROLE) == 0)
+ return;
+ int specialRoleFlags = IOTConstants.OT_CLASS_PURELY_COPIED|IOTConstants.OT_CLASS_ROLE_FILE;
+ if ((otClassFlags & specialRoleFlags) == 0)
+ {
+ if (DEBUG>0)
+ System.out.println("throwing!!! "+otClassFlags); //$NON-NLS-1$
+ RuntimeException t = new IllegalReusedBinaryRoleException("don't reuse explicit inline role"); //$NON-NLS-1$
+ //t.printStackTrace();
+ throw t;
+ }
+ }
+}