/*******************************************************************************
* Copyright 2011 Google Inc. All Rights Reserved.
*
* 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
*
* 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.google.gdt.eclipse.suite;
import com.google.gdt.eclipse.suite.launch.processors.DefaultWorkingDirectoryMigrator;
import com.google.gdt.eclipse.suite.launch.processors.LaunchConfigAffectingChangesListener;
import com.google.gdt.eclipse.suite.preferences.GdtPreferences;
import com.google.gwt.eclipse.core.nature.GWTNature;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
/**
* Runs migration logic on projects.
*/
public class ProjectMigrator {
public static final int CURRENT_VERSION = 4;
/**
* Scans projects in workspace for those that have not been migrated to the latest version.
*/
public void migrate() {
boolean closedProjectsInWorkspace = false;
// Attempt to migrate all projects
IWorkspace workspace = ResourcesPlugin.getWorkspace();
for (IProject project : workspace.getRoot().getProjects()) {
if (project.isOpen()) {
safelyMigrateIfVersionChanged(project);
} else {
closedProjectsInWorkspace = true;
}
}
// Add listeners for all closed projects, so we can rebuild them, too,
// when they're opened (but only if they are GWT projects).
if (closedProjectsInWorkspace) {
workspace.addResourceChangeListener(new IResourceChangeListener() {
@Override
public void resourceChanged(IResourceChangeEvent event) {
IResourceDelta delta = event.getDelta();
if (delta != null) {
// Find any project-level changes
IResourceDelta[] projectDeltas = delta.getAffectedChildren(IResourceDelta.CHANGED, IResource.PROJECT);
// The master delta may include more than one project delta
for (IResourceDelta projectDelta : projectDeltas) {
// Find any deltas for projects being opened/closed
if ((projectDelta.getFlags() & IResourceDelta.OPEN) > 0) {
IProject project = (IProject) projectDelta.getResource();
if (project.isOpen()) {
safelyMigrateIfVersionChanged(project);
}
}
}
}
}
});
}
}
/**
* The actual migration logic. Ensure the template is followed exactly -- specifically that
* {@link ProjectMigrator#CURRENT_VERSION} has been bumped, and that it will equal the projectVersion at the end of
* this method. Also make sure you use "if" and not "else if".
*
* @param project
* @param projectVersion
*/
private void migrateProject(IProject project, int projectVersion) {
if (projectVersion == 0) {
projectVersion = 1;
/* Dummy migration logic to serve as a template/example */
project.toString();
}
if (projectVersion == 1) {
projectVersion = 2;
/*
* Moves to the GPE's new style of launch configs where arguments reflect the actual parameters passed to the
* launch
*/
LaunchConfigAffectingChangesListener.INSTANCE.updateLaunchConfigurations(project);
}
if (projectVersion == 2) {
projectVersion = 3;
/*
* Set the launch config's working directory to default (which will always resolve to the WAR directory) if it
* currently equals the WAR directory.
*/
new DefaultWorkingDirectoryMigrator().migrate(project);
}
if (projectVersion == 3) {
projectVersion = 4;
/*
* GPE now realizes GWTShell from newer SDKs supports the -remoteUI argument. Update the launch configs so those
* that use GWTShell will switch to the Dev Mode view inside Eclipse.
*/
LaunchConfigAffectingChangesListener.INSTANCE.updateLaunchConfigurations(project);
}
if (projectVersion != CURRENT_VERSION) {
GdtPlugin.getLogger().logError("Project migrator did not migrate project to the latest version");
}
// Write back project version
GdtPreferences.setProjectMigratorVersion(project, projectVersion);
}
/**
* Migrates the given project if there is some migration that needs to be done. This method ensures no exceptions
* escape.
*/
private void safelyMigrateIfVersionChanged(IProject project) {
try {
if (GWTNature.isGWTProject(project.getProject())) {
int projectVersion = GdtPreferences.getProjectMigratorVersion(project);
if (projectVersion != CURRENT_VERSION) {
migrateProject(project, projectVersion);
}
}
} catch (Throwable e) {
GdtPlugin.getLogger().logError(e, "Skipping project migrator for project " + project.getName());
}
}
}