blob: 72ece1e031d5028721ae54e339f3bb63ce22851c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009 by SAP AG, Walldorf.
* 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:
* SAP AG - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.ws.jaxws.dom.runtime.persistence.sync;
import static org.eclipse.jst.ws.jaxws.dom.runtime.persistence.WSAnnotationFeatures.WS_ANNOTATION;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.ElementChangedEvent;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IElementChangedListener;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jst.ws.jaxws.dom.runtime.api.IDOM;
import org.eclipse.jst.ws.jaxws.dom.runtime.api.IJavaWebServiceElement;
import org.eclipse.jst.ws.jaxws.dom.runtime.api.IServiceEndpointInterface;
import org.eclipse.jst.ws.jaxws.dom.runtime.api.IWebService;
import org.eclipse.jst.ws.jaxws.dom.runtime.api.IWebServiceProject;
import org.eclipse.jst.ws.jaxws.dom.runtime.api.WsDOMLoadCanceledException;
import org.eclipse.jst.ws.jaxws.dom.runtime.persistence.ICompilationUnitFinder;
import org.eclipse.jst.ws.jaxws.dom.runtime.persistence.IProjectSelector;
import org.eclipse.jst.ws.jaxws.dom.runtime.persistence.JaxWsWorkspaceResource;
import org.eclipse.jst.ws.jaxws.dom.runtime.persistence.WorkspaceCUFinder;
import org.eclipse.jst.ws.jaxws.dom.runtime.persistence.JaxWsWorkspaceResource.ServiceModelData;
import org.eclipse.jst.ws.jaxws.utils.annotations.IAnnotation;
public class OnEventModelSynchronizer extends AbstractModelSynchronizer implements IElementChangedListener
{
@Override
public IDOM getDomBeingLoaded()
{
return resource().getDOM();
}
public OnEventModelSynchronizer(JaxWsWorkspaceResource resource, ServiceModelData serviceData)
{
super(resource, serviceData);
}
public void elementChanged(final ElementChangedEvent event)
{
try
{
if (logger().isDebug())
{
logger().logDebug("ElementChangedEvent has been delivered. Event details: " + event.toString());//$NON-NLS-1$
}
// no processing if DOM load has been canceled
if (resource().isLoadCnaceled()) {
return;
}
resource().disableSaving();
// handles ElementChangedEvent.POST_RECONCILE - the case when the editor sends reconcile event
if (event.getType() == ElementChangedEvent.POST_RECONCILE)
{
handleReconcileEvent(event);
}
// handles ElementChangedEvent.POST_CHANGE - the case when the compilation unit has been changed
if (event.getDelta().getElement() != resource().javaModel())
{
return;
}
assert (event.getDelta().getFlags() & (IJavaElementDelta.F_CHILDREN | IJavaElementDelta.F_CONTENT)) != 0;
for (IJavaElementDelta child : event.getDelta().getAffectedChildren())
{
if (child.getElement() instanceof IJavaProject)
{
handleChangedProject(child);
}
}
}
catch (CoreException ce) {
logger().logError("Unable to synchronize Web Service model upon java element delta "+ event.getDelta(), ce); //$NON-NLS-1$
}
catch (WsDOMLoadCanceledException e) {
logger().logError("Unable to synchronize Web Service model upon java element delta " + event.getDelta(), e); //$NON-NLS-1$
}
finally {
resource().enableSaving();
}
}
protected void handleReconcileEvent(final ElementChangedEvent event) throws JavaModelException
{
if(!(event.getDelta().getElement() instanceof ICompilationUnit )) {
return;
}
int requiredFlags = IJavaElementDelta.F_CONTENT | IJavaElementDelta.F_CHILDREN;
if ((event.getDelta().getFlags() & requiredFlags) == 0) {
return;
}
final ICompilationUnit cu = (ICompilationUnit)event.getDelta().getElement();
if (!resource().approveProject(cu.getJavaProject())) {
return;
}
if (isJavaResource(cu)) {
handleChangedContentCompilationUnit(cu);
}
}
private boolean isJavaResource(ICompilationUnit cu) throws JavaModelException
{
IJavaElement javaElement = cu;
while ((javaElement = javaElement.getParent()) != null)
{
if (!javaElement.exists()) {
return false;
}
}
return true;
}
void handleChangedProject(IJavaElementDelta projectDelta) throws CoreException, WsDOMLoadCanceledException
{
assert (projectDelta.getElement() instanceof IJavaProject);
if ((((projectDelta.getFlags() & IJavaElementDelta.F_CLOSED) != 0) || projectDelta.getKind() == IJavaElementDelta.REMOVED)
&& null != util().findProjectByName(getDomBeingLoaded(), projectDelta.getElement().getElementName()))
{
//if the project has been closed then it's facet's could not be read. Thus the approve method
//will always return false. That's why we check if the project has already been in the
handleClosedProject(projectDelta);
}
if (!resource().approveProject((IJavaProject)projectDelta.getElement()))
{
return;
}
if (((projectDelta.getFlags() & IJavaElementDelta.F_OPENED) != 0) || projectDelta.getKind() == IJavaElementDelta.ADDED)
{
handleOpenedProject(projectDelta);
}
for (IJavaElementDelta childDelta : projectDelta.getAffectedChildren())
{
if (!(childDelta.getElement() instanceof IPackageFragmentRoot))
{
continue;
}
if ((childDelta.getFlags() & IJavaElementDelta.F_ADDED_TO_CLASSPATH) != 0)
{
handleClosedProject(projectDelta);
handleOpenedProject(projectDelta);
}
if ((childDelta.getFlags() & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0)
{
handleClosedProject(projectDelta);
handleOpenedProject(projectDelta);
}
if ((childDelta.getFlags() & IJavaElementDelta.F_CHILDREN) != 0)
{
recursevilyHandleRemovedPackages(childDelta);
recursevilyHandleAddedPackages(childDelta);
recursevilyHandleCompilationUnits(childDelta);
}
}
}
protected void recursevilyHandleAddedPackages(IJavaElementDelta rootDelta) throws JavaModelException
{
final IWebServiceProject wsPrj = findProjectByDelta(rootDelta);
if (wsPrj == null) {
return;
}
for (IJavaElementDelta childDelta : rootDelta.getAffectedChildren())
{
if (childDelta.getElement() instanceof IPackageFragment && childDelta.getKind() == IJavaElementDelta.ADDED)
{
for (ICompilationUnit cu : ((IPackageFragment)childDelta.getElement()).getCompilationUnits())
{
processCompilationUnit(wsPrj, cu);
}
recursevilyHandleAddedPackages(childDelta);
}
}
}
protected IWebServiceProject findProjectByDelta(IJavaElementDelta rootDelta) {
return util().findProjectByName(getDomBeingLoaded(), rootDelta.getElement().getJavaProject().getElementName());
}
private void recursevilyHandleRemovedPackages(IJavaElementDelta rootDelta) throws JavaModelException
{
for (IJavaElementDelta childDelta : rootDelta.getAffectedChildren())
{
if (childDelta.getElement() instanceof IPackageFragment)
{
if (childDelta.getKind() == IJavaElementDelta.REMOVED)
{
final IWebServiceProject wsPrj = findProjectByDelta(rootDelta);
if (wsPrj != null) {
removeModelElements(wsPrj, childDelta.getElement().getElementName(), true);
}
} else
{
recursevilyHandleRemovedPackages(childDelta);
}
}
}
}
private void handleOpenedProject(IJavaElementDelta projectDelta) throws CoreException, WsDOMLoadCanceledException
{
assert projectDelta.getElement() instanceof IJavaProject;
final IJavaProject changedProject = (IJavaProject) projectDelta.getElement();
newProjectCUFinder(changedProject).find(null, new LoaderCompilationUnitHandler());
}
private void handleClosedProject(IJavaElementDelta projectDelta) throws CoreException
{
assert projectDelta.getElement() instanceof IJavaProject;
final IWebServiceProject wsPrj = util().findProjectByName(getDomBeingLoaded(), projectDelta.getElement().getElementName());
if (wsPrj==null) {
return;
}
for (IServiceEndpointInterface sei : wsPrj.getServiceEndpointInterfaces())
{
sei.getImplementingWebServices().clear();
}
for (IWebService ws : wsPrj.getWebServices())
{
serviceData().unmap(ws);
}
getDomBeingLoaded().getWebServiceProjects().remove(wsPrj);
}
private ICompilationUnitFinder newProjectCUFinder(final IJavaProject prj)
{
return new WorkspaceCUFinder(resource().javaModel(), new IProjectSelector[] { new IProjectSelector()
{
public boolean approve(IJavaProject toApprove)
{
return prj.getElementName().equals(toApprove.getElementName());
}
} });
}
// handles compilation units - skips working copies
private void recursevilyHandleCompilationUnits(IJavaElementDelta delta)
{
if (delta.getElement() instanceof ICompilationUnit)
{
final ICompilationUnit cu = (ICompilationUnit) delta.getElement();
if (util().findProjectByName(getDomBeingLoaded(), cu.getJavaProject().getElementName())==null)
{
return;
}
try
{
if (delta.getKind() == IJavaElementDelta.ADDED && (delta.getFlags() & IJavaElementDelta.F_MOVED_FROM) == 0)
{
handleAddedCompilationUnit(cu);
}
if (delta.getKind() == IJavaElementDelta.REMOVED && (delta.getFlags() & IJavaElementDelta.F_MOVED_TO) == 0)
{
handleRemovedCompilationUnit(cu);
}
if (delta.getKind() == IJavaElementDelta.REMOVED && (delta.getFlags() & IJavaElementDelta.F_MOVED_TO) != 0)
{
handleMovedToCompilationUnit(cu, (ICompilationUnit) delta.getMovedToElement());
}
if (delta.getKind() == IJavaElementDelta.CHANGED &&
((delta.getFlags() & IJavaElementDelta.F_PRIMARY_RESOURCE) != 0) ||
((delta.getFlags() & IJavaElementDelta.F_PRIMARY_WORKING_COPY) != 0))
{
handleChangedContentCompilationUnit(cu);
}
} catch (JavaModelException jme)
{
logger().logError("Unable to parse the content of compilation unit" + delta.getElement(), jme); //$NON-NLS-1$
}
} else
{
for (IJavaElementDelta childDelta : delta.getAffectedChildren())
{
recursevilyHandleCompilationUnits(childDelta);
}
}
}
private void handleChangedContentCompilationUnit(ICompilationUnit cu) throws JavaModelException
{
final IType type = cu.findPrimaryType();
final IAnnotation<IType> annotation = type==null ? null : resource().newAnnotationInspector(type).inspectType(WS_ANNOTATION);
if (type == null || annotation == null)
{
updateSubclassingWSElements(cu);
handleRemovedCompilationUnit(cu);
} else
{
final IWebServiceProject wsProject = util().findProjectByName(getDomBeingLoaded(), cu.getJavaProject().getElementName());
assert wsProject != null;
processCompilationUnit(wsProject, cu);
}
}
private void updateSubclassingWSElements(ICompilationUnit cu) throws JavaModelException
{
for (IWebServiceProject wsPrj : getDomBeingLoaded().getWebServiceProjects())
{
final IJavaProject javaPrj = javaModel().getJavaProject(wsPrj.getName());
for (IServiceEndpointInterface sei : wsPrj.getServiceEndpointInterfaces())
{
if(serviceData().getHierarchy(sei.getImplementation())==null) {
continue;
}
if (serviceData().getHierarchy(sei.getImplementation()).contains(cu))
{
processCompilationUnit(wsPrj, javaPrj.findType(sei.getImplementation()).getCompilationUnit());
}
}
for (IWebService ws : wsPrj.getWebServices())
{
if(serviceData().getHierarchy(ws.getImplementation())==null) {
continue;
}
if (serviceData().getHierarchy(ws.getImplementation()).contains(cu))
{
processCompilationUnit(wsPrj, javaPrj.findType(ws.getImplementation()).getCompilationUnit());
}
}
}
}
private void handleAddedCompilationUnit(ICompilationUnit addedCU) throws JavaModelException
{
final IWebServiceProject wsPrj = util().findProjectByName(getDomBeingLoaded(), addedCU.getJavaProject().getElementName());
this.processCompilationUnit(wsPrj, addedCU);
}
void handleMovedToCompilationUnit(ICompilationUnit fromCU, ICompilationUnit toCU) throws JavaModelException
{
final IJavaWebServiceElement wsElem = guessContainedWSElement(fromCU);
if (wsElem == null)
{
return;
}
final boolean fqNameChanged = !toCU.getElementName().equals(fromCU.getElementName())
|| !toCU.getParent().getElementName().equals(fromCU.getParent().getElementName());
if (fqNameChanged)
{
handleRemovedCompilationUnit(fromCU);
handleAddedCompilationUnit(toCU);
} else
// then assume that the project only has changed.
{
final IWebServiceProject toPrj = util().findProjectByName(getDomBeingLoaded(), toCU.getJavaProject().getElementName());
if (wsElem instanceof IWebService)
{
toPrj.getWebServices().add((IWebService) wsElem);
} else
{
toPrj.getServiceEndpointInterfaces().add((IServiceEndpointInterface) wsElem);
}
}
}
private void handleRemovedCompilationUnit(ICompilationUnit remCU) throws JavaModelException
{
final IWebServiceProject wsPrj = util().findProjectByName(getDomBeingLoaded(), remCU.getJavaProject().getElementName());
removeModelElements(wsPrj, guessPrimaryTypeName(remCU), false);
}
private void removeModelElements(IWebServiceProject wsPrj, String implBaseName, boolean isForPackage) throws JavaModelException
{
if (wsPrj == null) {
return;
}
removeWsModelElements(wsPrj, implBaseName, isForPackage);
removeSeiModelElements(wsPrj, implBaseName, isForPackage, false);
}
private IJavaWebServiceElement guessContainedWSElement(ICompilationUnit cu)
{
final IWebServiceProject wsPrj = util().findProjectByName(getDomBeingLoaded(), cu.getJavaProject().getElementName());
return util().findJavaWebServiceElemByImplName(wsPrj, guessPrimaryTypeName(cu));
}
protected String guessPrimaryTypeName(ICompilationUnit cu)
{
final String parentName = cu.getParent().getElementName();
final StringBuilder assumedPrimaryTypeName = new StringBuilder();
if (parentName.length() > 0) {
assumedPrimaryTypeName .append(parentName).append('.');
}
return assumedPrimaryTypeName.append(cu.getElementName()).
delete(assumedPrimaryTypeName.lastIndexOf(".java"), assumedPrimaryTypeName.length()).toString();//$NON-NLS-1$
}
}