/******************************************************************************* * Copyright (c) 2005, 2012 IBM Corporation 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.bpel.ui; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.eclipse.bpel.common.extension.model.ExtensionMap; import org.eclipse.bpel.common.extension.model.ExtensionmodelFactory; import org.eclipse.bpel.model.CorrelationSet; import org.eclipse.bpel.model.messageproperties.Property; import org.eclipse.bpel.ui.util.BPELUtil; import org.eclipse.bpel.validator.Builder; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; 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.IResourceDeltaVisitor; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; /** * Listens to changes to the BPEL file and reacts accordingly. */ public class BPELResourceChangeListener implements IResourceChangeListener { class ResourceDeltaVisitor implements IResourceDeltaVisitor { public boolean visit(final IResourceDelta delta) throws CoreException { IResource target = delta.getResource(); // Bugzilla 320545: if (Builder.isBPELFile(target)) { handleBPEL(delta); } return true; } private void handleBPEL(final IResourceDelta delta) throws CoreException { IWorkspaceRunnable runnable = new IWorkspaceRunnable() { public void run(IProgressMonitor monitor) throws CoreException { IFile target = (IFile) delta.getResource(); switch (delta.getKind()) { case IResourceDelta.REMOVED : { int flags = delta.getFlags(); if ((flags & IResourceDelta.MOVED_TO) != 0) { fileMoved(target, delta.getMovedToPath()); } else { fileDeleted(target, monitor); } break; } } } }; ResourcesPlugin.getWorkspace().run(runnable, null); } } protected IResourceDeltaVisitor visitor; protected List<IFileChangeListener> listeners; public BPELResourceChangeListener() { listeners = new ArrayList<IFileChangeListener>(); } /** * Objects like the BPELEditor can add listeners so they can be * notified and react when BPEL files change. */ public void addListener(IFileChangeListener listener) { listeners.add(listener); } /** * Removed the listener. */ public void removeListener(IFileChangeListener listener) { listeners.remove(listener); } public void resourceChanged(IResourceChangeEvent event) { try { event.getDelta().accept(getResourceDeltaVisitor()); } catch (CoreException e) { BPELUIPlugin.log(e); } } protected IResourceDeltaVisitor getResourceDeltaVisitor() { if (visitor == null) { visitor = new ResourceDeltaVisitor(); } return visitor; } /** * Calculate and return all related files to this BPEL file. * Currently this list includes the .bpelex file and the * artifacts WSDL. */ protected static IFile[] getRelatedFiles(IFile bpelFile) { IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IPath bpelPath = bpelFile.getFullPath(); IFile bpelexFile = root.getFile(bpelPath.removeFileExtension().addFileExtension(IBPELUIConstants.EXTENSION_MODEL_EXTENSIONS)); String baseName = bpelPath.removeFileExtension().lastSegment(); IPath artifactsPath = bpelPath.removeFileExtension().removeLastSegments(1).append(baseName+"Artifacts").addFileExtension(IBPELUIConstants.EXTENSION_WSDL); //$NON-NLS-1$ IFile artifactsFile = root.getFile(artifactsPath); return new IFile[] { bpelexFile, artifactsFile }; } /** * Calculate a new name for the given related file, based on * the old file and the new base name. Need a clause in here * to recognize each of the files calculated in getRelatedFiles(). */ protected static String getNewRelatedFileName(IFile oldFile, String newBaseName) { if (IBPELUIConstants.EXTENSION_WSDL.equals(oldFile.getFileExtension())) { return newBaseName + "Artifacts" + IBPELUIConstants.EXTENSION_DOT_WSDL; //$NON-NLS-1$ } else if (IBPELUIConstants.EXTENSION_MODEL_EXTENSIONS.equals(oldFile.getFileExtension())) { return newBaseName + "." + IBPELUIConstants.EXTENSION_MODEL_EXTENSIONS; //$NON-NLS-1$ } return null; } /** * If the BPEL file has moved we have to move related files (e.g. .bpelex). */ protected void fileMoved(IFile oldBPELFile, IPath newBPELFilePath) throws CoreException { IFile[] relatedFiles = getRelatedFiles(oldBPELFile); for (int i = 0; i < relatedFiles.length; i++) { move(relatedFiles[i], newBPELFilePath); } // Fix the bpelex file - it contains a file reference to the bpel // file in each extension, which is incorrect now. fixBPELExtensionFile(oldBPELFile, newBPELFilePath); // notify listeners IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IFile newBPELFile = root.getFile(newBPELFilePath); for (Iterator<IFileChangeListener> iter = listeners.iterator(); iter.hasNext();) { IFileChangeListener listener = iter.next(); listener.moved(oldBPELFile, newBPELFile); } } protected void fixBPELExtensionFile(IFile oldBPELFile, IPath newBPELFilePath) { // Find the path of the new bpelex file URI bpelURI = URI.createPlatformResourceURI(newBPELFilePath.toString() + "#/"); //$NON-NLS-1$ IPath newBPELEXFilePath = newBPELFilePath.removeFileExtension().addFileExtension(IBPELUIConstants.EXTENSION_MODEL_EXTENSIONS); URI extensionsURI = URI.createPlatformResourceURI(newBPELEXFilePath.toString()); ResourceSet resourceSet = new ResourceSetImpl(); Resource extensionsResource = resourceSet.getResource(extensionsURI, true); try { extensionsResource.load(Collections.EMPTY_MAP); EList extensionContents = extensionsResource.getContents(); ExtensionMap extensionMap = ExtensionmodelFactory.eINSTANCE.findExtensionMap( IBPELUIConstants.MODEL_EXTENSIONS_NAMESPACE, extensionContents); for (EObject next : extensionMap.keySet()) { if (next.eIsProxy()) { ((InternalEObject) next).eSetProxyURI(bpelURI); } } extensionsResource.save(Collections.EMPTY_MAP); } catch (IOException e) { } } /** * Used to move files derived from a given source file. Moves the oldRelatedFile * into the folder containing newBpelPath. */ protected void move(IFile oldRelatedFile, IPath newBpelPath) throws CoreException { if (oldRelatedFile.exists()) { IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IFile newBpelFile = root.getFile(newBpelPath); IContainer folder = newBpelFile.getParent(); String newBaseName = newBpelFile.getFullPath().removeFileExtension().lastSegment(); String newName = getNewRelatedFileName(oldRelatedFile, newBaseName); IPath newRelatedFilePath = folder.getFullPath().append(newName); oldRelatedFile.move(newRelatedFilePath, true, null); } } /** * If the BPEL file has been deleted we have to delete related files (e.g. .bpelex). */ protected void fileDeleted(IFile oldBPELFile, IProgressMonitor monitor) throws CoreException { // notify listeners for (IFileChangeListener listener : listeners) { listener.deleted(oldBPELFile); } // Delete bpelex file IFile bpelex = BPELUtil.getBPELEXFile(oldBPELFile); try { bpelex.delete(true, monitor); } catch (CoreException e) { BPELUIPlugin.log(e); } } }