IProject[] referencedProjects = null;
try {
+ IJavaProject javaProject = JavaCore.create(project);
+
// Top level check to make sure the build can move forward.
- abortOnBadSetup(project);
+ abortOnBadSetup(javaProject);
// get the list of referenced projects.
referencedProjects = ProjectHelper.getReferencedProjects(project);
// get the output folder, this method returns the path with a trailing
// separator
- IJavaProject javaProject = JavaCore.create(project);
IFolder outputFolder = BaseProjectHelper.getOutputFolder(project);
// now we need to get the classpath list
}
@Override
- protected void abortOnBadSetup(IProject project) throws CoreException {
- super.abortOnBadSetup(project);
-
- // for this version, we stop on any marker (ie also markers coming from JDT)
- IMarker[] markers = project.findMarkers(null /*type*/, false /*includeSubtypes*/,
- IResource.DEPTH_ZERO);
+ protected void abortOnBadSetup(IJavaProject javaProject) throws CoreException {
+ super.abortOnBadSetup(javaProject);
+
+ // for this version, we stop on any marker (ie also markers coming from JDT).
+ // The depth is set to ZERO to make sure we don't stop on warning on resources.
+ // Only markers set directly on the project are considered.
+ IMarker[] markers = javaProject.getProject().findMarkers(null /*type*/,
+ false /*includeSubtypes*/, IResource.DEPTH_ZERO);
if (markers.length > 0) {
stopBuild("");
import com.android.ide.eclipse.adt.internal.project.XmlErrorHandler;
import com.android.ide.eclipse.adt.internal.project.XmlErrorHandler.XmlErrorListener;
import com.android.ide.eclipse.adt.internal.sdk.LoadStatus;
+import com.android.ide.eclipse.adt.internal.sdk.Sdk;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
* Aborts the build if the SDK/project setups are broken. This does not
* display any errors.
*
- * @param project The {@link IJavaProject} being compiled.
+ * @param javaProject The {@link IJavaProject} being compiled.
* @throws CoreException
*/
- protected void abortOnBadSetup(IProject project) throws CoreException {
- // check if we have finished loading the SDK.
- if (AdtPlugin.getDefault().getSdkLoadStatus() != LoadStatus.LOADED) {
+ protected void abortOnBadSetup(IJavaProject javaProject) throws CoreException {
+ IProject iProject = javaProject.getProject();
+ // check if we have finished loading the project target.
+ Sdk sdk = Sdk.getCurrent();
+ if (sdk == null) {
// we exit silently
stopBuild("SDK is not loaded yet");
}
+ // get the target for the project
+ IAndroidTarget target = sdk.getTarget(javaProject.getProject());
+
+ if (target == null) {
+ // we exit silently
+ stopBuild("Project target not resolved yet.");
+ }
+
+ // check on the target data.
+ if (sdk.checkAndLoadTargetData(target, javaProject) != LoadStatus.LOADED) {
+ // we exit silently
+ stopBuild("Project target not loaded yet.");
+ }
+
// abort if there are TARGET or ADT type markers
- IMarker[] markers = project.findMarkers(AndroidConstants.MARKER_TARGET,
+ IMarker[] markers = iProject.findMarkers(AndroidConstants.MARKER_TARGET,
false /*includeSubtypes*/, IResource.DEPTH_ZERO);
if (markers.length > 0) {
stopBuild("");
}
- markers = project.findMarkers(AndroidConstants.MARKER_ADT, false /*includeSubtypes*/,
+ markers = iProject.findMarkers(AndroidConstants.MARKER_ADT, false /*includeSubtypes*/,
IResource.DEPTH_ZERO);
if (markers.length > 0) {
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
/**
private final SdkManager mManager;
private final AvdManager mAvdManager;
+ /**
+ * Data bundled using during the load of Target data.
+ * <p/>This contains the {@link LoadStatus} and a list of projects that attempted
+ * to compile before the loading was finished. Those projects will be recompiled
+ * at the end of the loading.
+ */
+ private final static class TargetLoadBundle {
+ LoadStatus status;
+ final HashSet<IJavaProject> projecsToReload = new HashSet<IJavaProject>();
+ }
+
/** Map associating an {@link IAndroidTarget} to an {@link AndroidTargetData} */
private final HashMap<IAndroidTarget, AndroidTargetData> mTargetDataMap =
new HashMap<IAndroidTarget, AndroidTargetData>();
- /** Map associating an {@link IAndroidTarget} and the {@link LoadStatus} of its
- * {@link AndroidTargetData}. */
- private final HashMap<IAndroidTarget, LoadStatus> mTargetDataStatusMap =
- new HashMap<IAndroidTarget, LoadStatus>();
+ /** Map associating an {@link IAndroidTarget} and its {@link TargetLoadBundle}. */
+ private final HashMap<IAndroidTarget, TargetLoadBundle> mTargetDataStatusMap =
+ new HashMap<IAndroidTarget, TargetLoadBundle>();
/** Map associating {@link IProject} and their resolved {@link IAndroidTarget}. */
private final HashMap<IProject, IAndroidTarget> mProjectTargetMap =
* <p/>If the SDK failed to load, it displays an error to the user.
* @param sdkLocation the OS path to the SDK.
*/
- public static Sdk loadSdk(String sdkLocation) {
+ public static synchronized Sdk loadSdk(String sdkLocation) {
if (sCurrentSdk != null) {
sCurrentSdk.dispose();
sCurrentSdk = null;
/**
* Returns the current {@link Sdk} object.
*/
- public static Sdk getCurrent() {
+ public static synchronized Sdk getCurrent() {
return sCurrentSdk;
}
* Checks and loads (if needed) the data for a given target.
* <p/> The data is loaded in a separate {@link Job}, and opened editors will be notified
* through their implementation of {@link ITargetChangeListener#onTargetLoaded(IAndroidTarget)}.
+ * <p/>An optional project as second parameter can be given to be recompiled once the target
+ * data is finished loading.
+ * <p/>The return value is non-null only if the target data has already been loaded (and in this
+ * case is the status of the load operation)
* @param target the target to load.
+ * @param project an optional project to be recompiled when the target data is loaded.
+ * If the target is already loaded, nothing happens.
+ * @return The load status if the target data is already loaded.
*/
- public void checkAndLoadTargetData(final IAndroidTarget target) {
+ public LoadStatus checkAndLoadTargetData(final IAndroidTarget target, IJavaProject project) {
boolean loadData = false;
synchronized (AdtPlugin.getDefault().getSdkLockObject()) {
- LoadStatus status = mTargetDataStatusMap.get(target);
- if (status == null) {
+ TargetLoadBundle bundle = mTargetDataStatusMap.get(target);
+ if (bundle == null) {
+ bundle = new TargetLoadBundle();
+ mTargetDataStatusMap.put(target,bundle);
+
// set status to loading
- mTargetDataStatusMap.put(target, LoadStatus.LOADING);
+ bundle.status = LoadStatus.LOADING;
+
+ // add project to bundle
+ if (project != null) {
+ bundle.projecsToReload.add(project);
+ }
+
// and set the flag to start the loading below
loadData = true;
+ } else if (bundle.status == LoadStatus.LOADING) {
+ // add project to bundle
+ if (project != null) {
+ bundle.projecsToReload.add(project);
+ }
+ } else if (bundle.status == LoadStatus.LOADED || bundle.status == LoadStatus.FAILED) {
+ return bundle.status;
}
}
Job job = new Job(String.format("Loading data for %1$s", target.getFullName())) {
@Override
protected IStatus run(IProgressMonitor monitor) {
+ AdtPlugin plugin = AdtPlugin.getDefault();
try {
IStatus status = new AndroidTargetParser(target).run(monitor);
- AdtPlugin plugin = AdtPlugin.getDefault();
+
+ IJavaProject[] javaProjectArray = null;
+
synchronized (plugin.getSdkLockObject()) {
+ TargetLoadBundle bundle = mTargetDataStatusMap.get(target);
+
if (status.getCode() != IStatus.OK) {
- mTargetDataStatusMap.put(target, LoadStatus.FAILED);
+ bundle.status = LoadStatus.FAILED;
+ bundle.projecsToReload.clear();
} else {
- mTargetDataStatusMap.put(target, LoadStatus.LOADED);
+ bundle.status = LoadStatus.LOADED;
+
+ // Prepare the array of project to recompile.
+ // The call is done outside of the synchronized block.
+ javaProjectArray = bundle.projecsToReload.toArray(
+ new IJavaProject[bundle.projecsToReload.size()]);
+
+ // and update the UI of the editors that depend on the target data.
plugin.updateTargetListeners(target);
}
}
+
+ if (javaProjectArray != null) {
+ AndroidClasspathContainerInitializer.updateProjects(javaProjectArray);
+ }
+
return status;
} catch (Throwable t) {
+ synchronized (plugin.getSdkLockObject()) {
+ TargetLoadBundle bundle = mTargetDataStatusMap.get(target);
+ bundle.status = LoadStatus.FAILED;
+ }
+
AdtPlugin.log(t, "Exception in checkAndLoadTargetData."); //$NON-NLS-1$
return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
String.format(
job.setPriority(Job.BUILD); // build jobs are run after other interactive jobs
job.schedule();
}
- }
- /**
- * Returns the {@link LoadStatus} for the data of a given {@link IAndroidTarget}.
- * @param target the target that is queried.
- * @return the status or <code>null</code> if the data was not loaded.
- */
- public LoadStatus getTargetDataLoadStatus(IAndroidTarget target) {
- synchronized (AdtPlugin.getDefault().getSdkLockObject()) {
- return mTargetDataStatusMap.get(target);
- }
+ return null;
}
/**