/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.core.builder; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.teiid.core.designer.ModelerCoreException; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.TransactionRunnable; import org.teiid.designer.core.container.Container; import org.teiid.designer.core.index.IndexUtil; import org.teiid.designer.core.notification.util.IgnorableNotificationSource; import org.teiid.designer.core.transaction.UnitOfWork; import org.teiid.designer.core.workspace.ModelResource; import org.teiid.designer.core.workspace.ModelUtil; import org.teiid.designer.core.workspace.ModelWorkspaceManager; import org.teiid.designer.core.workspace.SearchIndexResourceVisitor; import org.teiid.designer.core.workspace.WorkspaceResourceFinderUtil; /** * ModelIndexBuilder * * @since 8.0 */ public class ModelBuilder extends AbstractTeiidProjectBuilder implements IgnorableNotificationSource { /** * @see org.eclipse.core.resources.IncrementalProjectBuilder#clean(org.eclipse.core.runtime.IProgressMonitor) * @since 4.3 */ @Override protected void clean( final IProgressMonitor monitor ) throws CoreException { super.clean(monitor); final IProject proj = getProject(); proj.deleteMarkers(IMarker.PROBLEM, false, IResource.DEPTH_INFINITE); // clear current markers // construct visitor to be used SearchIndexResourceVisitor visitor = new SearchIndexResourceVisitor(); // Notify listeners of clean ModelWorkspaceManager.getModelWorkspaceManager().notifyClean(proj); // Clean all indexes for project ModelWorkspaceManager.getModelWorkspaceManager().deleteIndexes(proj, visitor); // Set build state to not indexed on all resources within project for (final Iterator iter = visitor.getResources().iterator(); iter.hasNext();) { IResource model = (IResource)iter.next(); final ModelResource resrc = ModelerCore.getModelWorkspace().findModelResource(model); if (resrc != null) { model.deleteMarkers(IMarker.PROBLEM, false, IResource.DEPTH_INFINITE); // clear current markers resrc.setIndexType(ModelResource.NOT_INDEXED); } } } /** * @see org.eclipse.core.resources.IncrementalProjectBuilder#build(int, java.util.Map, org.eclipse.core.runtime.IProgressMonitor) */ @Override protected IProject[] buildInternal( final int kind, final Map args, final IProgressMonitor monitor ) throws CoreException { final IProject project = getProject(); if (project == null || !project.isAccessible()) { return null; } switch (kind) { case FULL_BUILD: { performFullBuild(monitor); break; } case AUTO_BUILD: case INCREMENTAL_BUILD: { // Build with a delta (Auto/Incremental) final IResourceDelta delta = getDelta(project); if (delta == null) { performFullBuild(monitor); } else { performIncrementaBuild(monitor, delta); } break; } } return null; } /** * Get all IResources in the given project and index them * * @throws CoreException */ private void performFullBuild( final IProgressMonitor monitor ) throws CoreException { // System.out.println(" ModelBuilder.performFullBuild(): ******** START ******** "); final SearchIndexResourceVisitor visitor = new SearchIndexResourceVisitor(); // collect all IResources for model files getProject().accept(visitor); final TransactionRunnable runnable = new TransactionRunnable() { @Override public Object run( final UnitOfWork uow ) throws ModelerCoreException { // build the resources (index and validate) final Container container = doGetContainer(); List resources = visitor.getResources(); // clear all markers on these resources as we are going to create fresh markers for (Object resource : resources) { try { ((IResource)resource).deleteMarkers(IMarker.PROBLEM, false, IResource.DEPTH_INFINITE); } catch (CoreException e) { ModelerCore.Util.log(e); } } ModelBuildUtil.buildResources(monitor, visitor.getResources(), container, false); Collection<IResource> projectResources = new ArrayList<IResource>(1); projectResources.add(getProject()); ModelBuildUtil.buildResources(monitor, projectResources, container, false); return null; } }; // Get the list of "modified" EMF resources within the model container // prior to performing the build. Since indexing and validation are // considered read-only operations we must make sure that any resources // that are loaded as a result of these operations have a status of // not modified final List modifiedResources = ModelBuildUtil.getModifiedResources(); // Execute the indexing and validation within a transaction ModelerCore.getModelEditor().executeAsTransaction(runnable, "Full Build", false, false, this); //$NON-NLS-1$ // Reset the modified state of all EMF resources to what it was prior to // indexing and validating. Simply commiting the transaction can mark a // resource as modified so we must undo it. ModelBuildUtil.setModifiedResources(modifiedResources); // after every full build remove any index files that have // no coressponding resources in the workspace cleanOrphanedIndexes(); // System.out.println(" ModelBuilder.performFullBuild(): ******** END ******** \n"); } /** * Get all changed IResources in the given IResourceDelta and index them * * @throws CoreException */ private void performIncrementaBuild( final IProgressMonitor monitor, final IResourceDelta delta ) throws CoreException { // System.out.println(" ModelBuilder.performIncrementaBuild(): ******** START ********"); class ResourceDeltaVisitor implements IResourceDeltaVisitor { List resources = new ArrayList(); @Override public boolean visit( final IResourceDelta delta ) throws CoreException { IResource resource = delta.getResource(); if (isIncludedResource(resource)) { resources.add(resource); // clear all markers on this resource, as we are going to create fresh markets resource.deleteMarkers(IMarker.PROBLEM, false, IResource.DEPTH_INFINITE); } return true; } public List getResources() { return resources; } private boolean isIncludedResource( final IResource resource ) { if (resource == null || !resource.exists()) { return false; } if (ModelUtil.isModelFile(resource) || ModelUtil.isXsdFile(resource) || ModelUtil.isVdbArchiveFile(resource)) { return true; } return false; } } final ResourceDeltaVisitor visitor = new ResourceDeltaVisitor(); // collect all IResources for model files delta.accept(visitor); final TransactionRunnable runnable = new TransactionRunnable() { @Override public Object run( final UnitOfWork uow ) throws ModelerCoreException { // Collection of IResources to validate/index final Collection iResources = visitor.getResources(); // Add to the iResources collection any VDB IResource that references one of // the entries in iResourcs. We want to revalidate VDBs that reference modified // resources in the workspace (defect 15779) Collection<IFile> vdbResources = WorkspaceResourceFinderUtil.getVdbResourcesThatContain(iResources); for (IFile vdbResource : vdbResources) { if (!iResources.contains(vdbResource)) { iResources.add(vdbResource); } } // build the resources (index and validate) final Container container = doGetContainer(); if( !iResources.contains(getProject()) ) { iResources.add(getProject()); } ModelBuildUtil.buildResources(monitor, iResources, container, false); return null; } }; // Get the list of "modified" EMF resources within the model container // prior to performing the build. Since indexing and validation are // considered read-only operations we must make sure that any resources // that are loaded as a result of these operations have a status of // not modified final List modifiedResources = ModelBuildUtil.getModifiedResources(); // Execute the indexing and validation within a transaction ModelerCore.getModelEditor().executeAsTransaction(runnable, "Incremental Build", false, false, this); //$NON-NLS-1$ // Reset the modified state of all EMF resources to what it was prior to // indexing and validating. Simply commiting the transaction can mark a // resource as modified so we must undo it. ModelBuildUtil.setModifiedResources(modifiedResources); // System.out.println(" ModelBuilder.performIncrementaBuild(): ******** END ******** \n"); } protected Container doGetContainer() throws ModelerCoreException { try { return ModelerCore.getModelContainer(); } catch (CoreException err) { throw new ModelerCoreException(err); } } /** * Deletes index files that are not associated with any resource in any of the open projects in the workspace. * * @throws CoreException * @since 4.2 */ protected void cleanOrphanedIndexes() throws CoreException { // collect all the projects that have been built // in the workspace IProject currentProj = getProject(); Collection builtProjects = new LinkedList(); // collect all projects in the workspace, if any of them have not been built // this method aborts if (currentProj != null) { IWorkspace workspace = currentProj.getWorkspace(); IWorkspaceRoot root = workspace.getRoot(); if (root != null) { IProject[] projects = root.getProjects(); for (int i = 0; i < projects.length; i++) { IProject project = projects[i]; if (project != null && project.isAccessible()) { // if this is not the current project being built and // the project has never been built...abort...we may be\ // in the middle of a full build in the workspace if (!super.hasBeenBuilt(project) && !currentProj.equals(project)) { // abort return; } builtProjects.add(project); } } } } if (!builtProjects.isEmpty()) { // collect all the file resources that have indexes in // all the projects final SearchIndexResourceVisitor visitor = new SearchIndexResourceVisitor(); for (final Iterator iter = builtProjects.iterator(); iter.hasNext();) { IProject proj = (IProject)iter.next(); proj.accept(visitor); } // get all the files from the location containing indexes File[] indexFiles = new File(IndexUtil.INDEX_PATH).listFiles(); for (int i = 0; i < indexFiles.length; i++) { File indexFile = indexFiles[i]; if (IndexUtil.isIndexFile(indexFile)) { String fileName = indexFile.getName(); // check the name of the file againt the name of indexes for a file resource if (!visitor.getIndexNames().contains(fileName)) { // if no resource found for the index file....get rid off it indexFile.delete(); } } } } } }