/*
 * Copyright (C) 2007 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;

import static com.android.SdkConstants.CURRENT_PLATFORM;
import static com.android.SdkConstants.PLATFORM_DARWIN;
import static com.android.SdkConstants.PLATFORM_LINUX;
import static com.android.SdkConstants.PLATFORM_WINDOWS;

import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ide.common.resources.ResourceFile;
import com.android.ide.common.sdk.LoadStatus;
import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler.Solution;
import com.android.ide.eclipse.adt.internal.VersionCheck;
import com.android.ide.eclipse.adt.internal.actions.SdkManagerAction;
import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
import com.android.ide.eclipse.adt.internal.editors.IconFactory;
import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.IncludeFinder;
import com.android.ide.eclipse.adt.internal.lint.LintDeltaProcessor;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs.BuildVerbosity;
import com.android.ide.eclipse.adt.internal.project.AndroidClasspathContainerInitializer;
import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
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.ResourceManager;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.ide.eclipse.adt.internal.sdk.Sdk.ITargetChangeListener;
import com.android.ide.eclipse.adt.internal.ui.EclipseUiHelper;
import com.android.ide.eclipse.ddms.DdmsPlugin;
import com.android.io.StreamException;
import com.android.resources.ResourceFolderType;
import com.android.sdklib.IAndroidTarget;
import com.android.utils.ILogger;
import com.google.common.collect.Sets;
import com.google.common.io.Closeables;

import org.eclipse.core.commands.Command;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IWorkspace;
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.SubMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.browser.IWebBrowser;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IConsoleConstants;
import org.eclipse.ui.console.MessageConsole;
import org.eclipse.ui.console.MessageConsoleStream;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.texteditor.AbstractTextEditor;
import org.eclipse.wb.internal.core.DesignerPlugin;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

/**
 * The activator class controls the plug-in life cycle
 */
public class AdtPlugin extends AbstractUIPlugin implements ILogger {
    /** The plug-in ID */
    public static final String PLUGIN_ID = "com.android.ide.eclipse.adt"; //$NON-NLS-1$

    /** singleton instance */
    private static AdtPlugin sPlugin;

    private static Image sAndroidLogo;
    private static ImageDescriptor sAndroidLogoDesc;

    /** The global android console */
    private MessageConsole mAndroidConsole;

    /** Stream to write in the android console */
    private MessageConsoleStream mAndroidConsoleStream;

    /** Stream to write error messages to the android console */
    private MessageConsoleStream mAndroidConsoleErrorStream;

    /** Color used in the error console */
    private Color mRed;

    /** Load status of the SDK. Any access MUST be in a synchronized(mPostLoadProjects) block */
    private LoadStatus mSdkLoadedStatus = LoadStatus.LOADING;
    /** Project to update once the SDK is loaded.
     * Any access MUST be in a synchronized(mPostLoadProjectsToResolve) block */
    private final Set<IJavaProject> mPostLoadProjectsToResolve = Sets.newHashSet();
    /** Project to check validity of cache vs actual once the SDK is loaded.
     * Any access MUST be in a synchronized(mPostLoadProjectsToResolve) block */
    private final ArrayList<IJavaProject> mPostLoadProjectsToCheck = new ArrayList<IJavaProject>();

    private GlobalProjectMonitor mResourceMonitor;
    private ArrayList<ITargetChangeListener> mTargetChangeListeners =
            new ArrayList<ITargetChangeListener>();

    /**
     * This variable indicates that the job inside parseSdkContent() is currently
     * trying to load the SDK, to avoid re-entrance.
     * To check whether this succeeds or not, please see {@link #getSdkLoadStatus()}.
     */
    private volatile boolean mParseSdkContentIsRunning;

    /**
     * An error handler for checkSdkLocationAndId() that will handle the generated error
     * or warning message. Each method must return a boolean that will in turn be returned by
     * checkSdkLocationAndId.
     */
    public static abstract class CheckSdkErrorHandler {

        public enum Solution {
            NONE,
            OPEN_SDK_MANAGER,
            OPEN_ANDROID_PREFS,
            OPEN_P2_UPDATE
        }

        /**
         * Handle an error message during sdk location check. Returns whatever
         * checkSdkLocationAndId() should returns.
         */
        public abstract boolean handleError(Solution solution, String message);

        /**
         * Handle a warning message during sdk location check. Returns whatever
         * checkSdkLocationAndId() should returns.
         */
        public abstract boolean handleWarning(Solution solution, String message);
    }

    /**
     * The constructor
     */
    public AdtPlugin() {
        sPlugin = this;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
     */
    @Override
    public void start(BundleContext context) throws Exception {
        super.start(context);

        // set the default android console.
        mAndroidConsole = new MessageConsole("Android", null); //$NON-NLS-1$
        ConsolePlugin.getDefault().getConsoleManager().addConsoles(
                new IConsole[] { mAndroidConsole });

        // get the stream to write in the android console.
        mAndroidConsoleStream = mAndroidConsole.newMessageStream();
        mAndroidConsoleErrorStream = mAndroidConsole.newMessageStream();

        // get the eclipse store
        IPreferenceStore eclipseStore = getPreferenceStore();
        AdtPrefs.init(eclipseStore);

        // set the listener for the preference change
        eclipseStore.addPropertyChangeListener(new IPropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent event) {
                // load the new preferences
                AdtPrefs.getPrefs().loadValues(event);

                // if the SDK changed, we have to do some extra work
                if (AdtPrefs.PREFS_SDK_DIR.equals(event.getProperty())) {

                    // finally restart adb, in case it's a different version
                    DdmsPlugin.setToolsLocation(getOsAbsoluteAdb(), true /* startAdb */,
                            getOsAbsoluteHprofConv(), getOsAbsoluteTraceview());

                    // get the SDK location and build id.
                    if (checkSdkLocationAndId()) {
                        // if sdk if valid, reparse it

                        reparseSdk();
                    }
                }
            }
        });

        // load preferences.
        AdtPrefs.getPrefs().loadValues(null /*event*/);

        // initialize property-sheet library
        DesignerPlugin.initialize(
                this,
                PLUGIN_ID,
                CURRENT_PLATFORM == PLATFORM_WINDOWS,
                CURRENT_PLATFORM == PLATFORM_DARWIN,
                CURRENT_PLATFORM == PLATFORM_LINUX);

        // initialize editors
        startEditors();

        // Listen on resource file edits for updates to file inclusion
        IncludeFinder.start();
    }

    /*
     * (non-Javadoc)
     *
     * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
     */
    @Override
    public void stop(BundleContext context) throws Exception {
        super.stop(context);

        stopEditors();
        IncludeFinder.stop();

        DesignerPlugin.dispose();

        if (mRed != null) {
            mRed.dispose();
            mRed = null;
        }

        synchronized (AdtPlugin.class) {
            sPlugin = null;
        }
    }

    /** Called when the workbench has been started */
    public void workbenchStarted() {
        // Parse the SDK content.
        // This is deferred in separate jobs to avoid blocking the bundle start.
        final boolean isSdkLocationValid = checkSdkLocationAndId();
        if (isSdkLocationValid) {
            // parse the SDK resources.
            // Wait 2 seconds before starting the job. This leaves some time to the
            // other bundles to initialize.
            parseSdkContent(2000 /*milliseconds*/);
        }

        Display display = getDisplay();
        mRed = new Color(display, 0xFF, 0x00, 0x00);

        // because this can be run, in some cases, by a non ui thread, and because
        // changing the console properties update the ui, we need to make this change
        // in the ui thread.
        display.asyncExec(new Runnable() {
            @Override
            public void run() {
                mAndroidConsoleErrorStream.setColor(mRed);
            }
        });
    }

    /**
     * Returns the shared instance
     *
     * @return the shared instance
     */
    public static synchronized AdtPlugin getDefault() {
        return sPlugin;
    }

    /**
     * Returns the current display, if any
     *
     * @return the display
     */
    @NonNull
    public static Display getDisplay() {
        synchronized (AdtPlugin.class) {
            if (sPlugin != null) {
                IWorkbench bench = sPlugin.getWorkbench();
                if (bench != null) {
                    Display display = bench.getDisplay();
                    if (display != null) {
                        return display;
                    }
                }
            }
        }

        Display display = Display.getCurrent();
        if (display != null) {
            return display;
        }

        return Display.getDefault();
    }

    /**
     * Returns the shell, if any
     *
     * @return the shell, if any
     */
    @Nullable
    public static Shell getShell() {
        Display display = AdtPlugin.getDisplay();
        Shell shell = display.getActiveShell();
        if (shell == null) {
            Shell[] shells = display.getShells();
            if (shells.length > 0) {
                shell = shells[0];
            }
        }

        return shell;
    }

    /** Returns the adb path relative to the sdk folder */
    public static String getOsRelativeAdb() {
        return SdkConstants.OS_SDK_PLATFORM_TOOLS_FOLDER + SdkConstants.FN_ADB;
    }

    /** Returns the emulator path relative to the sdk folder */
    public static String getOsRelativeEmulator() {
        return SdkConstants.OS_SDK_TOOLS_FOLDER + SdkConstants.FN_EMULATOR;
    }

    /** Returns the adb path relative to the sdk folder */
    public static String getOsRelativeProguard() {
        return SdkConstants.OS_SDK_TOOLS_PROGUARD_BIN_FOLDER + SdkConstants.FN_PROGUARD;
    }

    /** Returns the absolute adb path */
    public static String getOsAbsoluteAdb() {
        return getOsSdkFolder() + getOsRelativeAdb();
    }

    /** Returns the absolute traceview path */
    public static String getOsAbsoluteTraceview() {
        return getOsSdkFolder() + SdkConstants.OS_SDK_TOOLS_FOLDER +
                AdtConstants.FN_TRACEVIEW;
    }

    /** Returns the absolute emulator path */
    public static String getOsAbsoluteEmulator() {
        return getOsSdkFolder() + getOsRelativeEmulator();
    }

    public static String getOsAbsoluteHprofConv() {
        return getOsSdkFolder() + SdkConstants.OS_SDK_PLATFORM_TOOLS_FOLDER +
                AdtConstants.FN_HPROF_CONV;
    }

    /** Returns the absolute proguard path */
    public static String getOsAbsoluteProguard() {
        return getOsSdkFolder() + getOsRelativeProguard();
    }

    /**
     * Returns a Url file path to the javaDoc folder.
     */
    public static String getUrlDoc() {
        return ProjectHelper.getJavaDocPath(
                getOsSdkFolder() + AdtConstants.WS_JAVADOC_FOLDER_LEAF);
    }

    /**
     * Returns the SDK folder.
     * Guaranteed to be terminated by a platform-specific path separator.
     */
    public static synchronized String getOsSdkFolder() {
        if (sPlugin == null) {
            return null;
        }

        return AdtPrefs.getPrefs().getOsSdkFolder();
    }

    public static String getOsSdkToolsFolder() {
        return getOsSdkFolder() + SdkConstants.OS_SDK_TOOLS_FOLDER;
    }

    /**
     * Returns an image descriptor for the image file at the given
     * plug-in relative path
     *
     * @param path the path
     * @return the image descriptor
     */
    public static ImageDescriptor getImageDescriptor(String path) {
        return imageDescriptorFromPlugin(PLUGIN_ID, path);
    }

    /**
     * Reads the contents of an {@link IFile} and return it as a String
     *
     * @param file the file to be read
     * @return the String read from the file, or null if there was an error
     */
    @SuppressWarnings("resource") // Eclipse doesn't understand Closeables.closeQuietly yet
    @Nullable
    public static String readFile(@NonNull IFile file) {
        InputStream contents = null;
        InputStreamReader reader = null;
        try {
            contents = file.getContents();
            String charset = file.getCharset();
            reader = new InputStreamReader(contents, charset);
            return readFile(reader);
        } catch (CoreException e) {
            // pass -- ignore files we can't read
        } catch (IOException e) {
            // pass -- ignore files we can't read.

            // Note that IFile.getContents() indicates it throws a CoreException but
            // experience shows that if the file does not exists it really throws
            // IOException.
            // New InputStreamReader() throws UnsupportedEncodingException
            // which is handled by this IOException catch.

        } finally {
            Closeables.closeQuietly(reader);
            Closeables.closeQuietly(contents);
        }

        return null;
    }

    /**
     * Reads the contents of an {@link File} and return it as a String
     *
     * @param file the file to be read
     * @return the String read from the file, or null if there was an error
     */
    public static String readFile(File file) {
        try {
            return readFile(new FileReader(file));
        } catch (FileNotFoundException e) {
            AdtPlugin.log(e, "Can't read file %1$s", file); //$NON-NLS-1$
        }

        return null;
    }

    /**
     * Writes the given content out to the given {@link File}. The file will be deleted if
     * it already exists.
     *
     * @param file the target file
     * @param content the content to be written into the file
     */
    public static void writeFile(File file, String content) {
        if (file.exists()) {
            file.delete();
        }
        FileWriter fw = null;
        try {
            fw = new FileWriter(file);
            fw.write(content);
        } catch (IOException e) {
            AdtPlugin.log(e, null);
        } finally {
            if (fw != null) {
                try {
                    fw.close();
                } catch (IOException e) {
                    AdtPlugin.log(e, null);
                }
            }
        }
    }

    /**
     * Returns true iff the given file contains the given String.
     *
     * @param file the file to look for the string in
     * @param string the string to be searched for
     * @return true if the file is found and contains the given string anywhere within it
     */
    @SuppressWarnings("resource") // Closed by streamContains
    public static boolean fileContains(IFile file, String string) {
        InputStream contents = null;
        try {
            contents = file.getContents();
            String charset = file.getCharset();
            return streamContains(new InputStreamReader(contents, charset), string);
        } catch (Exception e) {
            AdtPlugin.log(e, "Can't read file %1$s", file); //$NON-NLS-1$
        }

        return false;
    }

    /**
     * Returns true iff the given file contains the given String.
     *
     * @param file the file to look for the string in
     * @param string the string to be searched for
     * @return true if the file is found and contains the given string anywhere within it
     */
    public static boolean fileContains(File file, String string) {
        try {
            return streamContains(new FileReader(file), string);
        } catch (Exception e) {
            AdtPlugin.log(e, "Can't read file %1$s", file); //$NON-NLS-1$
        }

        return false;
    }

    /**
     * Returns true iff the given input stream contains the given String.
     *
     * @param r the stream to look for the string in
     * @param string the string to be searched for
     * @return true if the file is found and contains the given string anywhere within it
     */
    public static boolean streamContains(Reader r, String string) {
        if (string.length() == 0) {
            return true;
        }

        PushbackReader reader = null;
        try {
            reader = new PushbackReader(r, string.length());
            char first = string.charAt(0);
            while (true) {
                int c = reader.read();
                if (c == -1) {
                    return false;
                } else if (c == first) {
                    boolean matches = true;
                    for (int i = 1; i < string.length(); i++) {
                        c = reader.read();
                        if (c == -1) {
                            return false;
                        } else if (string.charAt(i) != (char)c) {
                            matches = false;
                            // Back up the characters that did not match
                            reader.backup(i-1);
                            break;
                        }
                    }
                    if (matches) {
                        return true;
                    }
                }
            }
        } catch (Exception e) {
            AdtPlugin.log(e, "Can't read stream"); //$NON-NLS-1$
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                AdtPlugin.log(e, "Can't read stream"); //$NON-NLS-1$
            }
        }

        return false;

    }

    /**
     * A special reader that allows backing up in the input (up to a predefined maximum
     * number of characters)
     * <p>
     * NOTE: This class ONLY works with the {@link #read()} method!!
     */
    private static class PushbackReader extends BufferedReader {
        /**
         * Rolling/circular buffer. Can be a char rather than int since we never store EOF
         * in it.
         */
        private char[] mStorage;

        /** Points to the head of the queue. When equal to the tail, the queue is empty. */
        private int mHead;

        /**
         * Points to the tail of the queue. This will move with each read of the actual
         * wrapped reader, and the characters previous to it in the circular buffer are
         * the most recently read characters.
         */
        private int mTail;

        /**
         * Creates a new reader with a given maximum number of backup characters
         *
         * @param reader the reader to wrap
         * @param max the maximum number of characters to allow rollback for
         */
        public PushbackReader(Reader reader, int max) {
            super(reader);
            mStorage = new char[max + 1];
        }

        @Override
        public int read() throws IOException {
            // Have we backed up? If so we should serve characters
            // from the storage
            if (mHead != mTail) {
                char c = mStorage[mHead];
                mHead = (mHead + 1) % mStorage.length;
                return c;
            }
            assert mHead == mTail;

            // No backup -- read the next character, but stash it into storage
            // as well such that we can retrieve it if we must.
            int c = super.read();
            mStorage[mHead] = (char) c;
            mHead = mTail = (mHead + 1) % mStorage.length;
            return c;
        }

        /**
         * Backs up the reader a given number of characters. The next N reads will yield
         * the N most recently read characters prior to this backup.
         *
         * @param n the number of characters to be backed up
         */
        public void backup(int n) {
            if (n >= mStorage.length) {
                throw new IllegalArgumentException("Exceeded backup limit");
            }
            assert n < mStorage.length;
            mHead -= n;
            if (mHead < 0) {
                mHead += mStorage.length;
            }
        }
    }

    /**
     * Reads the contents of a {@link ResourceFile} and returns it as a String
     *
     * @param file the file to be read
     * @return the contents as a String, or null if reading failed
     */
    public static String readFile(ResourceFile file) {
        InputStream contents = null;
        try {
            contents = file.getFile().getContents();
            return readFile(new InputStreamReader(contents));
        } catch (StreamException e) {
            // pass -- ignore files we can't read
        } finally {
            try {
                if (contents != null) {
                    contents.close();
                }
            } catch (IOException e) {
                AdtPlugin.log(e, "Can't read layout file"); //$NON-NLS-1$
            }
        }

        return null;
    }

    /**
     * Reads the contents of a {@link Reader} and return it as a String. This
     * method will close the input reader.
     *
     * @param reader the reader to be read from
     * @return the String read from reader, or null if there was an error
     */
    public static String readFile(Reader reader) {
        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader(reader);
            StringBuilder sb = new StringBuilder(2000);
            while (true) {
                int c = bufferedReader.read();
                if (c == -1) {
                    return sb.toString();
                } else {
                    sb.append((char)c);
                }
            }
        } catch (IOException e) {
            // pass -- ignore files we can't read
        } finally {
            try {
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
            } catch (IOException e) {
                AdtPlugin.log(e, "Can't read input stream"); //$NON-NLS-1$
            }
        }

        return null;
    }

    /**
     * Reads and returns the content of a text file embedded in the plugin jar
     * file.
     * @param filepath the file path to the text file
     * @return null if the file could not be read
     */
    public static String readEmbeddedTextFile(String filepath) {
        try {
            InputStream is = readEmbeddedFileAsStream(filepath);
            if (is != null) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(is));
                try {
                    String line;
                    StringBuilder total = new StringBuilder(reader.readLine());
                    while ((line = reader.readLine()) != null) {
                        total.append('\n');
                        total.append(line);
                    }

                    return total.toString();
                } finally {
                    reader.close();
                }
            }
        } catch (IOException e) {
            // we'll just return null
            AdtPlugin.log(e, "Failed to read text file '%s'", filepath);  //$NON-NLS-1$
        }

        return null;
    }

    /**
     * Reads and returns the content of a binary file embedded in the plugin jar
     * file.
     * @param filepath the file path to the text file
     * @return null if the file could not be read
     */
    public static byte[] readEmbeddedFile(String filepath) {
        try {
            InputStream is = readEmbeddedFileAsStream(filepath);
            if (is != null) {
                // create a buffered reader to facilitate reading.
                BufferedInputStream stream = new BufferedInputStream(is);
                try {
                    // get the size to read.
                    int avail = stream.available();

                    // create the buffer and reads it.
                    byte[] buffer = new byte[avail];
                    stream.read(buffer);

                    // and return.
                    return buffer;
                } finally {
                    stream.close();
                }
            }
        } catch (IOException e) {
            // we'll just return null;.
            AdtPlugin.log(e, "Failed to read binary file '%s'", filepath);  //$NON-NLS-1$
        }

        return null;
    }

    /**
     * Reads and returns the content of a binary file embedded in the plugin jar
     * file.
     * @param filepath the file path to the text file
     * @return null if the file could not be read
     */
    public static InputStream readEmbeddedFileAsStream(String filepath) {
        // attempt to read an embedded file
        try {
            URL url = getEmbeddedFileUrl(AdtConstants.WS_SEP + filepath);
            if (url != null) {
                return url.openStream();
            }
        } catch (MalformedURLException e) {
            // we'll just return null.
            AdtPlugin.log(e, "Failed to read stream '%s'", filepath);  //$NON-NLS-1$
        } catch (IOException e) {
            // we'll just return null;.
            AdtPlugin.log(e, "Failed to read stream '%s'", filepath);  //$NON-NLS-1$
        }

        return null;
    }

    /**
     * Returns the URL of a binary file embedded in the plugin jar file.
     * @param filepath the file path to the text file
     * @return null if the file was not found.
     */
    public static URL getEmbeddedFileUrl(String filepath) {
        Bundle bundle = null;
        synchronized (AdtPlugin.class) {
            if (sPlugin != null) {
                bundle = sPlugin.getBundle();
            } else {
                AdtPlugin.log(IStatus.WARNING, "ADT Plugin is missing");    //$NON-NLS-1$
                return null;
            }
        }

        // attempt to get a file to one of the template.
        String path = filepath;
        if (!path.startsWith(AdtConstants.WS_SEP)) {
            path = AdtConstants.WS_SEP + path;
        }

        URL url = bundle.getEntry(path);

        if (url == null) {
            AdtPlugin.log(IStatus.INFO, "Bundle file URL not found at path '%s'", path); //$NON-NLS-1$
        }

        return url;
    }

    /**
     * Displays an error dialog box. This dialog box is ran asynchronously in the ui thread,
     * therefore this method can be called from any thread.
     * @param title The title of the dialog box
     * @param message The error message
     */
    public final static void displayError(final String title, final String message) {
        // get the current Display
        final Display display = getDisplay();

        // dialog box only run in ui thread..
        display.asyncExec(new Runnable() {
            @Override
            public void run() {
                Shell shell = display.getActiveShell();
                MessageDialog.openError(shell, title, message);
            }
        });
    }

    /**
     * Displays a warning dialog box. This dialog box is ran asynchronously in the ui thread,
     * therefore this method can be called from any thread.
     * @param title The title of the dialog box
     * @param message The warning message
     */
    public final static void displayWarning(final String title, final String message) {
        // get the current Display
        final Display display = getDisplay();

        // dialog box only run in ui thread..
        display.asyncExec(new Runnable() {
            @Override
            public void run() {
                Shell shell = display.getActiveShell();
                MessageDialog.openWarning(shell, title, message);
            }
        });
    }

    /**
     * Display a yes/no question dialog box. This dialog is opened synchronously in the ui thread,
     * therefore this message can be called from any thread.
     * @param title The title of the dialog box
     * @param message The error message
     * @return true if OK was clicked.
     */
    public final static boolean displayPrompt(final String title, final String message) {
        // get the current Display and Shell
        final Display display = getDisplay();

        // we need to ask the user what he wants to do.
        final boolean[] result = new boolean[1];
        display.syncExec(new Runnable() {
            @Override
            public void run() {
                Shell shell = display.getActiveShell();
                result[0] = MessageDialog.openQuestion(shell, title, message);
            }
        });
        return result[0];
    }

    /**
     * Logs a message to the default Eclipse log.
     *
     * @param severity The severity code. Valid values are: {@link IStatus#OK},
     * {@link IStatus#ERROR}, {@link IStatus#INFO}, {@link IStatus#WARNING} or
     * {@link IStatus#CANCEL}.
     * @param format The format string, like for {@link String#format(String, Object...)}.
     * @param args The arguments for the format string, like for
     * {@link String#format(String, Object...)}.
     */
    public static void log(int severity, String format, Object ... args) {
        if (format == null) {
            return;
        }

        String message = String.format(format, args);
        Status status = new Status(severity, PLUGIN_ID, message);

        if (getDefault() != null) {
            getDefault().getLog().log(status);
        } else {
            // During UnitTests, we generally don't have a plugin object. It's ok
            // to log to stdout or stderr in this case.
            (severity < IStatus.ERROR ? System.out : System.err).println(status.toString());
        }
    }

    /**
     * Logs an exception to the default Eclipse log.
     * <p/>
     * The status severity is always set to ERROR.
     *
     * @param exception the exception to log.
     * @param format The format string, like for {@link String#format(String, Object...)}.
     * @param args The arguments for the format string, like for
     * {@link String#format(String, Object...)}.
     */
    public static void log(Throwable exception, String format, Object ... args) {
        String message = null;
        if (format != null) {
            message = String.format(format, args);
        } else {
            message = "";
        }
        Status status = new Status(IStatus.ERROR, PLUGIN_ID, message, exception);

        if (getDefault() != null) {
            getDefault().getLog().log(status);
        } else {
            // During UnitTests, we generally don't have a plugin object. It's ok
            // to log to stderr in this case.
            System.err.println(status.toString());
        }
    }

    /**
     * This is a mix between log(Throwable) and printErrorToConsole.
     * <p/>
     * This logs the exception with an ERROR severity and the given printf-like format message.
     * The same message is then printed on the Android error console with the associated tag.
     *
     * @param exception the exception to log.
     * @param format The format string, like for {@link String#format(String, Object...)}.
     * @param args The arguments for the format string, like for
     * {@link String#format(String, Object...)}.
     */
    public static synchronized void logAndPrintError(Throwable exception, String tag,
            String format, Object ... args) {
        if (sPlugin != null) {
            String message = String.format(format, args);
            Status status = new Status(IStatus.ERROR, PLUGIN_ID, message, exception);
            getDefault().getLog().log(status);
            printToStream(sPlugin.mAndroidConsoleErrorStream, tag, message);
            showAndroidConsole();
        }
    }

    /**
     * Prints one or more error message to the android console.
     * @param tag A tag to be associated with the message. Can be null.
     * @param objects the objects to print through their <code>toString</code> method.
     */
    public static synchronized void printErrorToConsole(String tag, Object... objects) {
        if (sPlugin != null) {
            printToStream(sPlugin.mAndroidConsoleErrorStream, tag, objects);

            showAndroidConsole();
        }
    }

    /**
     * Prints one or more error message to the android console.
     * @param objects the objects to print through their <code>toString</code> method.
     */
    public static void printErrorToConsole(Object... objects) {
        printErrorToConsole((String)null, objects);
    }

    /**
     * Prints one or more error message to the android console.
     * @param project The project to which the message is associated. Can be null.
     * @param objects the objects to print through their <code>toString</code> method.
     */
    public static void printErrorToConsole(IProject project, Object... objects) {
        String tag = project != null ? project.getName() : null;
        printErrorToConsole(tag, objects);
    }

    /**
     * Prints one or more build messages to the android console, filtered by Build output verbosity.
     * @param level {@link BuildVerbosity} level of the message.
     * @param project The project to which the message is associated. Can be null.
     * @param objects the objects to print through their <code>toString</code> method.
     * @see BuildVerbosity#ALWAYS
     * @see BuildVerbosity#NORMAL
     * @see BuildVerbosity#VERBOSE
     */
    public static synchronized void printBuildToConsole(BuildVerbosity level, IProject project,
            Object... objects) {
        if (sPlugin != null) {
            if (level.getLevel() <= AdtPrefs.getPrefs().getBuildVerbosity().getLevel()) {
                String tag = project != null ? project.getName() : null;
                printToStream(sPlugin.mAndroidConsoleStream, tag, objects);
            }
        }
    }

    /**
     * Prints one or more message to the android console.
     * @param tag The tag to be associated with the message. Can be null.
     * @param objects the objects to print through their <code>toString</code> method.
     */
    public static synchronized void printToConsole(String tag, Object... objects) {
        if (sPlugin != null) {
            printToStream(sPlugin.mAndroidConsoleStream, tag, objects);
        }
    }

    /**
     * Prints one or more message to the android console.
     * @param project The project to which the message is associated. Can be null.
     * @param objects the objects to print through their <code>toString</code> method.
     */
    public static void printToConsole(IProject project, Object... objects) {
        String tag = project != null ? project.getName() : null;
        printToConsole(tag, objects);
    }

    /** Force the display of the android console */
    public static void showAndroidConsole() {
        // first make sure the console is in the workbench
        EclipseUiHelper.showView(IConsoleConstants.ID_CONSOLE_VIEW, true);

        // now make sure it's not docked.
        ConsolePlugin.getDefault().getConsoleManager().showConsoleView(
                AdtPlugin.getDefault().getAndroidConsole());
    }

    /**
     * Returns whether the {@link IAndroidTarget}s have been loaded from the SDK.
     */
    public final LoadStatus getSdkLoadStatus() {
        synchronized (Sdk.getLock()) {
            return mSdkLoadedStatus;
        }
    }

    /**
     * Sets the given {@link IJavaProject} to have its target resolved again once the SDK finishes
     * to load.
     */
    public final void setProjectToResolve(IJavaProject javaProject) {
        synchronized (Sdk.getLock()) {
            mPostLoadProjectsToResolve.add(javaProject);
        }
    }

    /**
     * Sets the given {@link IJavaProject} to have its target checked for consistency
     * once the SDK finishes to load. This is used if the target is resolved using cached
     * information while the SDK is loading.
     */
    public final void setProjectToCheck(IJavaProject javaProject) {
        // only lock on
        synchronized (Sdk.getLock()) {
            mPostLoadProjectsToCheck.add(javaProject);
        }
    }

    /**
     * Checks the location of the SDK in the prefs is valid.
     * If it is not, display a warning dialog to the user and try to display
     * some useful link to fix the situation (setup the preferences, perform an
     * update, etc.)
     *
     * @return True if the SDK location points to an SDK.
     *  If false, the user has already been presented with a modal dialog explaining that.
     */
    public boolean checkSdkLocationAndId() {
        String sdkLocation = AdtPrefs.getPrefs().getOsSdkFolder();

        return checkSdkLocationAndId(sdkLocation, new CheckSdkErrorHandler() {
            private String mTitle = "Android SDK";

            /**
             * Handle an error, which is the case where the check did not find any SDK.
             * This returns false to {@link AdtPlugin#checkSdkLocationAndId()}.
             */
            @Override
            public boolean handleError(Solution solution, String message) {
                displayMessage(solution, message, MessageDialog.ERROR);
                return false;
            }

            /**
             * Handle an warning, which is the case where the check found an SDK
             * but it might need to be repaired or is missing an expected component.
             *
             * This returns true to {@link AdtPlugin#checkSdkLocationAndId()}.
             */
            @Override
            public boolean handleWarning(Solution solution, String message) {
                displayMessage(solution, message, MessageDialog.WARNING);
                return true;
            }

            private void displayMessage(
                    final Solution solution,
                    final String message,
                    final int dialogImageType) {
                final Display disp = getDisplay();
                disp.asyncExec(new Runnable() {
                    @Override
                    public void run() {
                        Shell shell = disp.getActiveShell();
                        if (shell == null) {
                            shell = AdtPlugin.getShell();
                        }
                        if (shell == null) {
                            return;
                        }

                        String customLabel = null;
                        switch(solution) {
                        case OPEN_ANDROID_PREFS:
                            customLabel = "Open Preferences";
                            break;
                        case OPEN_P2_UPDATE:
                            customLabel = "Check for Updates";
                            break;
                        case OPEN_SDK_MANAGER:
                            customLabel = "Open SDK Manager";
                            break;
                        }

                        String btnLabels[] = new String[customLabel == null ? 1 : 2];
                        btnLabels[0] = customLabel;
                        btnLabels[btnLabels.length - 1] = IDialogConstants.CLOSE_LABEL;

                        MessageDialog dialog = new MessageDialog(
                                shell, // parent
                                mTitle,
                                null, // dialogTitleImage
                                message,
                                dialogImageType,
                                btnLabels,
                                btnLabels.length - 1);
                        int index = dialog.open();

                        if (customLabel != null && index == 0) {
                            switch(solution) {
                            case OPEN_ANDROID_PREFS:
                                openAndroidPrefs();
                                break;
                            case OPEN_P2_UPDATE:
                                openP2Update();
                                break;
                            case OPEN_SDK_MANAGER:
                                openSdkManager();
                                break;
                            }
                        }
                    }
                });
            }

            private void openSdkManager() {
                // Open the standalone external SDK Manager since we know
                // that ADT on Windows is bound to be locking some SDK folders.
                //
                // Also when this is invoked because SdkManagerAction.run() fails, this
                // test will fail and we'll fallback on using the internal one.
                if (SdkManagerAction.openExternalSdkManager()) {
                    return;
                }

                // Otherwise open the regular SDK Manager bundled within ADT
                if (!SdkManagerAction.openAdtSdkManager()) {
                    // We failed because the SDK location is undefined. In this case
                    // let's open the preferences instead.
                    openAndroidPrefs();
                }
            }

            private void openP2Update() {
                Display disp = getDisplay();
                if (disp == null) {
                    return;
                }
                disp.asyncExec(new Runnable() {
                    @Override
                    public void run() {
                        String cmdId = "org.eclipse.equinox.p2.ui.sdk.update";  //$NON-NLS-1$
                        IWorkbench wb = PlatformUI.getWorkbench();
                        if (wb == null) {
                            return;
                        }

                        ICommandService cs = (ICommandService) wb.getService(ICommandService.class);
                        IHandlerService is = (IHandlerService) wb.getService(IHandlerService.class);
                        if (cs == null || is == null) {
                            return;
                        }

                        Command cmd = cs.getCommand(cmdId);
                        if (cmd != null && cmd.isDefined()) {
                            try {
                                is.executeCommand(cmdId, null/*event*/);
                            } catch (Exception ignore) {
                                AdtPlugin.log(ignore, "Failed to execute command %s", cmdId);
                            }
                        }
                    }
                });
            }

            private void openAndroidPrefs() {
                PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(
                        getDisplay().getActiveShell(),
                        "com.android.ide.eclipse.preferences.main", //$NON-NLS-1$ preferencePageId
                        null,  // displayedIds
                        null); // data
                dialog.open();
            }
        });
    }

    /**
     * Internal helper to perform the actual sdk location and id check.
     * <p/>
     * This is useful for callers who want to override what happens when the check
     * fails. Otherwise consider calling {@link #checkSdkLocationAndId()} that will
     * present a modal dialog to the user in case of failure.
     *
     * @param osSdkLocation The sdk directory, an OS path. Can be null.
     * @param errorHandler An checkSdkErrorHandler that can display a warning or an error.
     * @return False if there was an error or the result from the errorHandler invocation.
     */
    public boolean checkSdkLocationAndId(@Nullable String osSdkLocation,
                                         @NonNull CheckSdkErrorHandler errorHandler) {
        if (osSdkLocation == null || osSdkLocation.trim().length() == 0) {
            return errorHandler.handleError(
                    Solution.OPEN_ANDROID_PREFS,
                    "Location of the Android SDK has not been setup in the preferences.");
        }

        if (!osSdkLocation.endsWith(File.separator)) {
            osSdkLocation = osSdkLocation + File.separator;
        }

        File osSdkFolder = new File(osSdkLocation);
        if (osSdkFolder.isDirectory() == false) {
            return errorHandler.handleError(
                    Solution.OPEN_ANDROID_PREFS,
                    String.format(Messages.Could_Not_Find_Folder, osSdkLocation));
        }

        String osTools = osSdkLocation + SdkConstants.OS_SDK_TOOLS_FOLDER;
        File toolsFolder = new File(osTools);
        if (toolsFolder.isDirectory() == false) {
            return errorHandler.handleError(
                    Solution.OPEN_ANDROID_PREFS,
                    String.format(Messages.Could_Not_Find_Folder_In_SDK,
                            SdkConstants.FD_TOOLS, osSdkLocation));
        }

        // first check the min plug-in requirement as its error message is easier to figure
        // out for the user
        if (VersionCheck.checkVersion(osSdkLocation, errorHandler) == false) {
            return false;
        }

        // check that we have both the tools component and the platform-tools component.
        String platformTools = osSdkLocation + SdkConstants.OS_SDK_PLATFORM_TOOLS_FOLDER;
        if (checkFolder(platformTools) == false) {
            return errorHandler.handleWarning(
                    Solution.OPEN_SDK_MANAGER,
                    "SDK Platform Tools component is missing!\n" +
                    "Please use the SDK Manager to install it.");
        }

        String tools = osSdkLocation + SdkConstants.OS_SDK_TOOLS_FOLDER;
        if (checkFolder(tools) == false) {
            return errorHandler.handleError(
                    Solution.OPEN_SDK_MANAGER,
                    "SDK Tools component is missing!\n" +
                    "Please use the SDK Manager to install it.");
        }

        // check the path to various tools we use to make sure nothing is missing. This is
        // not meant to be exhaustive.
        String[] filesToCheck = new String[] {
                osSdkLocation + getOsRelativeAdb(),
                osSdkLocation + getOsRelativeEmulator()
        };
        for (String file : filesToCheck) {
            if (checkFile(file) == false) {
                return errorHandler.handleError(
                        Solution.OPEN_ANDROID_PREFS,
                        String.format(Messages.Could_Not_Find, file));
            }
        }

        return true;
    }

    /**
     * Checks if a path reference a valid existing file.
     * @param osPath the os path to check.
     * @return true if the file exists and is, in fact, a file.
     */
    private boolean checkFile(String osPath) {
        File file = new File(osPath);
        if (file.isFile() == false) {
            return false;
        }

        return true;
    }

    /**
     * Checks if a path reference a valid existing folder.
     * @param osPath the os path to check.
     * @return true if the folder exists and is, in fact, a folder.
     */
    private boolean checkFolder(String osPath) {
        File file = new File(osPath);
        if (file.isDirectory() == false) {
            return false;
        }

        return true;
    }

    /**
     * Parses the SDK resources.
     */
    private void parseSdkContent(long delay) {
        // Perform the update in a thread (here an Eclipse runtime job)
        // since this should never block the caller (especially the start method)
        Job job = new Job(Messages.AdtPlugin_Android_SDK_Content_Loader) {
            @SuppressWarnings("unchecked")
            @Override
            protected IStatus run(IProgressMonitor monitor) {
                try {

                    if (mParseSdkContentIsRunning) {
                        return new Status(IStatus.WARNING, PLUGIN_ID,
                                "An Android SDK is already being loaded. Please try again later.");
                    }

                    mParseSdkContentIsRunning = true;

                    SubMonitor progress = SubMonitor.convert(monitor,
                            "Initialize SDK Manager", 100);

                    Sdk sdk = Sdk.loadSdk(AdtPrefs.getPrefs().getOsSdkFolder());

                    if (sdk != null) {
                        ArrayList<IJavaProject> list = new ArrayList<IJavaProject>();
                        synchronized (Sdk.getLock()) {
                            mSdkLoadedStatus = LoadStatus.LOADED;

                            progress.setTaskName("Check Projects");

                            for (IJavaProject javaProject : mPostLoadProjectsToResolve) {
                                IProject iProject = javaProject.getProject();
                                if (iProject.isOpen()) {
                                    // project that have been resolved before the sdk was loaded
                                    // will have a ProjectState where the IAndroidTarget is null
                                    // so we load the target now that the SDK is loaded.
                                    sdk.loadTargetAndBuildTools(Sdk.getProjectState(iProject));
                                    list.add(javaProject);
                                }
                            }

                            // done with this list.
                            mPostLoadProjectsToResolve.clear();
                        }

                        // check the projects that need checking.
                        // The method modifies the list (it removes the project that
                        // do not need to be resolved again).
                        AndroidClasspathContainerInitializer.checkProjectsCache(
                                mPostLoadProjectsToCheck);

                        list.addAll(mPostLoadProjectsToCheck);

                        // update the project that needs recompiling.
                        if (list.size() > 0) {
                            IJavaProject[] array = list.toArray(
                                    new IJavaProject[list.size()]);
                            ProjectHelper.updateProjects(array);
                        }

                        progress.worked(10);
                    } else {
                        // SDK failed to Load!
                        // Sdk#loadSdk() has already displayed an error.
                        synchronized (Sdk.getLock()) {
                            mSdkLoadedStatus = LoadStatus.FAILED;
                        }
                    }

                    // Notify resource changed listeners
                    progress.setTaskName("Refresh UI");
                    progress.setWorkRemaining(mTargetChangeListeners.size());

                    // Clone the list before iterating, to avoid ConcurrentModification
                    // exceptions
                    final List<ITargetChangeListener> listeners =
                        (List<ITargetChangeListener>)mTargetChangeListeners.clone();
                    final SubMonitor progress2 = progress;
                    AdtPlugin.getDisplay().asyncExec(new Runnable() {
                        @Override
                        public void run() {
                            for (ITargetChangeListener listener : listeners) {
                                try {
                                    listener.onSdkLoaded();
                                } catch (Exception e) {
                                    AdtPlugin.log(e, "Failed to update a TargetChangeListener."); //$NON-NLS-1$
                                } finally {
                                    progress2.worked(1);
                                }
                            }
                        }
                    });
                } catch (Throwable t) {
                    log(t, "Unknown exception in parseSdkContent.");    //$NON-NLS-1$
                    return new Status(IStatus.ERROR, PLUGIN_ID,
                            "parseSdkContent failed", t);               //$NON-NLS-1$

                } finally {
                    mParseSdkContentIsRunning = false;
                    if (monitor != null) {
                        monitor.done();
                    }
                }

                return Status.OK_STATUS;
            }
        };
        job.setPriority(Job.BUILD); // build jobs are run after other interactive jobs
        job.setRule(ResourcesPlugin.getWorkspace().getRoot());
        if (delay > 0) {
            job.schedule(delay);
        } else {
            job.schedule();
        }
    }

    /** Returns the global android console */
    public MessageConsole getAndroidConsole() {
        return mAndroidConsole;
    }

    // ----- Methods for Editors -------

    public void startEditors() {
        sAndroidLogoDesc = imageDescriptorFromPlugin(AdtPlugin.PLUGIN_ID,
                "/icons/android.png"); //$NON-NLS-1$
        sAndroidLogo = sAndroidLogoDesc.createImage();

        // Add a resource listener to handle compiled resources.
        IWorkspace ws = ResourcesPlugin.getWorkspace();
        mResourceMonitor = GlobalProjectMonitor.startMonitoring(ws);

        if (mResourceMonitor != null) {
            try {
                setupEditors(mResourceMonitor);
                ResourceManager.setup(mResourceMonitor);
                LintDeltaProcessor.startListening(mResourceMonitor);
            } catch (Throwable t) {
                log(t, "ResourceManager.setup failed"); //$NON-NLS-1$
            }
        }
    }

    /**
     * The <code>AbstractUIPlugin</code> implementation of this <code>Plugin</code>
     * method saves this plug-in's preference and dialog stores and shuts down
     * its image registry (if they are in use). Subclasses may extend this
     * method, but must send super <b>last</b>. A try-finally statement should
     * be used where necessary to ensure that <code>super.shutdown()</code> is
     * always done.
     *
     * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
     */
    public void stopEditors() {
        sAndroidLogo.dispose();

        IconFactory.getInstance().dispose();

        LintDeltaProcessor.stopListening(mResourceMonitor);

        // Remove the resource listener that handles compiled resources.
        IWorkspace ws = ResourcesPlugin.getWorkspace();
        GlobalProjectMonitor.stopMonitoring(ws);

        if (mRed != null) {
            mRed.dispose();
            mRed = null;
        }
    }

    /**
     * Returns an Image for the small Android logo.
     *
     * Callers should not dispose it.
     */
    public static Image getAndroidLogo() {
        return sAndroidLogo;
    }

    /**
     * Returns an {@link ImageDescriptor} for the small Android logo.
     *
     * Callers should not dispose it.
     */
    public static ImageDescriptor getAndroidLogoDesc() {
        return sAndroidLogoDesc;
    }

    /**
     * Returns the ResourceMonitor object.
     */
    public GlobalProjectMonitor getResourceMonitor() {
        return mResourceMonitor;
    }

    /**
     * Sets up the editor resource listener.
     * <p>
     * The listener handles:
     * <ul>
     * <li> Discovering newly created files, and ensuring that if they are in an Android
     *      project, they default to the right XML editor.
     * <li> Discovering deleted files, and closing the corresponding editors if necessary.
     *      This is only done for XML files, since other editors such as Java editors handles
     *      it on their own.
     * <ul>
     *
     * This is called by the {@link AdtPlugin} during initialization.
     *
     * @param monitor The main Resource Monitor object.
     */
    public void setupEditors(GlobalProjectMonitor monitor) {
        monitor.addFileListener(new IFileListener() {
            @Override
            public void fileChanged(@NonNull IFile file, @NonNull IMarkerDelta[] markerDeltas,
                    int kind, @Nullable String extension, int flags, boolean isAndroidProject) {
                if (!isAndroidProject) {
                    return;
                }
                if (flags == IResourceDelta.MARKERS || !SdkConstants.EXT_XML.equals(extension)) {
                    // ONLY the markers changed, or not XML file: not relevant to this listener
                    return;
                }

                if (kind == IResourceDelta.REMOVED) {
                    AdtUtils.closeEditors(file, false /*save*/);
                    return;
                }

                // The resources files must have a file path similar to
                //    project/res/.../*.xml
                // There is no support for sub folders, so the segment count must be 4
                if (file.getFullPath().segmentCount() == 4) {
                    // check if we are inside the res folder.
                    String segment = file.getFullPath().segment(1);
                    if (segment.equalsIgnoreCase(SdkConstants.FD_RESOURCES)) {
                        // we are inside a res/ folder, get the ResourceFolderType of the
                        // parent folder.
                        String[] folderSegments = file.getParent().getName().split(
                                SdkConstants.RES_QUALIFIER_SEP);

                        // get the enum for the resource type.
                        ResourceFolderType type = ResourceFolderType.getTypeByName(
                                folderSegments[0]);

                        if (type != null) {
                            if (kind == IResourceDelta.ADDED) {
                                // A new file {@code /res/type-config/some.xml} was added.
                                // All the /res XML files are handled by the same common editor now.
                                IDE.setDefaultEditor(file, CommonXmlEditor.ID);
                            }
                        } else {
                            // if the res folder is null, this means the name is invalid,
                            // in this case we remove whatever android editors that was set
                            // as the default editor.
                            IEditorDescriptor desc = IDE.getDefaultEditor(file);
                            String editorId = desc.getId();
                            if (editorId.startsWith(AdtConstants.EDITORS_NAMESPACE)) {
                                // reset the default editor.
                                IDE.setDefaultEditor(file, null);
                            }
                        }
                    }
                }
            }
        }, IResourceDelta.ADDED | IResourceDelta.REMOVED);

        monitor.addProjectListener(new IProjectListener() {
            @Override
            public void projectClosed(IProject project) {
                // Close any editors referencing this project
                AdtUtils.closeEditors(project, true /*save*/);
            }

            @Override
            public void projectDeleted(IProject project) {
                // Close any editors referencing this project
                AdtUtils.closeEditors(project, false /*save*/);
            }

            @Override
            public void projectOpenedWithWorkspace(IProject project) {
            }

            @Override
            public void allProjectsOpenedWithWorkspace() {
            }

            @Override
            public void projectOpened(IProject project) {
            }

            @Override
            public void projectRenamed(IProject project, IPath from) {
            }
        });
    }

    /**
     * Adds a new {@link ITargetChangeListener} to be notified when a new SDK is loaded, or when
     * a project has its target changed.
     */
    public void addTargetListener(ITargetChangeListener listener) {
        mTargetChangeListeners.add(listener);
    }

    /**
     * Removes an existing {@link ITargetChangeListener}.
     * @see #addTargetListener(ITargetChangeListener)
     */
    public void removeTargetListener(ITargetChangeListener listener) {
        mTargetChangeListeners.remove(listener);
    }

    /**
     * Updates all the {@link ITargetChangeListener}s that a target has changed for a given project.
     * <p/>Only editors related to that project should reload.
     */
    @SuppressWarnings("unchecked")
    public void updateTargetListeners(final IProject project) {
        final List<ITargetChangeListener> listeners =
            (List<ITargetChangeListener>)mTargetChangeListeners.clone();

        AdtPlugin.getDisplay().asyncExec(new Runnable() {
            @Override
            public void run() {
                for (ITargetChangeListener listener : listeners) {
                    try {
                        listener.onProjectTargetChange(project);
                    } catch (Exception e) {
                        AdtPlugin.log(e, "Failed to update a TargetChangeListener.");  //$NON-NLS-1$
                    }
                }
            }
        });
    }

    /**
     * Updates all the {@link ITargetChangeListener}s that a target data was loaded.
     * <p/>Only editors related to a project using this target should reload.
     */
    @SuppressWarnings("unchecked")
    public void updateTargetListeners(final IAndroidTarget target) {
        final List<ITargetChangeListener> listeners =
            (List<ITargetChangeListener>)mTargetChangeListeners.clone();

        Display display = AdtPlugin.getDisplay();
        if (display == null || display.isDisposed()) {
            return;
        }
        display.asyncExec(new Runnable() {
            @Override
            public void run() {
                for (ITargetChangeListener listener : listeners) {
                    try {
                        listener.onTargetLoaded(target);
                    } catch (Exception e) {
                        AdtPlugin.log(e, "Failed to update a TargetChangeListener.");  //$NON-NLS-1$
                    }
                }
            }
        });
    }

    public static synchronized OutputStream getOutStream() {
        return sPlugin.mAndroidConsoleStream;
    }

    public static synchronized OutputStream getErrorStream() {
        return sPlugin.mAndroidConsoleErrorStream;
    }

    /**
     * Sets the named persistent property for the given file to the given value
     *
     * @param file the file to associate the property with
     * @param qname the name of the property
     * @param value the new value, or null to clear the property
     */
    public static void setFileProperty(IFile file, QualifiedName qname, String value) {
        try {
            file.setPersistentProperty(qname, value);
        } catch (CoreException e) {
            log(e, "Cannot set property %1$s to %2$s", qname, value);
        }
    }

    /**
     * Gets the named persistent file property from the given file
     *
     * @param file the file to look up properties for
     * @param qname the name of the property to look up
     * @return the property value, or null
     */
    public static String getFileProperty(IFile file, QualifiedName qname) {
        try {
            return file.getPersistentProperty(qname);
        } catch (CoreException e) {
            log(e, "Cannot get property %1$s", qname);
        }

        return null;
    }

    /**
     * Conditionally reparses the content of the SDK if it has changed on-disk
     * and updates opened projects.
     * <p/>
     * The operation is asynchronous and happens in a background eclipse job.
     * <p/>
     * This operation is called in multiple places and should be reasonably
     * cheap and conservative. The goal is to automatically refresh the SDK
     * when it is obvious it has changed so when not sure the code should
     * tend to not reload and avoid reloading too often (which is an expensive
     * operation that has a lot of user impact.)
     */
    public void refreshSdk() {
        // SDK can't have changed if we haven't loaded it yet.
        final Sdk sdk = Sdk.getCurrent();
        if (sdk == null) {
            return;
        }

        Job job = new Job("Check Android SDK") {
            @Override
            protected IStatus run(IProgressMonitor monitor) {
                // SDK has changed if its location path is different.
                File location = sdk.getSdkFileLocation();
                boolean changed = location == null || !location.isDirectory();

                if (!changed) {
                    assert location != null;
                    File prefLocation = new File(AdtPrefs.getPrefs().getOsSdkFolder());
                    changed = !location.equals(prefLocation);

                    if (changed) {
                        // Basic file path comparison indicates they are not the same.
                        // Let's dig a bit deeper.
                        try {
                            location     = location.getCanonicalFile();
                            prefLocation = prefLocation.getCanonicalFile();
                            changed = !location.equals(prefLocation);
                        } catch (IOException ignore) {
                            // There's no real reason for the canonicalization to fail
                            // if the paths map to actual directories. And if they don't
                            // this should have been caught above.
                        }
                    }
                }

                if (!changed) {
                    // Check whether the target directories has potentially changed.
                    changed = sdk.haveTargetsChanged();
                }

                if (changed) {
                    monitor.setTaskName("Reload Android SDK");
                    reparseSdk();
                }

                monitor.done();
                return Status.OK_STATUS;
            }
        };
        job.setRule(ResourcesPlugin.getWorkspace().getRoot());
        job.setPriority(Job.SHORT); // a short background job, not interactive.
        job.schedule();
    }

    /**
     * Reparses the content of the SDK and updates opened projects.
     * The operation is asynchronous and happens in a background eclipse job.
     * <p/>
     * This reloads the SDK all the time. To only perform this when it has potentially
     * changed, call {@link #refreshSdk()} instead.
     */
    public void reparseSdk() {
        // add all the opened Android projects to the list of projects to be updated
        // after the SDK is reloaded
        synchronized (Sdk.getLock()) {
            // get the project to refresh.
            IJavaProject[] androidProjects = BaseProjectHelper.getAndroidProjects(null /*filter*/);
            mPostLoadProjectsToResolve.addAll(Arrays.asList(androidProjects));
        }

        // parse the SDK resources at the new location
        parseSdkContent(0 /*immediately*/);
    }

    /**
     * Prints messages, associated with a project to the specified stream
     * @param stream The stream to write to
     * @param tag The tag associated to the message. Can be null
     * @param objects The objects to print through their toString() method (or directly for
     * {@link String} objects.
     */
    public static synchronized void printToStream(MessageConsoleStream stream, String tag,
            Object... objects) {
        String dateTag = AndroidPrintStream.getMessageTag(tag);

        for (Object obj : objects) {
            stream.print(dateTag);
            stream.print(" "); //$NON-NLS-1$
            if (obj instanceof String) {
                stream.println((String)obj);
            } else if (obj == null) {
                stream.println("(null)");  //$NON-NLS-1$
            } else {
                stream.println(obj.toString());
            }
        }
    }

    // --------- ILogger methods -----------

    @Override
    public void error(@Nullable Throwable t, @Nullable String format, Object... args) {
        if (t != null) {
            log(t, format, args);
        } else {
            log(IStatus.ERROR, format, args);
        }
    }

    @Override
    public void info(@NonNull String format, Object... args) {
        log(IStatus.INFO, format, args);
    }

    @Override
    public void verbose(@NonNull String format, Object... args) {
        log(IStatus.INFO, format, args);
    }

    @Override
    public void warning(@NonNull String format, Object... args) {
        log(IStatus.WARNING, format, args);
    }

    /**
     * Opens the given URL in a browser tab
     *
     * @param url the URL to open in a browser
     */
    public static void openUrl(URL url) {
        IWorkbenchBrowserSupport support = PlatformUI.getWorkbench().getBrowserSupport();
        IWebBrowser browser;
        try {
            browser = support.createBrowser(PLUGIN_ID);
            browser.openURL(url);
        } catch (PartInitException e) {
            log(e, null);
        }
    }

    /**
     * Opens a Java class for the given fully qualified class name
     *
     * @param project the project containing the class
     * @param fqcn the fully qualified class name of the class to be opened
     * @return true if the class was opened, false otherwise
     */
    public static boolean openJavaClass(IProject project, String fqcn) {
        if (fqcn == null) {
            return false;
        }

        // Handle inner classes
        if (fqcn.indexOf('$') != -1) {
            fqcn = fqcn.replaceAll("\\$", "."); //$NON-NLS-1$ //$NON-NLS-2$
        }

        try {
            if (project.hasNature(JavaCore.NATURE_ID)) {
                IJavaProject javaProject = JavaCore.create(project);
                IJavaElement result = javaProject.findType(fqcn);
                if (result != null) {
                    return JavaUI.openInEditor(result) != null;
                }
            }
        } catch (Throwable e) {
            log(e, "Can't open class %1$s", fqcn); //$NON-NLS-1$
        }

        return false;
    }

    /**
     * For a stack trace entry, specifying a class, method, and optionally
     * fileName and line number, open the corresponding line in the editor.
     *
     * @param fqcn the fully qualified name of the class
     * @param method the method name
     * @param fileName the file name, or null
     * @param lineNumber the line number or -1
     * @return true if the target location could be opened, false otherwise
     */
    public static boolean openStackTraceLine(@Nullable String fqcn,
            @Nullable String method, @Nullable String fileName, int lineNumber) {
        return new SourceRevealer().revealMethod(fqcn + '.' + method, fileName, lineNumber, null);
    }

    /**
     * Opens the given file and shows the given (optional) region in the editor (or
     * if no region is specified, opens the editor tab.)
     *
     * @param file the file to be opened
     * @param region an optional region which if set will be selected and shown to the
     *            user
     * @throws PartInitException if something goes wrong
     */
    public static void openFile(IFile file, IRegion region) throws PartInitException {
        openFile(file, region, true);
    }

    // TODO: Make an openEditor which does the above, and make the above pass false for showEditor

    /**
     * Opens the given file and shows the given (optional) region
     *
     * @param file the file to be opened
     * @param region an optional region which if set will be selected and shown to the
     *            user
     * @param showEditorTab if true, front the editor tab after opening the file
     * @return the editor that was opened, or null if no editor was opened
     * @throws PartInitException if something goes wrong
     */
    public static IEditorPart openFile(IFile file, IRegion region, boolean showEditorTab)
            throws PartInitException {
        IWorkbenchPage page = AdtUtils.getActiveWorkbenchPage();
        if (page == null) {
            return null;
        }
        IEditorPart targetEditor = IDE.openEditor(page, file, true);
        if (targetEditor instanceof AndroidXmlEditor) {
            AndroidXmlEditor editor = (AndroidXmlEditor) targetEditor;
            if (region != null) {
                editor.show(region.getOffset(), region.getLength(), showEditorTab);
            } else if (showEditorTab) {
                editor.setActivePage(AndroidXmlEditor.TEXT_EDITOR_ID);
            }
        } else if (targetEditor instanceof AbstractTextEditor) {
            AbstractTextEditor editor = (AbstractTextEditor) targetEditor;
            if (region != null) {
                editor.setHighlightRange(region.getOffset(), region.getLength(),
                        true /* moveCursor*/);
            }
        }

        return targetEditor;
    }
}
