/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.eclipse.org/org/documents/epl-v10.php
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.ide.eclipse.adt.internal.sdk;

import static com.android.SdkConstants.DOT_XML;
import static com.android.SdkConstants.EXT_JAR;
import static com.android.SdkConstants.FD_RES;

import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ddmlib.IDevice;
import com.android.ide.common.rendering.LayoutLibrary;
import com.android.ide.common.sdk.LoadStatus;
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.build.DexWrapper;
import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
import com.android.ide.eclipse.adt.internal.project.LibraryClasspathContainerInitializer;
import com.android.ide.eclipse.adt.internal.project.ProjectHelper;
import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor;
import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IFileListener;
import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IProjectListener;
import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IResourceEventListener;
import com.android.ide.eclipse.adt.internal.sdk.ProjectState.LibraryDifference;
import com.android.ide.eclipse.adt.internal.sdk.ProjectState.LibraryState;
import com.android.io.StreamException;
import com.android.prefs.AndroidLocation.AndroidLocationException;
import com.android.sdklib.AndroidVersion;
import com.android.sdklib.BuildToolInfo;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkManager;
import com.android.sdklib.devices.DeviceManager;
import com.android.sdklib.internal.avd.AvdManager;
import com.android.sdklib.internal.project.ProjectProperties;
import com.android.sdklib.internal.project.ProjectProperties.PropertyType;
import com.android.sdklib.internal.project.ProjectPropertiesWorkingCopy;
import com.android.sdklib.repository.FullRevision;
import com.android.utils.ILogger;
import com.google.common.collect.Maps;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Central point to load, manipulate and deal with the Android SDK. Only one SDK can be used
 * at the same time.
 *
 * To start using an SDK, call {@link #loadSdk(String)} which returns the instance of
 * the Sdk object.
 *
 * To get the list of platforms or add-ons present in the SDK, call {@link #getTargets()}.
 */
public final class Sdk  {
    private final static boolean DEBUG = false;

    private final static Object LOCK = new Object();

    private static Sdk sCurrentSdk = null;

    /**
     * Map associating {@link IProject} and their state {@link ProjectState}.
     * <p/>This <b>MUST NOT</b> be accessed directly. Instead use {@link #getProjectState(IProject)}.
     */
    private final static HashMap<IProject, ProjectState> sProjectStateMap =
            new HashMap<IProject, ProjectState>();

    /**
     * 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> projectsToReload = new HashSet<IJavaProject>();
    }

    private final SdkManager mManager;
    private final Map<String, DexWrapper> mDexWrappers = Maps.newHashMap();
    private final AvdManager mAvdManager;
    private final DeviceManager mDeviceManager;

    /** 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 its {@link TargetLoadBundle}. */
    private final HashMap<IAndroidTarget, TargetLoadBundle> mTargetDataStatusMap =
        new HashMap<IAndroidTarget, TargetLoadBundle>();

    /**
     * If true the target data will never load anymore. The only way to reload them is to
     * completely reload the SDK with {@link #loadSdk(String)}
     */
    private boolean mDontLoadTargetData = false;

    private final String mDocBaseUrl;

    /**
     * Classes implementing this interface will receive notification when targets are changed.
     */
    public interface ITargetChangeListener {
        /**
         * Sent when project has its target changed.
         */
        void onProjectTargetChange(IProject changedProject);

        /**
         * Called when the targets are loaded (either the SDK finished loading when Eclipse starts,
         * or the SDK is changed).
         */
        void onTargetLoaded(IAndroidTarget target);

        /**
         * Called when the base content of the SDK is parsed.
         */
        void onSdkLoaded();
    }

    /**
     * Basic abstract implementation of the ITargetChangeListener for the case where both
     * {@link #onProjectTargetChange(IProject)} and {@link #onTargetLoaded(IAndroidTarget)}
     * use the same code based on a simple test requiring to know the current IProject.
     */
    public static abstract class TargetChangeListener implements ITargetChangeListener {
        /**
         * Returns the {@link IProject} associated with the listener.
         */
        public abstract IProject getProject();

        /**
         * Called when the listener needs to take action on the event. This is only called
         * if {@link #getProject()} and the {@link IAndroidTarget} associated with the project
         * match the values received in {@link #onProjectTargetChange(IProject)} and
         * {@link #onTargetLoaded(IAndroidTarget)}.
         */
        public abstract void reload();

        @Override
        public void onProjectTargetChange(IProject changedProject) {
            if (changedProject != null && changedProject.equals(getProject())) {
                reload();
            }
        }

        @Override
        public void onTargetLoaded(IAndroidTarget target) {
            IProject project = getProject();
            if (target != null && target.equals(Sdk.getCurrent().getTarget(project))) {
                reload();
            }
        }

        @Override
        public void onSdkLoaded() {
            // do nothing;
        }
    }

    /**
     * Returns the lock object used to synchronize all operations dealing with SDK, targets and
     * projects.
     */
    @NonNull
    public static final Object getLock() {
        return LOCK;
    }

    /**
     * Loads an SDK and returns an {@link Sdk} object if success.
     * <p/>If the SDK failed to load, it displays an error to the user.
     * @param sdkLocation the OS path to the SDK.
     */
    @Nullable
    public static Sdk loadSdk(String sdkLocation) {
        synchronized (LOCK) {
            if (sCurrentSdk != null) {
                sCurrentSdk.dispose();
                sCurrentSdk = null;
            }

            final AtomicBoolean hasWarning = new AtomicBoolean();
            final AtomicBoolean hasError = new AtomicBoolean();
            final ArrayList<String> logMessages = new ArrayList<String>();
            ILogger log = new ILogger() {
                @Override
                public void error(@Nullable Throwable throwable, @Nullable String errorFormat,
                        Object... arg) {
                    hasError.set(true);
                    if (errorFormat != null) {
                        logMessages.add(String.format("Error: " + errorFormat, arg));
                    }

                    if (throwable != null) {
                        logMessages.add(throwable.getMessage());
                    }
                }

                @Override
                public void warning(@NonNull String warningFormat, Object... arg) {
                    hasWarning.set(true);
                    logMessages.add(String.format("Warning: " + warningFormat, arg));
                }

                @Override
                public void info(@NonNull String msgFormat, Object... arg) {
                    logMessages.add(String.format(msgFormat, arg));
                }

                @Override
                public void verbose(@NonNull String msgFormat, Object... arg) {
                    info(msgFormat, arg);
                }
            };

            // get an SdkManager object for the location
            SdkManager manager = SdkManager.createManager(sdkLocation, log);
            try {
                if (manager == null) {
                    hasError.set(true);
                } else {
                    // create the AVD Manager
                    AvdManager avdManager = null;
                    try {
                        avdManager = AvdManager.getInstance(manager.getLocalSdk(), log);
                    } catch (AndroidLocationException e) {
                        log.error(e, "Error parsing the AVDs");
                    }
                    sCurrentSdk = new Sdk(manager, avdManager);
                    return sCurrentSdk;
                }
            } finally {
                if (hasError.get() || hasWarning.get()) {
                    StringBuilder sb = new StringBuilder(
                            String.format("%s when loading the SDK:\n",
                                    hasError.get() ? "Error" : "Warning"));
                    for (String msg : logMessages) {
                        sb.append('\n');
                        sb.append(msg);
                    }
                    if (hasError.get()) {
                        AdtPlugin.printErrorToConsole("Android SDK", sb.toString());
                        AdtPlugin.displayError("Android SDK", sb.toString());
                    } else {
                        AdtPlugin.printToConsole("Android SDK", sb.toString());
                    }
                }
            }
            return null;
        }
    }

    /**
     * Returns the current {@link Sdk} object.
     */
    @Nullable
    public static Sdk getCurrent() {
        synchronized (LOCK) {
            return sCurrentSdk;
        }
    }

    /**
     * Returns the location of the current SDK as an OS path string.
     * Guaranteed to be terminated by a platform-specific path separator.
     * <p/>
     * Due to {@link File} canonicalization, this MAY differ from the string used to initialize
     * the SDK path.
     *
     * @return The SDK OS path or null if no SDK is setup.
     * @deprecated Consider using {@link #getSdkFileLocation()} instead.
     * @see #getSdkFileLocation()
     */
    @Deprecated
    @Nullable
    public String getSdkOsLocation() {
        String path = mManager == null ? null : mManager.getLocation();
        if (path != null) {
            // For backward compatibility make sure it ends with a separator.
            // This used to be the case when the SDK Manager was created from a String path
            // but now that a File is internally used the trailing dir separator is lost.
            if (path.length() > 0 && !path.endsWith(File.separator)) {
                path = path + File.separator;
            }
        }
        return path;
    }

    /**
     * Returns the location of the current SDK as a {@link File} or null.
     *
     * @return The SDK OS path or null if no SDK is setup.
     */
    @Nullable
    public File getSdkFileLocation() {
        if (mManager == null || mManager.getLocalSdk() == null) {
            return null;
        }
        return mManager.getLocalSdk().getLocation();
    }

    /**
     * Returns a <em>new</em> {@link SdkManager} that can parse the SDK located
     * at the current {@link #getSdkOsLocation()}.
     * <p/>
     * Implementation detail: The {@link Sdk} has its own internal manager with
     * a custom logger which is not designed to be useful for outsiders. Callers
     * who need their own {@link SdkManager} for parsing will often want to control
     * the logger for their own need.
     * <p/>
     * This is just a convenient method equivalent to writing:
     * <pre>SdkManager.createManager(Sdk.getCurrent().getSdkLocation(), log);</pre>
     *
     * @param log The logger for the {@link SdkManager}.
     * @return A new {@link SdkManager} parsing the same location.
     */
    public @Nullable SdkManager getNewSdkManager(@NonNull ILogger log) {
        return SdkManager.createManager(getSdkOsLocation(), log);
    }

    /**
     * Returns the URL to the local documentation.
     * Can return null if no documentation is found in the current SDK.
     *
     * @return A file:// URL on the local documentation folder if it exists or null.
     */
    @Nullable
    public String getDocumentationBaseUrl() {
        return mDocBaseUrl;
    }

    /**
     * Returns the list of targets that are available in the SDK.
     */
    public IAndroidTarget[] getTargets() {
        return mManager.getTargets();
    }

    /**
     * Queries the underlying SDK Manager to check whether the platforms or addons
     * directories have changed on-disk. Does not reload the SDK.
     * <p/>
     * This is a quick test based on the presence of the directories, their timestamps
     * and a quick checksum of the source.properties files. It's possible to have
     * false positives (e.g. if a file is manually modified in a platform) or false
     * negatives (e.g. if a platform data file is changed manually in a 2nd level
     * directory without altering the source.properties.)
     */
    public boolean haveTargetsChanged() {
        return mManager.hasChanged();
    }

    /**
     * Returns a target from a hash that was generated by {@link IAndroidTarget#hashString()}.
     *
     * @param hash the {@link IAndroidTarget} hash string.
     * @return The matching {@link IAndroidTarget} or null.
     */
    @Nullable
    public IAndroidTarget getTargetFromHashString(@NonNull String hash) {
        return mManager.getTargetFromHashString(hash);
    }

    @Nullable
    public BuildToolInfo getBuildToolInfo(@Nullable String buildToolVersion) {
        if (buildToolVersion != null) {
            try {
                return mManager.getBuildTool(FullRevision.parseRevision(buildToolVersion));
            } catch (Exception e) {
                // ignore, return null below.
            }
        }

        return null;
    }

    @Nullable
    public BuildToolInfo getLatestBuildTool() {
        return mManager.getLatestBuildTool();
    }

    /**
     * Initializes a new project with a target. This creates the <code>project.properties</code>
     * file.
     * @param project the project to initialize
     * @param target the project's target.
     * @throws IOException if creating the file failed in any way.
     * @throws StreamException if processing the project property file fails
     */
    public void initProject(@Nullable IProject project, @Nullable IAndroidTarget target)
            throws IOException, StreamException {
        if (project == null || target == null) {
            return;
        }

        synchronized (LOCK) {
            // check if there's already a state?
            ProjectState state = getProjectState(project);

            ProjectPropertiesWorkingCopy properties = null;

            if (state != null) {
                properties = state.getProperties().makeWorkingCopy();
            }

            if (properties == null) {
                IPath location = project.getLocation();
                if (location == null) {  // can return null when the project is being deleted.
                    // do nothing and return null;
                    return;
                }

                properties = ProjectProperties.create(location.toOSString(), PropertyType.PROJECT);
            }

            // save the target hash string in the project persistent property
            properties.setProperty(ProjectProperties.PROPERTY_TARGET, target.hashString());
            properties.save();
        }
    }

    /**
     * Returns the {@link ProjectState} object associated with a given project.
     * <p/>
     * This method is the only way to properly get the project's {@link ProjectState}
     * If the project has not yet been loaded, then it is loaded.
     * <p/>Because this methods deals with projects, it's not linked to an actual {@link Sdk}
     * objects, and therefore is static.
     * <p/>The value returned by {@link ProjectState#getTarget()} will change as {@link Sdk} objects
     * are replaced.
     * @param project the request project
     * @return the ProjectState for the project.
     */
    @Nullable
    @SuppressWarnings("deprecation")
    public static ProjectState getProjectState(IProject project) {
        if (project == null) {
            return null;
        }

        synchronized (LOCK) {
            ProjectState state = sProjectStateMap.get(project);
            if (state == null) {
                // load the project.properties from the project folder.
                IPath location = project.getLocation();
                if (location == null) {  // can return null when the project is being deleted.
                    // do nothing and return null;
                    return null;
                }

                String projectLocation = location.toOSString();

                ProjectProperties properties = ProjectProperties.load(projectLocation,
                        PropertyType.PROJECT);
                if (properties == null) {
                    // legacy support: look for default.properties and rename it if needed.
                    properties = ProjectProperties.load(projectLocation,
                            PropertyType.LEGACY_DEFAULT);

                    if (properties == null) {
                        AdtPlugin.log(IStatus.ERROR,
                                "Failed to load properties file for project '%s'",
                                project.getName());
                        return null;
                    } else {
                        //legacy mode.
                        // get a working copy with the new type "project"
                        ProjectPropertiesWorkingCopy wc = properties.makeWorkingCopy(
                                PropertyType.PROJECT);
                        // and save it
                        try {
                            wc.save();

                            // delete the old file.
                            ProjectProperties.delete(projectLocation, PropertyType.LEGACY_DEFAULT);

                            // make sure to use the new properties
                            properties = ProjectProperties.load(projectLocation,
                                    PropertyType.PROJECT);
                        } catch (Exception e) {
                            AdtPlugin.log(IStatus.ERROR,
                                    "Failed to rename properties file to %1$s for project '%s2$'",
                                    PropertyType.PROJECT.getFilename(), project.getName());
                        }
                    }
                }

                state = new ProjectState(project, properties);
                sProjectStateMap.put(project, state);

                // try to resolve the target
                if (AdtPlugin.getDefault().getSdkLoadStatus() == LoadStatus.LOADED) {
                    sCurrentSdk.loadTargetAndBuildTools(state);
                }
            }

            return state;
        }
    }

    /**
     * Returns the {@link IAndroidTarget} object associated with the given {@link IProject}.
     */
    @Nullable
    public IAndroidTarget getTarget(IProject project) {
        if (project == null) {
            return null;
        }

        ProjectState state = getProjectState(project);
        if (state != null) {
            return state.getTarget();
        }

        return null;
    }

    /**
     * Loads the {@link IAndroidTarget} and BuildTools for a given project.
     * <p/>This method will get the target hash string from the project properties, and resolve
     * it to an {@link IAndroidTarget} object and store it inside the {@link ProjectState}.
     * @param state the state representing the project to load.
     * @return the target that was loaded.
     */
    @Nullable
    public IAndroidTarget loadTargetAndBuildTools(ProjectState state) {
        IAndroidTarget target = null;
        if (state != null) {
            String hash = state.getTargetHashString();
            if (hash != null) {
                state.setTarget(target = getTargetFromHashString(hash));
            }

            String markerMessage = null;
            String buildToolInfoVersion = state.getBuildToolInfoVersion();
            if (buildToolInfoVersion != null) {
                BuildToolInfo buildToolsInfo = getBuildToolInfo(buildToolInfoVersion);

                if (buildToolsInfo != null) {
                    state.setBuildToolInfo(buildToolsInfo);
                } else {
                    markerMessage = String.format("Unable to resolve %s property value '%s'",
                                        ProjectProperties.PROPERTY_BUILD_TOOLS,
                                        buildToolInfoVersion);
                }
            } else {
                // this is ok, we'll use the latest one automatically.
                state.setBuildToolInfo(null);
            }

            handleBuildToolsMarker(state.getProject(), markerMessage);
        }

        return target;
    }

    /**
     * Adds or edit a build tools marker from the given project. This is done through a Job.
     * @param project the project
     * @param markerMessage the message. if null the marker is removed.
     */
    private void handleBuildToolsMarker(final IProject project, final String markerMessage) {
        Job markerJob = new Job("Android SDK: Build Tools Marker") {
            @Override
            protected IStatus run(IProgressMonitor monitor) {
                try {
                    if (project.isAccessible()) {
                        // always delete existing marker first
                        project.deleteMarkers(AdtConstants.MARKER_BUILD_TOOLS, true,
                                IResource.DEPTH_ZERO);

                        // add the new one if needed.
                        if (markerMessage != null) {
                            BaseProjectHelper.markProject(project,
                                    AdtConstants.MARKER_BUILD_TOOLS,
                                    markerMessage, IMarker.SEVERITY_ERROR,
                                    IMarker.PRIORITY_HIGH);
                        }
                    }
                } catch (CoreException e2) {
                    AdtPlugin.log(e2, null);
                    // Don't return e2.getStatus(); the job control will then produce
                    // a popup with this error, which isn't very interesting for the
                    // user.
                }

                return Status.OK_STATUS;
            }
        };

        // build jobs are run after other interactive jobs
        markerJob.setPriority(Job.BUILD);
        markerJob.setRule(ResourcesPlugin.getWorkspace().getRoot());
        markerJob.schedule();
    }

    /**
     * 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.
     */
    @NonNull
    public LoadStatus checkAndLoadTargetData(final IAndroidTarget target, IJavaProject project) {
        boolean loadData = false;

        synchronized (LOCK) {
            if (mDontLoadTargetData) {
                return LoadStatus.FAILED;
            }

            TargetLoadBundle bundle = mTargetDataStatusMap.get(target);
            if (bundle == null) {
                bundle = new TargetLoadBundle();
                mTargetDataStatusMap.put(target,bundle);

                // set status to loading
                bundle.status = LoadStatus.LOADING;

                // add project to bundle
                if (project != null) {
                    bundle.projectsToReload.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.projectsToReload.add(project);
                }

                return bundle.status;
            } else if (bundle.status == LoadStatus.LOADED || bundle.status == LoadStatus.FAILED) {
                return bundle.status;
            }
        }

        if (loadData) {
            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);

                        IJavaProject[] javaProjectArray = null;

                        synchronized (LOCK) {
                            TargetLoadBundle bundle = mTargetDataStatusMap.get(target);

                            if (status.getCode() != IStatus.OK) {
                                bundle.status = LoadStatus.FAILED;
                                bundle.projectsToReload.clear();
                            } else {
                                bundle.status = LoadStatus.LOADED;

                                // Prepare the array of project to recompile.
                                // The call is done outside of the synchronized block.
                                javaProjectArray = bundle.projectsToReload.toArray(
                                        new IJavaProject[bundle.projectsToReload.size()]);

                                // and update the UI of the editors that depend on the target data.
                                plugin.updateTargetListeners(target);
                            }
                        }

                        if (javaProjectArray != null) {
                            ProjectHelper.updateProjects(javaProjectArray);
                        }

                        return status;
                    } catch (Throwable t) {
                        synchronized (LOCK) {
                            TargetLoadBundle bundle = mTargetDataStatusMap.get(target);
                            bundle.status = LoadStatus.FAILED;
                        }

                        AdtPlugin.log(t, "Exception in checkAndLoadTargetData.");    //$NON-NLS-1$
                        String message = String.format("Parsing Data for %1$s failed",  target.hashString());
                        if (t instanceof UnsupportedClassVersionError) {
                            message = "To use this platform, run Eclipse with JDK 7 or later. (" + message + ")";
                        }
                        return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, message, t);
                    }
                }
            };
            job.setPriority(Job.BUILD); // build jobs are run after other interactive jobs
            job.setRule(ResourcesPlugin.getWorkspace().getRoot());
            job.schedule();
        }

        // The only way to go through here is when the loading starts through the Job.
        // Therefore the current status of the target is LOADING.
        return LoadStatus.LOADING;
    }

    /**
     * Return the {@link AndroidTargetData} for a given {@link IAndroidTarget}.
     */
    @Nullable
    public AndroidTargetData getTargetData(IAndroidTarget target) {
        synchronized (LOCK) {
            return mTargetDataMap.get(target);
        }
    }

    /**
     * Return the {@link AndroidTargetData} for a given {@link IProject}.
     */
    @Nullable
    public AndroidTargetData getTargetData(IProject project) {
        synchronized (LOCK) {
            IAndroidTarget target = getTarget(project);
            if (target != null) {
                return getTargetData(target);
            }
        }

        return null;
    }

    /**
     * Returns a {@link DexWrapper} object to be used to execute dx commands. If dx.jar was not
     * loaded properly, then this will return <code>null</code>.
     */
    @Nullable
    public DexWrapper getDexWrapper(@Nullable BuildToolInfo buildToolInfo) {
        if (buildToolInfo == null) {
            return null;
        }
        synchronized (LOCK) {
            String dexLocation = buildToolInfo.getPath(BuildToolInfo.PathId.DX_JAR);
            DexWrapper dexWrapper = mDexWrappers.get(dexLocation);

            if (dexWrapper == null) {
                // load DX.
                dexWrapper = new DexWrapper();
                IStatus res = dexWrapper.loadDex(dexLocation);
                if (res != Status.OK_STATUS) {
                    AdtPlugin.log(null, res.getMessage());
                    dexWrapper = null;
                } else {
                    mDexWrappers.put(dexLocation, dexWrapper);
                }
            }

            return dexWrapper;
        }
    }

    public void unloadDexWrappers() {
        synchronized (LOCK) {
            for (DexWrapper wrapper : mDexWrappers.values()) {
                wrapper.unload();
            }
            mDexWrappers.clear();
        }
    }

    /**
     * Returns the {@link AvdManager}. If the AvdManager failed to parse the AVD folder, this could
     * be <code>null</code>.
     */
    @Nullable
    public AvdManager getAvdManager() {
        return mAvdManager;
    }

    @Nullable
    public static AndroidVersion getDeviceVersion(@NonNull IDevice device) {
        try {
            Map<String, String> props = device.getProperties();
            String apiLevel = props.get(IDevice.PROP_BUILD_API_LEVEL);
            if (apiLevel == null) {
                return null;
            }

            return new AndroidVersion(Integer.parseInt(apiLevel),
                    props.get((IDevice.PROP_BUILD_CODENAME)));
        } catch (NumberFormatException e) {
            return null;
        }
    }

    @NonNull
    public DeviceManager getDeviceManager() {
        return mDeviceManager;
    }

    /**
     * Returns a list of {@link ProjectState} representing projects depending, directly or
     * indirectly on a given library project.
     * @param project the library project.
     * @return a possibly empty list of ProjectState.
     */
    @NonNull
    public static Set<ProjectState> getMainProjectsFor(IProject project) {
        synchronized (LOCK) {
            // first get the project directly depending on this.
            Set<ProjectState> list = new HashSet<ProjectState>();

            // loop on all project and see if ProjectState.getLibrary returns a non null
            // project.
            for (Entry<IProject, ProjectState> entry : sProjectStateMap.entrySet()) {
                if (project != entry.getKey()) {
                    LibraryState library = entry.getValue().getLibrary(project);
                    if (library != null) {
                        list.add(entry.getValue());
                    }
                }
            }

            // now look for projects depending on the projects directly depending on the library.
            HashSet<ProjectState> result = new HashSet<ProjectState>(list);
            for (ProjectState p : list) {
                if (p.isLibrary()) {
                    Set<ProjectState> set = getMainProjectsFor(p.getProject());
                    result.addAll(set);
                }
            }

            return result;
        }
    }

    /**
     * Unload the SDK's target data.
     *
     * If <var>preventReload</var>, this effect is final until the SDK instance is changed
     * through {@link #loadSdk(String)}.
     *
     * The goal is to unload the targets to be able to replace existing targets with new ones,
     * before calling {@link #loadSdk(String)} to fully reload the SDK.
     *
     * @param preventReload prevent the data from being loaded again for the remaining live of
     *   this {@link Sdk} instance.
     */
    public void unloadTargetData(boolean preventReload) {
        synchronized (LOCK) {
            mDontLoadTargetData = preventReload;

            // dispose of the target data.
            for (AndroidTargetData data : mTargetDataMap.values()) {
                data.dispose();
            }

            mTargetDataMap.clear();
        }
    }

    private Sdk(SdkManager manager, AvdManager avdManager) {
        mManager = manager;
        mAvdManager = avdManager;

        // listen to projects closing
        GlobalProjectMonitor monitor = GlobalProjectMonitor.getMonitor();
        // need to register the resource event listener first because the project listener
        // is called back during registration with project opened in the workspace.
        monitor.addResourceEventListener(mResourceEventListener);
        monitor.addProjectListener(mProjectListener);
        monitor.addFileListener(mFileListener,
                IResourceDelta.CHANGED | IResourceDelta.ADDED | IResourceDelta.REMOVED);

        // pre-compute some paths
        mDocBaseUrl = getDocumentationBaseUrl(manager.getLocation() +
                SdkConstants.OS_SDK_DOCS_FOLDER);

        mDeviceManager = DeviceManager.createInstance(manager.getLocalSdk().getLocation(),
                                                      AdtPlugin.getDefault());

        // update whatever ProjectState is already present with new IAndroidTarget objects.
        synchronized (LOCK) {
            for (Entry<IProject, ProjectState> entry: sProjectStateMap.entrySet()) {
                loadTargetAndBuildTools(entry.getValue());
            }
        }
    }

    /**
     *  Cleans and unloads the SDK.
     */
    private void dispose() {
        GlobalProjectMonitor monitor = GlobalProjectMonitor.getMonitor();
        monitor.removeProjectListener(mProjectListener);
        monitor.removeFileListener(mFileListener);
        monitor.removeResourceEventListener(mResourceEventListener);

        // the IAndroidTarget objects are now obsolete so update the project states.
        synchronized (LOCK) {
            for (Entry<IProject, ProjectState> entry: sProjectStateMap.entrySet()) {
                entry.getValue().setTarget(null);
            }

            // dispose of the target data.
            for (AndroidTargetData data : mTargetDataMap.values()) {
                data.dispose();
            }

            mTargetDataMap.clear();
        }
    }

    void setTargetData(IAndroidTarget target, AndroidTargetData data) {
        synchronized (LOCK) {
            mTargetDataMap.put(target, data);
        }
    }

    /**
     * Returns the URL to the local documentation.
     * Can return null if no documentation is found in the current SDK.
     *
     * @param osDocsPath Path to the documentation folder in the current SDK.
     *  The folder may not actually exist.
     * @return A file:// URL on the local documentation folder if it exists or null.
     */
    private String getDocumentationBaseUrl(String osDocsPath) {
        File f = new File(osDocsPath);

        if (f.isDirectory()) {
            try {
                // Note: to create a file:// URL, one would typically use something like
                // f.toURI().toURL().toString(). However this generates a broken path on
                // Windows, namely "C:\\foo" is converted to "file:/C:/foo" instead of
                // "file:///C:/foo" (i.e. there should be 3 / after "file:"). So we'll
                // do the correct thing manually.

                String path = f.getAbsolutePath();
                if (File.separatorChar != '/') {
                    path = path.replace(File.separatorChar, '/');
                }

                // For some reason the URL class doesn't add the mandatory "//" after
                // the "file:" protocol name, so it has to be hacked into the path.
                URL url = new URL("file", null, "//" + path);  //$NON-NLS-1$ //$NON-NLS-2$
                String result = url.toString();
                return result;
            } catch (MalformedURLException e) {
                // ignore malformed URLs
            }
        }

        return null;
    }

    /**
     * Delegate listener for project changes.
     */
    private IProjectListener mProjectListener = new IProjectListener() {
        @Override
        public void projectClosed(IProject project) {
            onProjectRemoved(project, false /*deleted*/);
        }

        @Override
        public void projectDeleted(IProject project) {
            onProjectRemoved(project, true /*deleted*/);
        }

        private void onProjectRemoved(IProject removedProject, boolean deleted) {
            if (DEBUG) {
                System.out.println(">>> CLOSED: " + removedProject.getName());
            }

            // get the target project
            synchronized (LOCK) {
                // Don't use getProject() as it could create the ProjectState if it's not
                // there yet and this is not what we want. We want the current object.
                // Therefore, direct access to the map.
                ProjectState removedState = sProjectStateMap.get(removedProject);
                if (removedState != null) {
                    // 1. clear the layout lib cache associated with this project
                    IAndroidTarget target = removedState.getTarget();
                    if (target != null) {
                        // get the bridge for the target, and clear the cache for this project.
                        AndroidTargetData data = mTargetDataMap.get(target);
                        if (data != null) {
                            LayoutLibrary layoutLib = data.getLayoutLibrary();
                            if (layoutLib != null && layoutLib.getStatus() == LoadStatus.LOADED) {
                                layoutLib.clearCaches(removedProject);
                            }
                        }
                    }

                    // 2. if the project is a library, make sure to update the
                    // LibraryState for any project referencing it.
                    // Also, record the updated projects that are libraries, to update
                    // projects that depend on them.
                    for (ProjectState projectState : sProjectStateMap.values()) {
                        LibraryState libState = projectState.getLibrary(removedProject);
                        if (libState != null) {
                            // Close the library right away.
                            // This remove links between the LibraryState and the projectState.
                            // This is because in case of a rename of a project, projectClosed and
                            // projectOpened will be called before any other job is run, so we
                            // need to make sure projectOpened is closed with the main project
                            // state up to date.
                            libState.close();

                            // record that this project changed, and in case it's a library
                            // that its parents need to be updated as well.
                            markProject(projectState, projectState.isLibrary());
                        }
                    }

                    // now remove the project for the project map.
                    sProjectStateMap.remove(removedProject);
                }
            }

            if (DEBUG) {
                System.out.println("<<<");
            }
        }

        @Override
        public void projectOpened(IProject project) {
            onProjectOpened(project);
        }

        @Override
        public void projectOpenedWithWorkspace(IProject project) {
            // no need to force recompilation when projects are opened with the workspace.
            onProjectOpened(project);
        }

        @Override
        public void allProjectsOpenedWithWorkspace() {
            // Correct currently open editors
            fixOpenLegacyEditors();
        }

        private void onProjectOpened(final IProject openedProject) {

            ProjectState openedState = getProjectState(openedProject);
            if (openedState != null) {
                if (DEBUG) {
                    System.out.println(">>> OPENED: " + openedProject.getName());
                }

                synchronized (LOCK) {
                    final boolean isLibrary = openedState.isLibrary();
                    final boolean hasLibraries = openedState.hasLibraries();

                    if (isLibrary || hasLibraries) {
                        boolean foundLibraries = false;
                        // loop on all the existing project and update them based on this new
                        // project
                        for (ProjectState projectState : sProjectStateMap.values()) {
                            if (projectState != openedState) {
                                // If the project has libraries, check if this project
                                // is a reference.
                                if (hasLibraries) {
                                    // ProjectState#needs() both checks if this is a missing library
                                    // and updates LibraryState to contains the new values.
                                    // This must always be called.
                                    LibraryState libState = openedState.needs(projectState);

                                    if (libState != null) {
                                        // found a library! Add the main project to the list of
                                        // modified project
                                        foundLibraries = true;
                                    }
                                }

                                // if the project is a library check if the other project depend
                                // on it.
                                if (isLibrary) {
                                    // ProjectState#needs() both checks if this is a missing library
                                    // and updates LibraryState to contains the new values.
                                    // This must always be called.
                                    LibraryState libState = projectState.needs(openedState);

                                    if (libState != null) {
                                        // There's a dependency! Add the project to the list of
                                        // modified project, but also to a list of projects
                                        // that saw one of its dependencies resolved.
                                        markProject(projectState, projectState.isLibrary());
                                    }
                                }
                            }
                        }

                        // if the project has a libraries and we found at least one, we add
                        // the project to the list of modified project.
                        // Since we already went through the parent, no need to update them.
                        if (foundLibraries) {
                            markProject(openedState, false /*updateParents*/);
                        }
                    }
                }

                // Correct file editor associations.
                fixEditorAssociations(openedProject);

                // Fix classpath entries in a job since the workspace might be locked now.
                Job fixCpeJob = new Job("Adjusting Android Project Classpath") {
                    @Override
                    protected IStatus run(IProgressMonitor monitor) {
                        try {
                            ProjectHelper.fixProjectClasspathEntries(
                                    JavaCore.create(openedProject));
                        } catch (JavaModelException e) {
                            AdtPlugin.log(e, "error fixing classpath entries");
                            // Don't return e2.getStatus(); the job control will then produce
                            // a popup with this error, which isn't very interesting for the
                            // user.
                        }

                        return Status.OK_STATUS;
                    }
                };

                // build jobs are run after other interactive jobs
                fixCpeJob.setPriority(Job.BUILD);
                fixCpeJob.setRule(ResourcesPlugin.getWorkspace().getRoot());
                fixCpeJob.schedule();


                if (DEBUG) {
                    System.out.println("<<<");
                }
            }
        }

        @Override
        public void projectRenamed(IProject project, IPath from) {
            // we don't actually care about this anymore.
        }
    };

    /**
     * Delegate listener for file changes.
     */
    private IFileListener mFileListener = new IFileListener() {
        @Override
        public void fileChanged(final @NonNull IFile file, @NonNull IMarkerDelta[] markerDeltas,
                int kind, @Nullable String extension, int flags, boolean isAndroidPRoject) {
            if (!isAndroidPRoject) {
                return;
            }

            if (SdkConstants.FN_PROJECT_PROPERTIES.equals(file.getName()) &&
                    file.getParent() == file.getProject()) {
                try {
                    // reload the content of the project.properties file and update
                    // the target.
                    IProject iProject = file.getProject();

                    ProjectState state = Sdk.getProjectState(iProject);

                    // get the current target and build tools
                    IAndroidTarget oldTarget = state.getTarget();
                    boolean oldRsSupportMode = state.getRenderScriptSupportMode();

                    // get the current library flag
                    boolean wasLibrary = state.isLibrary();

                    LibraryDifference diff = state.reloadProperties();

                    // load the (possibly new) target.
                    IAndroidTarget newTarget = loadTargetAndBuildTools(state);

                    // reload the libraries if needed
                    if (diff.hasDiff()) {
                        if (diff.added) {
                            synchronized (LOCK) {
                                for (ProjectState projectState : sProjectStateMap.values()) {
                                    if (projectState != state) {
                                        // need to call needs to do the libraryState link,
                                        // but no need to look at the result, as we'll compare
                                        // the result of getFullLibraryProjects()
                                        // this is easier to due to indirect dependencies.
                                        state.needs(projectState);
                                    }
                                }
                            }
                        }

                        markProject(state, wasLibrary || state.isLibrary());
                    }

                    // apply the new target if needed.
                    if (newTarget != oldTarget ||
                            oldRsSupportMode != state.getRenderScriptSupportMode()) {
                        IJavaProject javaProject = BaseProjectHelper.getJavaProject(
                                file.getProject());
                        if (javaProject != null) {
                            ProjectHelper.updateProject(javaProject);
                        }

                        // update the editors to reload with the new target
                        AdtPlugin.getDefault().updateTargetListeners(iProject);
                    }
                } catch (CoreException e) {
                    // This can't happen as it's only for closed project (or non existing)
                    // but in that case we can't get a fileChanged on this file.
                }
            } else if (kind == IResourceDelta.ADDED || kind == IResourceDelta.REMOVED) {
                // check if it's an add/remove on a jar files inside libs
                if (EXT_JAR.equals(extension) &&
                        file.getProjectRelativePath().segmentCount() == 2 &&
                        file.getParent().getName().equals(SdkConstants.FD_NATIVE_LIBS)) {
                    // need to update the project and whatever depend on it.

                    processJarFileChange(file);
                }
            }
        }

        private void processJarFileChange(final IFile file) {
            try {
                IProject iProject = file.getProject();

                if (iProject.hasNature(AdtConstants.NATURE_DEFAULT) == false) {
                    return;
                }

                List<IJavaProject> projectList = new ArrayList<IJavaProject>();
                IJavaProject javaProject = BaseProjectHelper.getJavaProject(iProject);
                if (javaProject != null) {
                    projectList.add(javaProject);
                }

                ProjectState state = Sdk.getProjectState(iProject);

                if (state != null) {
                    Collection<ProjectState> parents = state.getFullParentProjects();
                    for (ProjectState s : parents) {
                        javaProject = BaseProjectHelper.getJavaProject(s.getProject());
                        if (javaProject != null) {
                            projectList.add(javaProject);
                        }
                    }

                    ProjectHelper.updateProjects(
                            projectList.toArray(new IJavaProject[projectList.size()]));
                }
            } catch (CoreException e) {
                // This can't happen as it's only for closed project (or non existing)
                // but in that case we can't get a fileChanged on this file.
            }
        }
    };

    /** List of modified projects. This is filled in
     * {@link IProjectListener#projectOpened(IProject)},
     * {@link IProjectListener#projectOpenedWithWorkspace(IProject)},
     * {@link IProjectListener#projectClosed(IProject)}, and
     * {@link IProjectListener#projectDeleted(IProject)} and processed in
     * {@link IResourceEventListener#resourceChangeEventEnd()}.
     */
    private final List<ProjectState> mModifiedProjects = new ArrayList<ProjectState>();
    private final List<ProjectState> mModifiedChildProjects = new ArrayList<ProjectState>();

    private void markProject(ProjectState projectState, boolean updateParents) {
        if (mModifiedProjects.contains(projectState) == false) {
            if (DEBUG) {
                System.out.println("\tMARKED: " + projectState.getProject().getName());
            }
            mModifiedProjects.add(projectState);
        }

        // if the project is resolved also add it to this list.
        if (updateParents) {
            if (mModifiedChildProjects.contains(projectState) == false) {
                if (DEBUG) {
                    System.out.println("\tMARKED(child): " + projectState.getProject().getName());
                }
                mModifiedChildProjects.add(projectState);
            }
        }
    }

    /**
     * Delegate listener for resource changes. This is called before and after any calls to the
     * project and file listeners (for a given resource change event).
     */
    private IResourceEventListener mResourceEventListener = new IResourceEventListener() {
        @Override
        public void resourceChangeEventStart() {
            mModifiedProjects.clear();
            mModifiedChildProjects.clear();
        }

        @Override
        public void resourceChangeEventEnd() {
            if (mModifiedProjects.size() == 0) {
                return;
            }

            // first make sure all the parents are updated
            updateParentProjects();

            // for all modified projects, update their library list
            // and gather their IProject
            final List<IJavaProject> projectList = new ArrayList<IJavaProject>();
            for (ProjectState state : mModifiedProjects) {
                state.updateFullLibraryList();
                projectList.add(JavaCore.create(state.getProject()));
            }

            Job job = new Job("Android Library Update") { //$NON-NLS-1$
                @Override
                protected IStatus run(IProgressMonitor monitor) {
                    LibraryClasspathContainerInitializer.updateProjects(
                            projectList.toArray(new IJavaProject[projectList.size()]));

                    for (IJavaProject javaProject : projectList) {
                        try {
                            javaProject.getProject().build(IncrementalProjectBuilder.FULL_BUILD,
                                    monitor);
                        } catch (CoreException e) {
                            // pass
                        }
                    }
                    return Status.OK_STATUS;
                }
            };
            job.setPriority(Job.BUILD);
            job.setRule(ResourcesPlugin.getWorkspace().getRoot());
            job.schedule();
        }
    };

    /**
     * Updates all existing projects with a given list of new/updated libraries.
     * This loops through all opened projects and check if they depend on any of the given
     * library project, and if they do, they are linked together.
     */
    private void updateParentProjects() {
        if (mModifiedChildProjects.size() == 0) {
            return;
        }

        ArrayList<ProjectState> childProjects = new ArrayList<ProjectState>(mModifiedChildProjects);
        mModifiedChildProjects.clear();
        synchronized (LOCK) {
            // for each project for which we must update its parent, we loop on the parent
            // projects and adds them to the list of modified projects. If they are themselves
            // libraries, we add them too.
            for (ProjectState state : childProjects) {
                if (DEBUG) {
                    System.out.println(">>> Updating parents of " + state.getProject().getName());
                }
                List<ProjectState> parents = state.getParentProjects();
                for (ProjectState parent : parents) {
                    markProject(parent, parent.isLibrary());
                }
                if (DEBUG) {
                    System.out.println("<<<");
                }
            }
        }

        // done, but there may be parents that are also libraries. Need to update their parents.
        updateParentProjects();
    }

    /**
     * Fix editor associations for the given project, if not already done.
     * <p/>
     * Eclipse has a per-file setting for which editor should be used for each file
     * (see {@link IDE#setDefaultEditor(IFile, String)}).
     * We're using this flag to pick between the various XML editors (layout, drawable, etc)
     * since they all have the same file name extension.
     * <p/>
     * Unfortunately, the file setting can be "wrong" for two reasons:
     * <ol>
     *   <li> The editor type was added <b>after</b> a file had been seen by the IDE.
     *        For example, we added new editors for animations and for drawables around
     *        ADT 12, but any file seen by ADT in earlier versions will continue to use
     *        the vanilla Eclipse XML editor instead.
     *   <li> A bug in ADT 14 and ADT 15 (see issue 21124) meant that files created in new
     *        folders would end up with wrong editor associations. Even though that bug
     *        is fixed in ADT 16, the fix only affects new files, it cannot retroactively
     *        fix editor associations that were set incorrectly by ADT 14 or 15.
     * </ol>
     * <p/>
     * This method attempts to fix the editor bindings retroactively by scanning all the
     * resource XML files and resetting the editor associations.
     * Since this is a potentially slow operation, this is only done "once"; we use a
     * persistent project property to avoid looking repeatedly. In the future if we add
     * additional editors, we can rev the scanned version value.
     */
    private void fixEditorAssociations(final IProject project) {
        QualifiedName KEY = new QualifiedName(AdtPlugin.PLUGIN_ID, "editorbinding"); //$NON-NLS-1$

        try {
            String value = project.getPersistentProperty(KEY);
            int currentVersion = 0;
            if (value != null) {
                try {
                    currentVersion = Integer.parseInt(value);
                } catch (Exception ingore) {
                }
            }

            // The target version we're comparing to. This must be incremented each time
            // we change the processing here so that a new version of the plugin would
            // try to fix existing user projects.
            final int targetVersion = 2;

            if (currentVersion >= targetVersion) {
                return;
            }

            // Set to specific version such that we can rev the version in the future
            // to trigger further scanning
            project.setPersistentProperty(KEY, Integer.toString(targetVersion));

            // Now update the actual editor associations.
            Job job = new Job("Update Android editor bindings") { //$NON-NLS-1$
                @Override
                protected IStatus run(IProgressMonitor monitor) {
                    try {
                        for (IResource folderResource : project.getFolder(FD_RES).members()) {
                            if (folderResource instanceof IFolder) {
                                IFolder folder = (IFolder) folderResource;

                                for (IResource resource : folder.members()) {
                                    if (resource instanceof IFile &&
                                            resource.getName().endsWith(DOT_XML)) {
                                        fixXmlFile((IFile) resource);
                                    }
                                }
                            }
                        }

                        // TODO change AndroidManifest.xml ID too

                    } catch (CoreException e) {
                        AdtPlugin.log(e, null);
                    }

                    return Status.OK_STATUS;
                }

                /**
                 * Attempt to fix the editor ID for the given /res XML file.
                 */
                private void fixXmlFile(final IFile file) {
                    // Fix the default editor ID for this resource.
                    // This has no effect on currently open editors.
                    IEditorDescriptor desc = IDE.getDefaultEditor(file);

                    if (desc == null || !CommonXmlEditor.ID.equals(desc.getId())) {
                        IDE.setDefaultEditor(file, CommonXmlEditor.ID);
                    }
                }
            };
            job.setPriority(Job.BUILD);
            job.schedule();
        } catch (CoreException e) {
            AdtPlugin.log(e, null);
        }
    }

    /**
     * Tries to fix all currently open Android legacy editors.
     * <p/>
     * If an editor is found to match one of the legacy ids, we'll try to close it.
     * If that succeeds, we try to reopen it using the new common editor ID.
     * <p/>
     * This method must be run from the UI thread.
     */
    private void fixOpenLegacyEditors() {

        AdtPlugin adt = AdtPlugin.getDefault();
        if (adt == null) {
            return;
        }

        final IPreferenceStore store = adt.getPreferenceStore();
        int currentValue = store.getInt(AdtPrefs.PREFS_FIX_LEGACY_EDITORS);
        // The target version we're comparing to. This must be incremented each time
        // we change the processing here so that a new version of the plugin would
        // try to fix existing editors.
        final int targetValue = 1;

        if (currentValue >= targetValue) {
            return;
        }

        // To be able to close and open editors we need to make sure this is done
        // in the UI thread, which this isn't invoked from.
        PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
            @Override
            public void run() {
                HashSet<String> legacyIds =
                    new HashSet<String>(Arrays.asList(CommonXmlEditor.LEGACY_EDITOR_IDS));

                for (IWorkbenchWindow win : PlatformUI.getWorkbench().getWorkbenchWindows()) {
                    for (IWorkbenchPage page : win.getPages()) {
                        for (IEditorReference ref : page.getEditorReferences()) {
                            try {
                                IEditorInput input = ref.getEditorInput();
                                if (input instanceof IFileEditorInput) {
                                    IFile file = ((IFileEditorInput)input).getFile();
                                    IEditorPart part = ref.getEditor(true /*restore*/);
                                    if (part != null) {
                                        IWorkbenchPartSite site = part.getSite();
                                        if (site != null) {
                                            String id = site.getId();
                                            if (legacyIds.contains(id)) {
                                                // This editor matches one of legacy editor IDs.
                                                fixEditor(page, part, input, file, id);
                                            }
                                        }
                                    }
                                }
                            } catch (Exception e) {
                                // ignore
                            }
                        }
                    }
                }

                // Remember that we managed to do fix all editors
                store.setValue(AdtPrefs.PREFS_FIX_LEGACY_EDITORS, targetValue);
            }

            private void fixEditor(
                    IWorkbenchPage page,
                    IEditorPart part,
                    IEditorInput input,
                    IFile file,
                    String id) {
                IDE.setDefaultEditor(file, CommonXmlEditor.ID);

                boolean ok = page.closeEditor(part, true /*save*/);

                AdtPlugin.log(IStatus.INFO,
                    "Closed legacy editor ID %s for %s: %s", //$NON-NLS-1$
                    id,
                    file.getFullPath(),
                    ok ? "Success" : "Failed");//$NON-NLS-1$ //$NON-NLS-2$

                if (ok) {
                    // Try to reopen it with the new ID
                    try {
                        page.openEditor(input, CommonXmlEditor.ID);
                    } catch (PartInitException e) {
                        AdtPlugin.log(e,
                            "Failed to reopen %s",          //$NON-NLS-1$
                            file.getFullPath());
                    }
                }
            }
        });
    }
}
