Bug 532264 - PDE Builders don't contribute to build order can
result in erroneous build order

Introduced DynamicPluginProjectReferences which will return full set of
bundle project dependencies to the build.

Change-Id: Ib8cdf7d9844a6c6ce50158bced1f2db8d775df54
Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
diff --git a/ui/org.eclipse.pde.core/plugin.xml b/ui/org.eclipse.pde.core/plugin.xml
index 49ee1cd..b9781f4 100644
--- a/ui/org.eclipse.pde.core/plugin.xml
+++ b/ui/org.eclipse.pde.core/plugin.xml
@@ -127,6 +127,7 @@
          <run
                class="org.eclipse.pde.internal.core.builders.ManifestConsistencyChecker">
          </run>
+         <dynamicReference class="org.eclipse.pde.internal.core.DynamicPluginProjectReferences"/>
       </builder>
    </extension>
    <extension
diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/DynamicPluginProjectReferences.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/DynamicPluginProjectReferences.java
new file mode 100644
index 0000000..35bf964
--- /dev/null
+++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/DynamicPluginProjectReferences.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ *  Copyright (c) 2018 Andrey Loskutov <loskutov@gmx.de> and others.
+ *  All rights reserved. This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License v1.0
+ *  which accompanies this distribution, and is available at
+ *  http://www.eclipse.org/legal/epl-v10.html
+ *
+ *  Contributors:
+ *     Andrey Loskutov <loskutov@gmx.de> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.pde.internal.core;
+
+import java.util.Collections;
+import java.util.List;
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.pde.core.plugin.IPluginModelBase;
+
+/**
+ * Project references provider for JDT build to compute right build order with
+ * indirect plug-in dependencies
+ */
+public class DynamicPluginProjectReferences implements IDynamicReferenceProvider {
+
+	public DynamicPluginProjectReferences() {
+		super();
+	}
+
+	@Override
+	public List<IProject> getDependentProjects(IBuildConfiguration buildConfiguration) throws CoreException {
+		IProject input = buildConfiguration.getProject();
+		IJavaProject javaProject = JavaCore.create(input);
+		if (javaProject != null) {
+			IPluginModelBase model = PDECore.getDefault().getModelManager().findModel(javaProject.getProject());
+			if (model != null) {
+				return new RequiredPluginsClasspathContainer(model).getAllProjectDependencies();
+			}
+		}
+		return Collections.emptyList();
+	}
+}
diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/RequiredPluginsClasspathContainer.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/RequiredPluginsClasspathContainer.java
index 18d273d..7013d4c 100644
--- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/RequiredPluginsClasspathContainer.java
+++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/RequiredPluginsClasspathContainer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- *  Copyright (c) 2000, 2013 IBM Corporation and others.
+ *  Copyright (c) 2000, 2018 IBM Corporation and others.
  *  All rights reserved. This program and the accompanying materials
  *  are made available under the terms of the Eclipse Public License v1.0
  *  which accompanies this distribution, and is available at
@@ -29,7 +29,8 @@
 	private IPluginModelBase fModel;
 	private IBuild fBuild;
 
-	private IClasspathEntry[] fEntries = null;
+	private IClasspathEntry[] fEntries;
+	private boolean addImportedPackages;
 
 	/**
 	 * Cached list of {@link IClasspathContributor} from plug-in extensions
@@ -259,6 +260,18 @@
 				addDependency((BundleDescription) element.getSupplier(), added, map, entries, useInclusion);
 			}
 		}
+
+		if (addImportedPackages) {
+			// add Import-Package
+			ImportPackageSpecification[] imports = desc.getImportPackages();
+			for (ImportPackageSpecification importSpec : imports) {
+				BaseDescription supplier = importSpec.getSupplier();
+				if (supplier instanceof ExportPackageDescription) {
+					addDependencyViaImportPackage(((ExportPackageDescription) supplier).getExporter(), added, map,
+							entries);
+				}
+			}
+		}
 	}
 
 	private boolean addPlugin(BundleDescription desc, boolean useInclusions, Map<BundleDescription, ArrayList<Rule>> map, ArrayList<IClasspathEntry> entries) throws CoreException {
@@ -481,4 +494,32 @@
 				entries.add(clsEntry);
 		}
 	}
+
+	/**
+	 * Tries to compute a full set of bundle dependencies, including not exported
+	 * bundle dependencies and bundles contributing packages possibly imported by
+	 * any of bundles in the dependency graph.
+	 *
+	 * @return never null, but possibly empty project list which all projects in the
+	 *         workspace this container depends on, directly or indirectly.
+	 */
+	public List<IProject> getAllProjectDependencies() {
+		List<IProject> projects = new ArrayList<>();
+		IWorkspaceRoot root = PDECore.getWorkspace().getRoot();
+		try {
+			addImportedPackages = true;
+			IClasspathEntry[] entries = computePluginEntries();
+			for (IClasspathEntry cpe : entries) {
+				if (cpe.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
+					IProject project = root.getProject(cpe.getPath().lastSegment());
+					if (project.exists()) {
+						projects.add(project);
+					}
+				}
+			}
+		} finally {
+			addImportedPackages = false;
+		}
+		return projects;
+	}
 }