/******************************************************************************* | |
* Copyright (c) 2011 SAP AG 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: | |
* Stefan Dimov (SAP AG) - initial API and implementation | |
* Kaloyan Raev (SAP AG) | |
*******************************************************************************/ | |
package org.eclipse.libra.facet.internal; | |
import static org.eclipse.libra.facet.OSGiBundleFacetUtils.VIRTUAL_COMPONENT_PATH; | |
import static org.eclipse.libra.facet.OSGiBundleFacetUtils.getContextRootFromPDEModel; | |
import static org.eclipse.libra.facet.OSGiBundleFacetUtils.getContextRootFromWTPModel; | |
import static org.eclipse.libra.facet.OSGiBundleFacetUtils.getManifestPath; | |
import static org.eclipse.libra.facet.OSGiBundleFacetUtils.isWebApplicationBundle; | |
import static org.eclipse.libra.facet.OSGiBundleFacetUtils.setContextRootInPDEModel; | |
import static org.eclipse.libra.facet.OSGiBundleFacetUtils.setContextRootInWTPModel; | |
import java.util.HashSet; | |
import java.util.Set; | |
import org.eclipse.core.resources.IProject; | |
import org.eclipse.core.resources.IResourceChangeEvent; | |
import org.eclipse.core.resources.IResourceChangeListener; | |
import org.eclipse.core.resources.IResourceDelta; | |
import org.eclipse.core.resources.IncrementalProjectBuilder; | |
import org.eclipse.core.runtime.CoreException; | |
import org.eclipse.core.runtime.IProgressMonitor; | |
import org.eclipse.core.runtime.IStatus; | |
import org.eclipse.core.runtime.Status; | |
import org.eclipse.core.runtime.jobs.Job; | |
import org.eclipse.osgi.util.NLS; | |
/** | |
* This class is a resource change listener that watches for changes in the | |
* "web context root" in either the WTP and PDE models and synchronizes them. | |
* Meaning, if the web context root changes in the PDE model, it is | |
* automatically changed in the WTP model, and vice versa. | |
* | |
* <p> | |
* This resource change listener is registered and unregistered for events in | |
* the bundle's activator. | |
* </p> | |
*/ | |
public class WebContextRootSynchonizer implements IResourceChangeListener { | |
public void resourceChanged(IResourceChangeEvent event) { | |
// we are only interested in POST_CHANGE events | |
if (event.getType() != IResourceChangeEvent.POST_CHANGE) | |
return; | |
final Set<IProject> projectsWithModifiedWTPModel = new HashSet<IProject>(); | |
final Set<IProject> projectsWithModifiedPDEModel = new HashSet<IProject>(); | |
IResourceDelta rootDelta = event.getDelta(); | |
IResourceDelta[] projectDeltas = rootDelta.getAffectedChildren(); | |
for (IResourceDelta projectDelta : projectDeltas) { | |
IProject project = (IProject) projectDelta.getResource(); | |
// first check if the modified project is a web application bundle | |
if (!isWAB(project)) | |
continue; | |
// get the delta, if any, for the org.eclipse.wst.common.component file | |
IResourceDelta componentDelta = projectDelta.findMember(VIRTUAL_COMPONENT_PATH); | |
if (isContentChanged(componentDelta)) { | |
// add the project to the list of affected projects | |
projectsWithModifiedWTPModel.add(project); | |
} | |
// get the delta, if any, for the MANIFEST.MF file | |
IResourceDelta manifestDelta = projectDelta.findMember(getManifestPath(project)); | |
if (isContentChanged(manifestDelta)) { | |
// add the project to the list of modified projects | |
projectsWithModifiedPDEModel.add(project); | |
} | |
} | |
if (projectsWithModifiedWTPModel.size() > 0 || projectsWithModifiedPDEModel.size() > 0) { | |
// process in a separate job that all projects are identified for possible change in the context root. | |
// reading and writing to models involves expensive I/O operation that should be executed outside the | |
// resource change listener. | |
new Job(Messages.WebContextRootSynchonizer_JobName) { | |
@Override | |
protected IStatus run(IProgressMonitor monitor) { | |
// process all projects that are identified for possible change in the context root | |
for (IProject project : projectsWithModifiedWTPModel) { | |
try { | |
// trigger a build to give opportunity to the models to refresh | |
project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, monitor); | |
// get the new context root from the WTP model | |
String newContextRoot = getContextRootFromWTPModel(project); | |
// get the old context root from the PDE model | |
String oldContextRoot = getContextRootFromPDEModel(project); | |
// check the context roots and decide if updating the one in the PDE model is needed | |
if (!areEqual(newContextRoot, oldContextRoot)) { | |
setContextRootInPDEModel(project, newContextRoot, monitor); | |
} | |
} catch (CoreException e) { | |
LibraFacetPlugin.logError(NLS.bind(Messages.WebContextRootSynchonizer_UpdatingPDEModelFailed, project.getName()), e); | |
} | |
} | |
for (IProject project : projectsWithModifiedPDEModel) { | |
try { | |
// trigger a build to give opportunity to the models to refresh | |
project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, monitor); | |
// get the new context root from the PDE model | |
String newContextRoot = getContextRootFromPDEModel(project); | |
// get the old context root from the WTP model | |
String oldContextRoot = getContextRootFromWTPModel(project); | |
// check the context roots and decide if updating the one in the WTP model is needed | |
if (!areEqual(newContextRoot, oldContextRoot)) { | |
setContextRootInWTPModel(project, newContextRoot); | |
} | |
} catch (CoreException e) { | |
LibraFacetPlugin.logError(NLS.bind(Messages.WebContextRootSynchonizer_UpdatingWTPModelFailed, project.getName()), e); | |
} | |
} | |
return Status.OK_STATUS; | |
} | |
private boolean areEqual(String value1, String value2) { | |
if (value1 == null) | |
return value2 == null; | |
return value1.equals(value2); | |
} | |
}.schedule(); | |
} | |
} | |
private static boolean isWAB(IProject project) { | |
boolean result = false; | |
try { | |
result = isWebApplicationBundle(project); | |
} catch (CoreException e) { | |
LibraFacetPlugin.logError(e); | |
// do nothing - assume the project is not a web application bundle | |
} | |
return result; | |
} | |
private static boolean isContentChanged(IResourceDelta delta) { | |
return delta != null && delta.getKind() == IResourceDelta.CHANGED | |
&& (delta.getFlags() & IResourceDelta.CONTENT) != 0; | |
} | |
} |