/* * 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.workspace; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRunnable; 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.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.teiid.core.designer.util.CoreArgCheck; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.container.Container; import org.teiid.designer.core.refactor.ModelResourceCollectorVisitor; /** * ModelWorkspaceImpl * * @since 8.0 */ public class ModelWorkspaceImpl extends OpenableImpl implements ModelWorkspace { // ============================================================================================================================ // Constants private static final String[] MODEL_NATURES = new String[] {ModelerCore.NATURE_ID}; /** * A set of java.io.Files used as a cache of external jars that are known to be existing. Note this cache is kept for the * whole session. */ public static HashSet existingExternalFiles = new HashSet(); /** * Flushes the cache of external files known to be existing. */ public static void flushExternalFileCache() { existingExternalFiles = new HashSet(); } /** * Helper method - returns the targeted item (IResource if internal or java.io.File if external), or null if unbound Internal * items must be referred to using container relative paths. */ public static Object getTarget( IContainer container, IPath path, boolean checkResourceExistence ) { if (path == null) return null; // lookup - inside the container if (path.getDevice() == null) { // container relative paths should not contain a device // (see http://dev.eclipse.org/bugs/show_bug.cgi?id=18684) // (case of a workspace rooted at d:\ ) IResource resource = container.findMember(path); if (resource != null) { if (!checkResourceExistence || resource.exists()) return resource; return null; } } // if path is relative, it cannot be an external path // (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517) if (!path.isAbsolute()) return null; // lookup - outside the container File externalFile = new File(path.toOSString()); if (!checkResourceExistence) { return externalFile; } else if (existingExternalFiles.contains(externalFile)) { return externalFile; } else { if (ModelWorkspaceManager.ZIP_ACCESS_VERBOSE) { System.out.println("(" + Thread.currentThread() + ") [ModelWorkspaceImpl.getTarget(...)] Checking existence of " + path.toString()); //$NON-NLS-1$ //$NON-NLS-2$ } if (externalFile.exists()) { // cache external file existingExternalFiles.add(externalFile); return externalFile; } } return null; } /** * Construct an instance of ModelProjectImpl. */ ModelWorkspaceImpl() { super(MODEL_WORKSPACE, null, "" /*workspace has empty name*/); //$NON-NLS-1$ } /** * @see org.teiid.designer.core.workspace.ModelWorkspaceItem */ @Override public IPath getPath() { return Path.ROOT; } /** * @see org.teiid.designer.core.workspace.ModelWorkspaceItem */ @Override public IResource getResource() { return getWorkspace().getRoot(); } /** * @see org.teiid.designer.core.workspace.Openable */ @Override public IResource getUnderlyingResource() { return null; } /** * Returns the workbench associated with this object. */ @Override public IWorkspace getWorkspace() { return ModelerCore.getWorkspace(); } /** * @see org.teiid.designer.core.workspace.Openable */ @Override protected boolean generateInfos( final OpenableModelWorkspaceItemInfo info, final IProgressMonitor pm, final IResource underlyingResource ) { ModelWorkspaceManager.getModelWorkspaceManager().putInfo(this, info); // determine my children Collection<IProject> projects = DotProjectUtils.getOpenModelProjects(); for (IProject project : projects) { info.addChild(getModelProject(project)); } return true; } /** * @see org.teiid.designer.core.workspace.ModelWorkspace#findModelProject(java.lang.String) */ @Override public ModelProject findModelProject( final String name ) { CoreArgCheck.isNotNull(name); try { final ModelProject[] projects = getModelProjects(); for (int ndx = projects.length; --ndx >= 0;) { final ModelProject project = projects[ndx]; if (name.equals(project.getItemName())) { return project; } } } catch (ModelWorkspaceException e) { ModelerCore.Util.log(e); } return null; } /** * @see org.teiid.designer.core.workspace.ModelWorkspace#findModelProject(IResource) */ @Override public ModelProject findModelProject( final IResource resource ) { CoreArgCheck.isNotNull(resource); // if(!ModelerCore.hasModelNature(resource.getProject())) { // return null; // } IProject rsrcProject = null; switch (resource.getType()) { case IResource.FOLDER: rsrcProject = ((IFolder)resource).getProject(); break; case IResource.FILE: rsrcProject = ((IFile)resource).getProject(); break; case IResource.PROJECT: rsrcProject = (IProject)resource; break; case IResource.ROOT: default: // throw new IllegalArgumentException("Invalid resource type, {0}, for IResource {1}"); } try { final ModelProject[] projects = getModelProjects(); for (int ndx = projects.length; --ndx >= 0;) { final ModelProject mdlProject = projects[ndx]; if (rsrcProject != null && rsrcProject.equals(mdlProject.getResource())) { return mdlProject; } } } catch (ModelWorkspaceException e) { // do nothing } return null; } @Override public ModelWorkspaceItem getParent( final IResource resource ) { CoreArgCheck.isNotNull(resource); IProject project = resource.getProject(); if (project.isAccessible() && !ModelerCore.hasModelNature(project)) { return null; } // If the resource is an IProject... return the resource if (resource instanceof IProject) { return this; } // If the parent is null, return null final IResource parent = resource.getParent(); if (parent == null) { return null; } // Calculate the parent path from the given resource final IPath path = resource.getFullPath(); final IPath parentPath = path.removeLastSegments(1); // Find the workspaceItem for the parent path1 return getWorkspaceItem(parentPath); } public ModelWorkspaceItem getWorkspaceItem( final IPath path, int resourceType ) { CoreArgCheck.isNotNull(path); try { // first get all the projects ModelProject[] projects = getModelProjects(); for (int i = 0; i < projects.length; i++) { ModelProject project = projects[i]; if (resourceType == IResource.PROJECT) { if (project.getPath().equals(path)) { return project; } } else { if (!project.isOpen()) { continue; } // If the path only contains the project then we cannot match it // to a non-project type so return null if (path.segmentCount() < 2) { return null; } // If the first segment is not this project's name then skip it if (!path.segment(0).equals(project.getProject().getName())) { continue; } // Iterate over all the path segments navigating to the child by name ModelWorkspaceItem item = project; final String[] segments = path.segments(); for (int j = 1; j < segments.length; j++) { final String segment = segments[j]; if (!item.exists()) { // Must be in the process of closing (see defect 10957) ... return null; } item = item.getChild(segment); if (item == null) { break; } else if (item.getPath().makeRelative().equals(path.makeRelative())) { return item; } } // ModelWorkspaceItem[] children = project.getChildren(); // return recursiveLookUp(children, path); } } } catch (ModelWorkspaceException e) { // do nothing } return null; } public ModelWorkspaceItem getWorkspaceItem( final IPath path ) { CoreArgCheck.isNotNull(path); try { // first get all the projects ModelProject[] projects = getModelProjects(); for (int i = 0; i < projects.length; i++) { ModelProject project = projects[i]; if (!project.exists()) { continue; } if (!project.isOpen()) { // See if the underlying project is open ... final IProject iproj = (IProject)project.getResource(); if (!iproj.isOpen()) { continue; } // Try to open the ModelProject, since the IProject is open ... project.open(null); if (!project.isOpen()) { continue; // couldn't open it! } } if (project.getPath().equals(path)) { return project; } // Iterate over all the path segments navigating to the child by name ModelWorkspaceItem item = project; final String[] segments = path.segments(); for (int j = 1; j < segments.length; j++) { final String segment = segments[j]; if (!item.exists()) { // Must be in the process of closing (see defect 10957) ... return null; } final IResource itemResource = item.getResource(); item = item.getChild(segment); if (item == null) { // May be a newly created IResource for which there is yet no ModelWorkspaceItem if (itemResource instanceof IContainer) { final IContainer itemContainer = (IContainer)itemResource; final IResource child = itemContainer.findMember(segment); if (child != null) { // Find the ModelWorkspaceItem ... item = ModelWorkspaceManager.getModelWorkspaceManager().findModelWorkspaceItem(child, true); } } } if (item == null) { break; } else if (item.getPath().equals(path)) { return item; } } } } catch (ModelWorkspaceException e) { // do nothing } return null; } /** * @see org.teiid.designer.core.workspace.ModelWorkspace#createModelProject(java.lang.String, java.lang.String, * org.eclipse.core.runtime.IProgressMonitor) * @since 4.0 */ @Override public ModelProject createModelProject( final String name, final IPath path, final IProgressMonitor monitor ) throws CoreException { CoreArgCheck.isNotNull(name); // Check if project already exists if (findModelProject(name) != null) { throw new ModelWorkspaceException(ModelerCore.Util.getString("ModelWorkspaceImpl.cannotCreateModelProject", name)); //$NON-NLS-1$ } // Validate name final IWorkspace workspace = ModelerCore.getWorkspace(); final IStatus status = workspace.validateName(name, IResource.PROJECT); if (!status.isOK()) { throw new ModelWorkspaceException(new ModelStatusImpl(status.getSeverity(), status.getCode(), status.getMessage())); } // Create new model project final IProject project = workspace.getRoot().getProject(name); final IProjectDescription desc = workspace.newProjectDescription(project.getName()); desc.setLocation(path); desc.setNatureIds(MODEL_NATURES); final IWorkspaceRunnable op = new IWorkspaceRunnable() { @Override public void run( final IProgressMonitor monitor ) throws CoreException { project.create(desc, monitor); project.open(monitor); } }; workspace.run(op, monitor); return new ModelProjectImpl(project, this); } /** * Returns the active Model project associated with the specified resource, or <code>null</code> if no Model project yet * exists for the resource. * * @exception IllegalArgumentException if the given resource is not one of an IProject, IFolder, IRoot or IFile. * @see ModelWorkspace */ @Override public ModelProject getModelProject( final IResource resource ) { IProject project = resource.getProject(); if (project == null || ! project.isOpen()) return null; if (!DotProjectUtils.isModelerProject(project)) { return null; } // Only if the modelling project is open, is a partner model project created ModelProject modelProject = findModelProject(resource); if (modelProject == null) { switch (resource.getType()) { case IResource.FOLDER: case IResource.FILE: case IResource.PROJECT: return new ModelProjectImpl(project, this); case IResource.ROOT: return null; default: throw new IllegalArgumentException( ModelerCore.Util.getString("ModelWorkspaceImpl.Invalid_resource_for_ModelProject", resource, this)); //$NON-NLS-1$ } } return modelProject; } /** * @see ModelWorkspace */ @Override public ModelProject[] getModelProjects() throws ModelWorkspaceException { ArrayList list = getChildrenOfType(MODEL_PROJECT); ModelProject[] array = new ModelProject[list.size()]; list.toArray(array); return array; } /** * @see org.teiid.designer.core.workspace.ModelWorkspace#getModelResources() * @since 4.2 */ @Override public ModelResource[] getModelResources() throws CoreException { List temp = new ArrayList(); ModelProject[] projects = getModelProjects(); for (int i = 0; i < projects.length; ++i) { ModelProject mProject = projects[i]; ModelResourceCollectorVisitor visitor = new ModelResourceCollectorVisitor(); if (mProject != null && mProject.isOpen() && mProject.getProject().isOpen()) { mProject.getProject().accept(visitor); temp.addAll(visitor.getModelResources()); } } ModelResource[] modelResources = new ModelResource[temp.size()]; temp.toArray(modelResources); return modelResources; } /** * @see org.teiid.designer.core.workspace.ModelWorkspace#getEmfResources() * @since 4.2 */ @Override public Resource[] getEmfResources() throws CoreException { Resource[] result = null; ModelResource[] modelResources = getModelResources(); if (modelResources.length == 0) { result = new Resource[0]; } else { List temp = new ArrayList(modelResources.length); for (int i = 0; i < modelResources.length; ++i) { try { Resource resource = modelResources[i].getEmfResource(); if (resource != null) { temp.add(resource); } } catch (ModelWorkspaceException theException) { // unable to load. could be a duplicate model or a corrupted model. ModelerCore.Util.log(theException); } } result = (Resource[])temp.toArray(new Resource[temp.size()]); } return result; } /* (non-Javadoc) * @see org.teiid.designer.core.workspace.OpenableImpl#createItemInfo() */ @Override protected OpenableModelWorkspaceItemInfo createItemInfo() { return new ModelWorkspaceInfo(); } /* (non-Javadoc) * @See org.teiid.designer.core.workspace.ModelWorkspace#findModelResource(org.eclipse.emf.ecore.resource.Resource) */ @Override public ModelResource findModelResource( final IResource resource ) { CoreArgCheck.isNotNull(resource); if (!ModelUtil.isModelFile(resource)) { return null; } return (ModelResource)getWorkspaceItem(resource.getFullPath(), IResource.FILE); } /* (non-Javadoc) * @See org.teiid.designer.core.workspace.ModelWorkspace#findModelResource(org.eclipse.emf.ecore.resource.Resource) */ @Override public ModelResource findModelResource( final Resource resource ) { CoreArgCheck.isNotNull(resource); return ModelWorkspaceManager.getModelWorkspaceManager().findModelResource(resource); } /** * @see org.teiid.designer.core.workspace.ModelWorkspace#findModelResource(IPath) */ @Override public ModelResource findModelResource( final IPath pathInWorkspace ) { CoreArgCheck.isNotNull(pathInWorkspace); try { ModelWorkspaceItem item = this; final String[] segments = pathInWorkspace.segments(); for (int i = 0; i < segments.length; ++i) { final String segment = segments[i]; if (item == null) { break; } item = item.getChild(segment); } if (item == null || item.getItemType() != ModelWorkspaceItem.MODEL_RESOURCE) { return null; } return (ModelResource)item; } catch (ModelWorkspaceException e) { ModelerCore.Util.log(e); } return null; } /* (non-Javadoc) * @See org.teiid.designer.core.workspace.ModelWorkspace#findModelResource(org.eclipse.emf.ecore.EObject) */ @Override public ModelResource findModelResource( final EObject eObject ) { CoreArgCheck.isNotNull(eObject); try { final Container container = ModelerCore.getModelContainer(); Resource resource = ModelerCore.getModelEditor().findResource(container, eObject, false); if (resource != null) { return findModelResource(resource); } } catch (CoreException err) { ModelerCore.Util.log(err); } return null; } /* (non-Javadoc) * @See org.teiid.designer.core.workspace.ModelWorkspace#addNotificationListener(org.teiid.designer.core.workspace.ModelWorkspaceNotificationListener) */ @Override public void addNotificationListener( ModelWorkspaceNotificationListener listener ) { CoreArgCheck.isNotNull(listener); ModelWorkspaceManager.getModelWorkspaceManager().addNotificationListener(listener); } /* (non-Javadoc) * @See org.teiid.designer.core.workspace.ModelWorkspace#removeNotificationListener(org.teiid.designer.core.workspace.ModelWorkspaceNotificationListener) */ @Override public void removeNotificationListener( ModelWorkspaceNotificationListener listener ) { CoreArgCheck.isNotNull(listener); ModelWorkspaceManager.getModelWorkspaceManager().removeNotificationListener(listener); } /** * @see org.teiid.designer.core.workspace.ModelWorkspace#addModelResourceReloadVetoListener(org.teiid.designer.core.workspace.ModelResourceReloadVetoListener) * @since 4.2 */ @Override public void addModelResourceReloadVetoListener( ModelResourceReloadVetoListener listener ) { CoreArgCheck.isNotNull(listener); ModelWorkspaceManager.getModelWorkspaceManager().addModelResourceReloadVetoListener(listener); } /** * @see org.teiid.designer.core.workspace.ModelWorkspace#removeModelResourceReloadVetoListener(org.teiid.designer.core.workspace.ModelResourceReloadVetoListener) * @since 4.2 */ @Override public void removeModelResourceReloadVetoListener( ModelResourceReloadVetoListener listener ) { CoreArgCheck.isNotNull(listener); ModelWorkspaceManager.getModelWorkspaceManager().removeModelResourceReloadVetoListener(listener); } }