/******************************************************************************* * Copyright (c) 2012 VMWare, Inc. * 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: * VMWare, Inc. - initial API and implementation *******************************************************************************/ package org.grails.ide.eclipse.ui.internal.importfixes; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.WorkspaceJob; 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.Path; 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.grails.ide.eclipse.commands.GrailsCommandUtils; import org.grails.ide.eclipse.core.GrailsCoreActivator; import org.grails.ide.eclipse.core.internal.GrailsNature; /** * An instance of this class is responsible for fixing the output folder of a Grails project * if it overlaps with the output folder used by grails war command. * <p> * This functionality is hooked and triggered in two ways: * - called from GrailsProjectVersionFixer * - makes a scan of existing grails projects in the workspace when it starts. * * @author Kris De Volder * * @since 2.8 */ public class GrailsOutputFolderFixer { /** * The project relative path that is used by the grails war command as its output folder. */ private static final IPath GRAILS_WAR_OUTPUT_FOLDER = new Path("web-app/WEB-INF/classes"); public GrailsOutputFolderFixer(GrailsProjectVersionFixer versionFixer) { versionFixer.setGrailsOutputFolderFixer(this); //Allows version fixer to call us when new grails projects are detected. scanExistingGrailsProjects(); } /** * This method is public *only* for testing purposes. It shouldn't be called directly from * outside this class. */ public void scanExistingGrailsProjects() { IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); for (IProject p : projects) { if (GrailsNature.looksLikeGrailsProject(p)) { fix(p); } } } public void dispose() { } /** * Called by project version fixer when it detects a new grails project in the workspace. * <p> * This is called after the version fixer has already applied its fixer logic. (But beware that * the fixer actually shedules most of its work as jobs so the actually fixes probably * have not yet been applied. */ public void fix(IProject project) { try { if (project.hasNature(JavaCore.NATURE_ID)) { final IJavaProject javaProject = JavaCore.create(project); IPath outputFolder = javaProject.getOutputLocation(); if (isBadOutputFolder(outputFolder)) { WorkspaceJob job = new WorkspaceJob("Fix output folder") { @Override public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { try { //We recheck the fixing condition because, it may have changed by the time the job is scheduled. //This is because version fixer in some cases calls eclipsify (also from a scheduled job) and //this also fixes the output folder. It is probably harmless to fix twice, but it does //cause a potential build, so it is best not to do it. IPath outputFolder = javaProject.getOutputLocation(); if (isBadOutputFolder(outputFolder)) { GrailsCommandUtils.setDefaultOutputFolder(javaProject); } return Status.OK_STATUS; } catch (Exception e) { return new Status(IStatus.WARNING, GrailsCoreActivator.PLUGIN_ID, "Error while fixing output folder for project "+javaProject.getElementName()); } } }; job.setRule(ResourcesPlugin.getWorkspace().getRuleFactory().buildRule()); job.setPriority(Job.INTERACTIVE); job.schedule(); } } } catch (Exception e) { GrailsCoreActivator.log(e); } } private boolean isBadOutputFolder(IPath outputFolder) { return outputFolder.removeFirstSegments(1).equals(GRAILS_WAR_OUTPUT_FOLDER); } }