org.eclipseguru.gwt.core.runtimes.GwtRuntimeManager.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipseguru.gwt.core.runtimes.GwtRuntimeManager.java

Source

/*******************************************************************************
 * Copyright (c) 2006, 2010 EclipseGuru and others.
 * All rights reserved.
 *
 * This program and the accompanying materials are made available under the terms of the
 * Eclipse Public License v1.0 which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     EclipseGuru - initial API and implementation
 *******************************************************************************/
package org.eclipseguru.gwt.core.runtimes;

import org.eclipseguru.gwt.core.GwtCore;
import org.eclipseguru.gwt.core.classpath.GwtContainer;
import org.eclipseguru.gwt.core.preferences.GwtCorePreferenceConstants;

import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.INodeChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.NodeChangeEvent;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * A manager for GWT runtimes.
 */
public class GwtRuntimeManager implements GwtCorePreferenceConstants {
    private static String PREF_GWT_HOME = "gwtHome";

    private static final boolean logProblems = false;
    private static final INodeChangeListener listener = new INodeChangeListener() {

        public void added(final NodeChangeEvent event) {
            flush();
        }

        public void removed(final NodeChangeEvent event) {
            flush();
        }
    };

    private static AtomicReference<GwtRuntime[]> installedRuntimesRef = new AtomicReference<GwtRuntime[]>();
    private static final Lock initializationLock = new ReentrantLock();

    /**
     * Returns the installed runtime with the specified name.
     * 
     * @param name
     * @return the installed runtime (maybe <code>null</code>)
     */
    public static GwtRuntime findInstalledRuntime(final String name) {
        final GwtRuntime[] runtimes = getInstalledRuntimes();
        for (final GwtRuntime gwtRuntime : runtimes) {
            if (name == null) {
                return gwtRuntime;
            } else if (gwtRuntime.getName().equals(name)) {
                return gwtRuntime;
            }
        }
        return null;
    }

    static void flush() {
        try {
            installedRuntimesRef.set(null);
            rebindClasspathEntries();
        } catch (final CoreException e) {
            if (logProblems) {
                GwtCore.logError("Exception while rebinding GWT runtime libraries. " + e.getMessage(), e);
            }
        }
    }

    private static IEclipsePreferences getGwtRuntimePreferencesNode() {
        return (IEclipsePreferences) new InstanceScope().getNode(GwtCore.PLUGIN_ID)
                .node(GwtCorePreferenceConstants.PREF_GWT_RUNTIMES);
    }

    /**
     * Returns a list of all installed runtimes.
     * 
     * @return a list of all installed runtimes
     */
    public static GwtRuntime[] getInstalledRuntimes() {
        GwtRuntime[] installedRuntimes = installedRuntimesRef.get();
        while (null == installedRuntimes) {
            installedRuntimesRef.compareAndSet(null, loadInstalledRuntimes());
            installedRuntimes = installedRuntimesRef.get();
        }
        return installedRuntimes;
    }

    private static GwtRuntime[] loadInstalledRuntimes() {
        initializationLock.lock();
        try {
            // check if already initialized
            final GwtRuntime[] gwtRuntimes = installedRuntimesRef.get();
            if (null != gwtRuntimes) {
                return gwtRuntimes;
            }

            migrateOldPreferences();

            final IEclipsePreferences preferences = getGwtRuntimePreferencesNode();

            // hook change listener
            preferences.addNodeChangeListener(listener); // ok to be called multiple times

            // read runtimes
            String[] runtimeNames;
            try {
                runtimeNames = preferences.childrenNames();
            } catch (final BackingStoreException e) {
                GwtCore.logError("Error while loading GWT runtimes from preferences. " + e.getMessage(), e);
                return new GwtRuntime[0];
            }
            final List<GwtRuntime> runtimes = new ArrayList<GwtRuntime>(runtimeNames.length);
            for (final String name : runtimeNames) {
                final String location = preferences.node(name).get(GwtCorePreferenceConstants.PREF_LOCATION, null);
                if (null != location) {
                    try {
                        runtimes.add(new GwtRuntime(name, Path.fromPortableString(location)));
                    } catch (final Exception e) {
                        // ignore bogus entry
                    }
                }
            }

            return runtimes.toArray(new GwtRuntime[runtimes.size()]);

        } finally {
            initializationLock.unlock();
        }
    }

    /**
     * Migrates old preferences if necessary.
     */
    private static void migrateOldPreferences() {
        final IEclipsePreferences preferences = new InstanceScope().getNode(GwtCore.PLUGIN_ID);
        final String oldGwtHome = preferences.get(PREF_GWT_HOME, null);
        if (null != oldGwtHome) {
            final IPath oldLocation = Path.fromPortableString(oldGwtHome);
            GwtRuntime gwtRuntime;
            try {
                gwtRuntime = new GwtRuntime(oldLocation.lastSegment(), oldLocation);
            } catch (final IllegalArgumentException e) {
                // invalid location
                gwtRuntime = new GwtRuntime("Migrated GWT", oldLocation);
            }

            try {
                saveRuntime(gwtRuntime);

                // remove old node
                preferences.remove(PREF_GWT_HOME);
                try {
                    preferences.flush();
                } catch (final BackingStoreException e) {
                    // don't fail, we may issue a warning in this case
                }
            } catch (final BackingStoreException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    private static void rebindClasspathEntries() throws CoreException {
        final IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
        final IJavaProject[] projects = JavaCore.create(root).getJavaProjects();
        final IPath containerPath = new Path(GwtCore.GWT_CONTAINER);

        final List<IJavaProject> affectedProjects = new ArrayList<IJavaProject>();
        final List<IClasspathContainer> newContainers = new ArrayList<IClasspathContainer>();

        for (final IJavaProject project : projects) {
            final IClasspathEntry[] entries = project.getRawClasspath();
            for (final IClasspathEntry curr : entries) {
                if (curr.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
                    final IPath currPath = curr.getPath();
                    if (containerPath.isPrefixOf(currPath)) {
                        affectedProjects.add(project);
                        GwtContainer container = null;
                        if (currPath.segmentCount() > 1) {
                            final GwtRuntime runtime = findInstalledRuntime(currPath.segment(1));
                            if ((null != runtime) && !runtime.getLocation().isEmpty()) {
                                container = new GwtContainer(runtime, containerPath);
                            }
                        }
                        newContainers.add(container);
                        break;
                    }
                }
            }
        }
        if (!affectedProjects.isEmpty()) {
            final IJavaProject[] affected = affectedProjects.toArray(new IJavaProject[affectedProjects.size()]);
            final IClasspathContainer[] containers = newContainers
                    .toArray(new IClasspathContainer[newContainers.size()]);
            JavaCore.setClasspathContainer(containerPath, affected, containers, null);

        }
    }

    private static void saveRuntime(final GwtRuntime runtime) throws BackingStoreException {
        final Preferences runtimeNode = getGwtRuntimePreferencesNode().node(runtime.getName());
        runtimeNode.put(GwtCorePreferenceConstants.PREF_LOCATION, runtime.getLocation().toPortableString());
        runtimeNode.flush();
    }

    /**
     * Sets the active runtime
     * 
     * @param runtime
     */
    public static void setActiveRuntime(final GwtRuntime runtime) throws Exception {
        // remove all existing runtimes
        final Preferences runtimeNode = getGwtRuntimePreferencesNode();
        for (final String name : runtimeNode.childrenNames()) {
            runtimeNode.node(name).removeNode();
        }

        // save new runtime
        saveRuntime(runtime);
    }

    /**
     * Hidden
     */
    private GwtRuntimeManager() {
        // empty
    }
}