/******************************************************************************* * Copyright (c) 2013 Zend Technologies Ltd. * 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 *******************************************************************************/ package org.zend.php.zendserver.deployment.ui; import java.io.IOException; import org.eclipse.core.resources.IProject; 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.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.dltk.core.DLTKCore; import org.eclipse.dltk.core.IBuildpathEntry; import org.zend.php.zendserver.deployment.core.DeploymentNature; import org.zend.php.zendserver.deployment.core.descriptor.DescriptorContainerManager; import org.zend.php.zendserver.deployment.core.descriptor.IDeploymentDescriptor; import org.zend.php.zendserver.deployment.core.descriptor.IDescriptorContainer; import org.zend.sdklib.mapping.IMappingEntry.Type; import org.zend.sdklib.mapping.IMappingModel; import org.zend.sdklib.mapping.MappingModelFactory; /** * Listener responsible for updating deployment.properties file according to * changes in a project structure. * * @author Wojciech Galanciak, 2013 * */ public class MappingChangeListener implements IResourceChangeListener { /* * (non-Javadoc) * * @see * org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org * .eclipse.core.resources.IResourceChangeEvent) */ public void resourceChanged(IResourceChangeEvent event) { // on close event - exit IResourceDelta delta = event.getDelta(); if (delta == null) { return; } // finally - go over the changed files and submit changes ChangedFilesVisitor visitor = new ChangedFilesVisitor(); try { delta.accept(visitor); } catch (CoreException e) { Activator.log(e); return; } IProject[] allProjects = visitor.getAllProjects(); for (IProject project : allProjects) { if (!project.isAccessible() || !hasDeploymentNature(project)) { continue; } IMappingModel model = MappingModelFactory .createDefaultModel(project.getLocation().toFile()); if (model == null) { continue; } IDescriptorContainer container = DescriptorContainerManager .getService().openDescriptorContainer(project); IDeploymentDescriptor desc = container.getDescriptorModel(); String scriptsDir = desc.getScriptsRoot(); if (scriptsDir == null) { if (container.getFile().getParent().findMember("scripts") != null) { //$NON-NLS-1$ scriptsDir = "scripts"; //$NON-NLS-1$ } } IResourceDelta[] changedFiles = visitor.getChangedFiles(project); boolean isDirty = false; for (IResourceDelta d : changedFiles) { if (d.getResource().getProjectRelativePath() .segmentCount() == 0) { // means that this is more complex operation, e.g. project creation return; } if (isExcluded(d, project)) { continue; } switch (d.getKind()) { case IResourceDelta.REMOVED: if (handleRemoved(model, scriptsDir, d) && !isDirty) { isDirty = true; } break; case IResourceDelta.ADDED: if (handleAdded(model, scriptsDir, d) && !isDirty) { isDirty = true; } break; case IResourceDelta.CHANGED: break; } } if (isDirty) { try { model.store(); } catch (IOException e) { Activator.log(e); } } } } private boolean isExcluded(IResourceDelta d, IProject project) { IResource res = d.getResource(); if (res != null) { return isExcludedFromBuildpath(project, res.getProjectRelativePath()); } return false; } private boolean handleAdded(IMappingModel model, String scriptsDir, IResourceDelta delta) { IResource resource = delta.getResource(); if (checkIfValid(resource, model, scriptsDir)) { String relativePath = resource.getProjectRelativePath().toString(); if (!relativePath.isEmpty()) { return model.addMapping(IMappingModel.APPDIR, Type.INCLUDE, relativePath, false); } } return false; } private boolean handleRemoved(IMappingModel model, String scriptsDir, IResourceDelta delta) { IResource resource = delta.getResource(); if (checkIfValid(resource, model, scriptsDir)) { String relativePath = resource.getProjectRelativePath().toString(); return model.removeMapping(IMappingModel.APPDIR, Type.INCLUDE, relativePath); } return false; } private boolean checkIfValid(IResource resource, IMappingModel model, String scriptsDir) { if (resource != null) { String name = resource.getName(); if (checkHiddenFile(resource)) { return false; } if (name.equals(MappingModelFactory.DEPLOYMENT_PROPERTIES)) { return false; } if (name.equals(DescriptorContainerManager.DESCRIPTOR_PATH)) { return false; } try { String[] folders = model.getFolders(resource .getProjectRelativePath().toString()); if (folders != null && folders.length > 0) { return false; } } catch (IOException e) { // should not appear } IProject project = resource.getProject(); if (project != null) { IPath resPath = resource.getProjectRelativePath(); if (resPath.segmentCount() > 0 && (resource.getName().equals(scriptsDir) || resPath .segment(0).equals(scriptsDir))) { return false; } } return true; } return false; } private boolean checkHiddenFile(IResource resource) { String name = resource.getName(); if (name.startsWith(".")) { //$NON-NLS-1$ return true; } else { IResource parent = resource.getParent(); if (parent == resource.getProject()) { return false; } else { return checkHiddenFile(parent); } } } private boolean hasDeploymentNature(IProject project) { String[] natures = null; try { natures = project.getDescription().getNatureIds(); } catch (CoreException e) { return false; } for (String nature : natures) { if (DeploymentNature.ID.equals(nature)) { return true; } } return false; } public static boolean isExcludedFromBuildpath(IProject project, IPath path) { IBuildpathEntry[] buildpathEntries = DLTKCore.create(project) .readRawBuildpath(); for (int i = 0; i < buildpathEntries.length; i++) { IBuildpathEntry curr = buildpathEntries[i]; if (curr.getEntryKind() == IBuildpathEntry.BPE_SOURCE && curr.getPath() .equals(project.getProject().getFullPath())) { IPath[] exclusionPatterns = curr.getExclusionPatterns(); for (IPath p : exclusionPatterns) { if (path.matchingFirstSegments(p) == p.segmentCount()) { return true; } } break; } } return false; } }