Fixed bug 370652: custom source location causes "Duplicate extra
attribute: 'org.eclipse.objectteams.originBaseBundle0'" 
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
index 144b2be..5faee2c 100644
--- 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
@@ -49,11 +49,11 @@
 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.objectteams.otdt.core.compiler.IOTConstants;
+import org.eclipse.objectteams.otdt.core.compiler.OTNameUtils;
 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;
@@ -151,17 +151,35 @@
 		 */
 		static callin void addBaseBundleAttribute(IAccessRule[] accessRules, IClasspathAttribute[] extraAttributes) {
 			if (accessRules[0] instanceof ClasspathAccessRule) {
+				int len = extraAttributes.length;
+				int count = 0;
+				// filter existing attributes:
+				for (int i = 0; i < len; i++) {
+					if (!extraAttributes[i].getName().startsWith(CPENTRY_ATTR_ORIGIN_BASE_BUNDLE)) {
+						if (count != i)
+							extraAttributes[count] = extraAttributes[i];
+						count++;
+					}
+				}
+				// add new extraAttribute(s):
 				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);
+							int idx = 0;
+							if (count < len) {
+								idx = count++;
+							} else {
+								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);
+							extraAttributes[idx] = newClasspathAttribute(CPENTRY_ATTR_ORIGIN_BASE_BUNDLE+(i++), baseBundleName);
 						}
+				// compact the array, if existing extraAttributes are being removed:
+				if (count < len)
+					System.arraycopy(extraAttributes, 0, extraAttributes=new IClasspathAttribute[count], 0, count);
 			}
 			base.addBaseBundleAttribute(accessRules, extraAttributes);
 		}		
@@ -180,16 +198,16 @@
 		IProject getProject() -> IProject getProject();
 
 		@SuppressWarnings("rawtypes")
-		void enhanceCPEntry(IClasspathEntry[] resolvedEntries) 
+		void enhanceCPEntries(IClasspathEntry[] resolvedEntries) 
 			<- before void computePackageFragmentRoots(IClasspathEntry[] resolvedEntries, ObjectVector accumulatedRoots,
 													   HashSet rootIDs, IClasspathEntry referringEntry,
 													   boolean retrieveExportedRoots, Map rootToResolvedEntries);
 
 		/**
-		 * @param entry the entry to enhance
+		 * @param entries the entries whose access rules to enhance
 		 * @throws LiftingVetoException when the project is not an OT/Equinox project.
 		 */
-		void enhanceCPEntry(IClasspathEntry[] entries) throws LiftingVetoException 
+		void enhanceCPEntries(IClasspathEntry[] entries) throws LiftingVetoException 
 		{
 			IProject project = getProject();
 			AspectBindingReader reader = ResourceProjectAdaptor.getDefault().getAspectBindingReader((Project)project);
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
index 4e24b4d..6033041 100644
--- 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
@@ -115,9 +115,10 @@
 		@SuppressWarnings("basecall")
 		callin void forbiddenReference(TypeBinding type, ASTNode location, AccessRestriction restriction) 
 		{
+			DecapsulationState baseclassDecapsulation = getBaseclassDecapsulation(location);
 			switch (restriction.getProblemId()) {
 			case IProblem.BaseclassDecapsulationForcedExport:
-				switch (getBaseclassDecapsulation(location)) {
+				switch (baseclassDecapsulation) {
 				case ALLOWED:
 					decapsulationByForcedExport((ReferenceBinding)type, location);
 					break;
@@ -128,43 +129,57 @@
 					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));
-					}
-				}
+			case IProblem.AdaptedPluginAccess:
+				checkAdaptedPluginAccess(location, restriction);
 				break;
 			default:
-				base.forbiddenReference(type, location, restriction);
+				// normal access restriction, but ...
+				if (baseclassDecapsulation == DecapsulationState.ALLOWED) {
+					AccessRule rule= restriction.getAccessRule();
+					if (rule.aspectBindingData != null)
+						// ... as we have aspectBindingData, those should be checked first:
+						if (!checkAdaptedPluginAccess(location, restriction))
+							return;
+				}
+				base.forbiddenReference(type, location, restriction);				
 			}
 		}
+		
+		boolean checkAdaptedPluginAccess(ASTNode location, AccessRestriction restriction) {
+			// 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 false;
+					}
+					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 true;
+							}
+							actualBases.add(info.getSymbolicName());
+						}
+					}
+					illegalBaseImport(imp, baseString, flattenSet(actualBases));
+					return false;
+				}
+			}
+			return true;
+		}
 		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 }
@@ -245,7 +260,7 @@
 					if (!importedType.isValidBinding())
 						continue; // already reported
 					if (importedType.hasRestrictedAccess())
-						continue; // checked by forbiddenAccess()
+						continue; // checked by forbiddenReference()
 					if (aspectBindingReader.isAdaptingSelf(teamName)) {
 						char[][] current= CharOperation.splitOn('/', teamType.getFileName());
 						char[][] imported= CharOperation.splitOn('/', importedType.getFileName());
@@ -274,7 +289,7 @@
 	}
 	@SuppressWarnings("nls")
 	String flattenSet(Set<String> stringSet) {
-		if (stringSet == null) return null;
+		if (stringSet == null || stringSet.size() == 0) return null;
 		Iterator<String> iterator = stringSet.iterator();
 		if (stringSet.size()==1) {
 			return iterator.next();