blob: e6ae65ef148bdaeae08f0448231b75741ad31fd5 [file] [log] [blame]
/*******************************************************************************
* 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;
}
}