/** * Copyright (c) 2009-2011, The HATS Consortium. All rights reserved. * This file is licensed under the terms of the Modified BSD License. */ package org.absmodels.abs.plugin.builder; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.util.HashSet; import java.util.Map; import org.absmodels.abs.plugin.util.Constants; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.ui.actions.WorkspaceModifyOperation; import static org.absmodels.abs.plugin.util.Constants.JAVA_SOURCE_PATH; import static org.absmodels.abs.plugin.util.Constants.MARKER_TYPE; import static org.absmodels.abs.plugin.util.Constants.MAUDE_PATH; import static org.absmodels.abs.plugin.util.CoreControlUnit.notifyBuildListener; import static org.absmodels.abs.plugin.util.UtilityFunctions.deleteRecursive; import static org.absmodels.abs.plugin.util.UtilityFunctions.getAbsNature; import static org.absmodels.abs.plugin.util.UtilityFunctions.isABSFile; /** * Builds the abs files in abs projects. Automated building has to be activated for all abs files to be parsed * and typechecked automatically. * @author mweber * */ public class AbsBuilder extends IncrementalProjectBuilder { static class SampleDeltaVisitor implements IResourceDeltaVisitor { final private HashSet<String> changedFiles; final private IProgressMonitor monitor; public SampleDeltaVisitor(HashSet<String> changedFiles, IProgressMonitor monitor){ this.changedFiles = changedFiles; this.monitor = monitor; } /** * Visits and parses all files in the ABS project that have changed since last build * * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta) */ @Override public boolean visit(IResourceDelta delta) throws CoreException { IResource resource = delta.getResource(); AbsNature nature = getAbsNature(resource); switch (delta.getKind()) { case IResourceDelta.ADDED: // handle added resource if (nature.toIncludeInScope(resource)) { nature.parseABSFile(resource,false,monitor); changedFiles.add(resource.getFullPath().toString()); } break; case IResourceDelta.REMOVED: // handle removed resource break; case IResourceDelta.CHANGED: // handle changed resource if (nature.toIncludeInScope(resource)) { nature.parseABSFile(resource,false,monitor); changedFiles.add(resource.getFullPath().toString()); } break; } return true; } } /** * Works through the project and parses all abs files. gets called when a full build is needed. * * @author mweber * */ static class SampleResourceVisitor implements IResourceVisitor { private final HashSet<String> changedFiles; private final IProgressMonitor monitor; public SampleResourceVisitor(IProgressMonitor monitor, HashSet<String> changedFiles){ this.monitor = monitor; this.changedFiles = changedFiles; } @Override public boolean visit(IResource resource) throws CoreException{ AbsNature nature = getAbsNature(resource); synchronized (nature.modelLock) { if(isABSFile(resource) && nature.toIncludeInScope(resource)){ nature.parseABSFile(resource,false,monitor); changedFiles.add(resource.getFullPath().toString()); } } return true; } } /** * gets called when a build (full or partial) is requested * * @see org.eclipse.core.resources.IncrementalProjectBuilder#build(int, * java.util.Map, org.eclipse.core.runtime.IProgressMonitor) */ @SuppressWarnings("rawtypes") @Override protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException { final AbsNature nature = getAbsNature(getProject()); synchronized (nature.modelLock) { nature.cleanModel(); try { new WorkspaceModifyOperation() { @Override protected void execute(IProgressMonitor monitor) throws CoreException, InvocationTargetException, InterruptedException { HashSet<String> changedFiles = new HashSet<String>(); fullBuild(monitor, changedFiles); nature.typeCheckModel(monitor); notifyBuildListener(changedFiles); if (monitor != null) monitor.done(); } }.run(monitor); } catch (InvocationTargetException e) { throw new CoreException(new Status(IStatus.ERROR, Constants.PLUGIN_ID, "Build", e)); } catch (InterruptedException e) { } return null; } } /** * cleans the project by deleting all marks generated by a previous build, cleaning the model * by removing the current AST and deleting all generated Java and Maude files * @see org.eclipse.core.resources.IncrementalProjectBuilder#clean(org.eclipse.core.runtime.IProgressMonitor) */ @Override protected void clean(IProgressMonitor monitor) throws CoreException { AbsNature nature = getAbsNature(getProject()); synchronized (nature.modelLock) { getProject().deleteMarkers(MARKER_TYPE, true, IResource.DEPTH_INFINITE); nature.cleanModel(); // delete all Java files and classes String javaPathString = nature.getProjectPreferenceStore().getString(JAVA_SOURCE_PATH); cleanGeneratedFiles(javaPathString); // delete all Maude files and classes String maudePathString = nature.getProjectPreferenceStore().getString(MAUDE_PATH); cleanGeneratedFiles(maudePathString); getProject().refreshLocal(IProject.DEPTH_INFINITE, monitor); } } private void cleanGeneratedFiles(String pathstring) { if(pathstring!=null){ IPath path = new Path(pathstring); File dir; if (path.isAbsolute()){ dir = new File(path.toOSString()); } else { path=getProject().getLocation().append(path); dir=path.toFile(); } if(dir.exists()){ deleteRecursive(dir); } } } protected void fullBuild(final IProgressMonitor monitor, HashSet<String> changedFiles) throws CoreException { // the visitor does the work. getProject().accept(new SampleResourceVisitor(monitor,changedFiles)); } protected void incrementalBuild(IResourceDelta delta, IProgressMonitor monitor, HashSet<String> changedFiles) throws CoreException { // the visitor does the work. delta.accept(new SampleDeltaVisitor(changedFiles, monitor)); } }