Java tutorial
/******************************************************************************* * Copyright (c) 2008, 2012 Obeo. * 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: * Obeo - initial API and implementation *******************************************************************************/ package org.eclipse.acceleo.ide.ui.resources; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.acceleo.common.IAcceleoConstants; import org.eclipse.acceleo.common.utils.CompactHashSet; import org.eclipse.acceleo.common.utils.ModelUtils; import org.eclipse.acceleo.engine.AcceleoEnginePlugin; import org.eclipse.acceleo.ide.ui.AcceleoUIActivator; import org.eclipse.acceleo.model.mtl.MtlPackage; 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.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IBundleGroup; import org.eclipse.core.runtime.IBundleGroupProvider; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPluginDescriptor; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.common.util.WrappedException; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.ocl.ecore.EcoreEnvironment; import org.eclipse.ocl.ecore.EcoreEnvironmentFactory; import org.eclipse.osgi.service.resolver.BundleDescription; import org.eclipse.pde.core.plugin.IPluginModelBase; import org.eclipse.pde.core.plugin.PluginRegistry; import org.osgi.framework.Bundle; import org.osgi.framework.Constants; /** * A Acceleo project represents a view of a project resource in terms of Acceleo elements. Each Acceleo * project has a classpath, defining which folders contain source code and where templates are located. Each * Acceleo project also has an output location. The extension of a template is '.acceleo' and the extension of * an output file is '.emtl'. * * @author <a href="mailto:jonathan.musset@obeo.fr">Jonathan Musset</a> */ public class AcceleoProject { /** * Save the found URIs of the EMTL files in the plug-ins. The key is the bundle symbolic name and the * values are the URIs of the bundle EMTL files. */ private static Map<String, List<URI>> bundle2outputFiles = new HashMap<String, List<URI>>(); /** * Indicates if the saved map is complete. */ private static boolean allBundlesOutputFilesFound; /** * Indicates if the EMF registry has been initialized. */ private static boolean registryInitialized; /** * The project. */ private IProject project; /** * The folders that contain the Acceleo sources (A Acceleo source folder is a Java source folder). */ private List<IPath> sourceFolders; /** * Output file cache for MANIFEST.MF dependencies. */ private List<URI> outputFilesWithManifest; /** * The MANIFEST.MF file modification stamp. If the modification stamp doesn't change, we haven't to * compute the MANIFEST.MF dependencies. We can use the variable 'outputFilesWithManifest' to get the * dependencies while the MANIFEST.MF file doesn't change. */ private long manifestModificationStamp = -1; /** * Constructor. * * @param project * is the project */ public AcceleoProject(IProject project) { if (!registryInitialized) { registryInitialized = true; registerPackages(); } this.project = project; this.sourceFolders = new ArrayList<IPath>(); final IJavaProject javaProject = JavaCore.create(project); IClasspathEntry[] entries; try { entries = javaProject.getResolvedClasspath(true); } catch (JavaModelException e1) { entries = new IClasspathEntry[] {}; } for (int i = 0; i < entries.length; i++) { IClasspathEntry entry = entries[i]; if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { this.sourceFolders.add(entry.getPath()); } } } /** * Register the Acceleo metamodel NsURI. */ private static void registerPackages() { if (!EPackage.Registry.INSTANCE.containsKey(MtlPackage.eINSTANCE.getNsURI())) { EPackage.Registry.INSTANCE.put(org.eclipse.ocl.ecore.EcorePackage.eINSTANCE.getNsURI(), org.eclipse.ocl.ecore.EcorePackage.eINSTANCE); EPackage.Registry.INSTANCE.put(org.eclipse.ocl.expressions.ExpressionsPackage.eINSTANCE.getNsURI(), org.eclipse.ocl.expressions.ExpressionsPackage.eINSTANCE); EPackage.Registry.INSTANCE.put("http://www.eclipse.org/ocl/1.1.0/oclstdlib.ecore", //$NON-NLS-1$ getOCLStdLibPackage()); EPackage.Registry.INSTANCE.put(MtlPackage.eINSTANCE.getNsURI(), MtlPackage.eINSTANCE); } } /** * Returns the package containing the OCL standard library. * * @return The package containing the OCL standard library. * @generated */ private static EPackage getOCLStdLibPackage() { EcoreEnvironmentFactory factory = new EcoreEnvironmentFactory(); EcoreEnvironment environment = (EcoreEnvironment) factory.createEnvironment(); return (EPackage) EcoreUtil.getRootContainer(environment.getOCLStandardLibrary().getBag()); } /** * {@inheritDoc} * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (obj instanceof AcceleoProject) { return ((AcceleoProject) obj).project.equals(project); } return false; } /** * {@inheritDoc} * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return project.getName().hashCode(); } /** * Returns a list of existing Acceleo files (Acceleo files only) in this resource. * * @return all the Acceleo files * @throws CoreException * contains a status object describing the cause of the exception */ public List<IFile> getInputFiles() throws CoreException { List<IFile> filesInput = new ArrayList<IFile>(); for (Iterator<IPath> itSourceFolders = sourceFolders.iterator(); itSourceFolders.hasNext();) { IPath sourceFolderPath = itSourceFolders.next(); if (sourceFolderPath.segmentCount() > 1) { IFolder sourceFolder = ResourcesPlugin.getWorkspace().getRoot().getFolder(sourceFolderPath); if (sourceFolder != null && sourceFolder.isAccessible()) { computeInputFiles(filesInput, sourceFolder); } } } return filesInput; } /** * Computes a list of existing Acceleo files (Acceleo files only) in this resource. * * @param filesInput * an output parameter to get all the Acceleo files * @param container * is the container to browse * @throws CoreException * contains a status object describing the cause of the exception */ private void computeInputFiles(List<IFile> filesInput, IContainer container) throws CoreException { if (container != null) { IResource[] children = container.members(); if (children != null) { for (int i = 0; i < children.length; ++i) { IResource resource = children[i]; if (resource instanceof IFile && IAcceleoConstants.MTL_FILE_EXTENSION.equals(((IFile) resource).getFileExtension())) { filesInput.add((IFile) resource); } else if (resource instanceof IContainer) { computeInputFiles(filesInput, (IContainer) resource); } } } } } /** * Gets the output file path (EMTL) for the given Acceleo file. For example : <br> * '/MyProject/src/org/eclipse/acceleo/file.acceleo' becomes * '/MyProject/bin/org/eclipse/acceleo/file.emtl' </br> * * @param fileAcceleo * is the Acceleo file * @return the output file path */ public IPath getOutputFilePath(IFile fileAcceleo) { IPath projectPath = project.getRawLocation(); if (projectPath == null) { projectPath = project.getLocation(); } IPath acceleoFilePath = fileAcceleo.getRawLocation(); if (acceleoFilePath == null) { acceleoFilePath = fileAcceleo.getLocation(); } IPath filePath = makeRelativeTo(acceleoFilePath, projectPath); IFolder folder = getOutputFolder(project); if (folder != null) { for (Iterator<IPath> itSourceFolders = sourceFolders.iterator(); itSourceFolders.hasNext();) { IPath sourcePath = makeRelativeTo(itSourceFolders.next(), project.getFullPath()); if (sourcePath.isPrefixOf(filePath)) { IPath relativePath = filePath.removeFirstSegments(sourcePath.segmentCount()); return folder.getFullPath().append(relativePath.removeFileExtension() .addFileExtension(IAcceleoConstants.EMTL_FILE_EXTENSION)); } } } return null; } /** * Gets the input file path (Acceleo) for the given EMTL file path. For example : <br> * '/MyProject/bin/org/eclipse/acceleo/file.emtl' becomes * '/MyProject/src-gen/org/eclipse/acceleo/file.acceleo' </br> * * @param fileEMTL * is the EMTL file path * @return the input file, or null if the given file isn't valid */ public IPath getInputFilePath(IPath fileEMTL) { IFolder folder = getOutputFolder(project); if (folder != null && folder.getFullPath().isPrefixOf(fileEMTL)) { IPath relativePath = fileEMTL.removeFileExtension() .addFileExtension(IAcceleoConstants.MTL_FILE_EXTENSION) .removeFirstSegments(folder.getFullPath().segmentCount()); for (Iterator<IPath> itSourceFolders = sourceFolders.iterator(); itSourceFolders.hasNext();) { IPath sourcePath = itSourceFolders.next().append(relativePath); if (ResourcesPlugin.getWorkspace().getRoot().exists(sourcePath)) { return sourcePath; } } } return null; } /** * This is a helper method returning the resolved classpath for the project as a list of simple classpath * entries. * * @return the classpath entries */ public List<IPath> getResolvedClasspath() { List<IPath> result = new ArrayList<IPath>(); final IJavaProject javaProject = JavaCore.create(project); IClasspathEntry[] entries; try { entries = javaProject.getResolvedClasspath(true); } catch (JavaModelException e1) { AcceleoUIActivator.getDefault().getLog().log(e1.getStatus()); entries = new IClasspathEntry[] {}; } for (int i = 0; i < entries.length; i++) { IClasspathEntry entry = entries[i]; result.add(entry.getPath()); } return result; } /** * Gets the full name of the package which contains the Acceleo file. For example : <br> * '/MyProject/src/org/eclipse/acceleo/file.acceleo' becomes 'org.eclipse.acceleo' </br> * * @param fileAcceleo * is the Acceleo file * @return the full name of the package, or an empty string if the file is not valid */ public String getPackageName(IFile fileAcceleo) { IPath projectPath = project.getRawLocation(); if (projectPath == null) { projectPath = project.getLocation(); } IPath acceleoFilePath = fileAcceleo.getRawLocation(); if (acceleoFilePath == null) { acceleoFilePath = fileAcceleo.getLocation(); } IPath filePath = makeRelativeTo(acceleoFilePath, projectPath); for (Iterator<IPath> itSourceFolders = sourceFolders.iterator(); itSourceFolders.hasNext();) { IPath sourcePath = makeRelativeTo(itSourceFolders.next(), project.getFullPath()); if (sourcePath.isPrefixOf(filePath)) { StringBuffer name = new StringBuffer(); String[] segments = filePath.removeFirstSegments(sourcePath.segmentCount()).removeLastSegments(1) .segments(); for (int i = 0; i < segments.length; i++) { if (i > 0) { name.append("."); //$NON-NLS-1$ } name.append(segments[i]); } return name.toString(); } } return ""; //$NON-NLS-1$ } /** * Gets the output folder of the project. For example : '/MyProject/bin'. * * @param aProject * is a project of the workspace * @return the output folder of the project, or null if it doesn't exist * @see org.eclipse.acceleo.internal.ide.ui.editors.template.actions.refactor.AcceleoRefactoringUtils#getOutputFolder(IProject * aProject) */ private static IFolder getOutputFolder(IProject aProject) { final IJavaProject javaProject = JavaCore.create(aProject); try { IPath output = javaProject.getOutputLocation(); if (output != null && output.segmentCount() > 1) { IFolder folder = aProject.getWorkspace().getRoot().getFolder(output); if (folder.isAccessible()) { return folder; } } } catch (JavaModelException e) { // continue AcceleoUIActivator.getDefault().getLog().log(e.getStatus()); } return null; } /** * Gets all the output files (EMTL) of this project. It means the files of the project and not the files * of the required plugins. * * @return the URIs of the output files, there are only 'workspace' URIs... */ public List<URI> getOutputFiles() { List<URI> outputURIs = new ArrayList<URI>(); computeAccessibleOutputFilesInFolder(outputURIs, getOutputFolder(project)); return outputURIs; } /** * Gets all the accessible output files (EMTL) of this project. It means the files of the project and the * files of the required plugins. * * @return the URIs of the output files, there are 'plugin' URIs and 'workspace' URIs... */ public List<URI> getAccessibleOutputFiles() { List<URI> outputURIs = new ArrayList<URI>(); computeAccessibleOutputFilesInFolder(outputURIs, getOutputFolder(project)); computeAccessibleOutputFilesWithPluginXML(outputURIs, project); computeAccessibleOutputFilesWithProjectDependencies(outputURIs, project); return outputURIs; } /** * Computes the URIs of all the accessible output files (EMTL) in the given folder. * * @param outputURIs * is an output parameter with all the URIs * @param folder * is the folder to browse */ private static void computeAccessibleOutputFilesInFolder(List<URI> outputURIs, IContainer folder) { if (folder == null) { return; } try { IResource[] members = folder.members(); for (int i = 0; i < members.length; i++) { IResource member = members[i]; if (member instanceof IFile) { if (IAcceleoConstants.EMTL_FILE_EXTENSION.equals(((IFile) member).getFileExtension())) { URI uri = URI.createPlatformResourceURI(((IFile) member).getFullPath().toString(), false); if (!outputURIs.contains(uri)) { outputURIs.add(uri); } } } else if (member instanceof IContainer) { computeAccessibleOutputFilesInFolder(outputURIs, (IContainer) member); } } } catch (CoreException e) { AcceleoUIActivator.getDefault().getLog() .log(new Status(IStatus.ERROR, AcceleoUIActivator.PLUGIN_ID, e.getMessage(), e)); } } /** * Returns the URIs of the emtl files in the required plugin of the given project. * * @param project * The project * @return The URIs of the emtl files in the required plugin of the given project. * @since 3.3 */ public static List<URI> computeAcceleoModuleInRequiredPlugins(IProject project) { List<URI> uris = new ArrayList<URI>(); AcceleoProject acceleoProject = new AcceleoProject(project); acceleoProject.computeAccessibleOutputFilesWithPluginXML(uris, project); return uris; } /** * Computes the URIs of all the accessible output files (EMTL) in the dependencies of the current plug-in * (project). It browses all the required plug-ins declared in the 'plugin.xml' file. * * @param outputURIs * is an output parameter with all the URIs * @param aProject * is the current plug-in */ private void computeAccessibleOutputFilesWithPluginXML(List<URI> outputURIs, IProject aProject) { IFile manifest = aProject.getFile(new Path("META-INF/MANIFEST.MF")); //$NON-NLS-1$ if (outputFilesWithManifest == null || (manifest.isAccessible() && manifest.getModificationStamp() != manifestModificationStamp)) { outputFilesWithManifest = new ArrayList<URI>(); manifestModificationStamp = manifest.getModificationStamp(); IPluginModelBase plugin = PluginRegistry.findModel(aProject); if (plugin != null && plugin.getBundleDescription() != null) { BundleDescription[] requiredPlugins = plugin.getBundleDescription().getResolvedRequires(); for (int i = 0; i < requiredPlugins.length; i++) { String requiredSymbolicName = requiredPlugins[i].getSymbolicName(); IProject requiredProject = ResourcesPlugin.getWorkspace().getRoot() .getProject(requiredSymbolicName); if (requiredProject != null && requiredProject.isAccessible()) { computeAccessibleOutputFilesInFolder(outputFilesWithManifest, getOutputFolder(requiredProject)); } else { computeAccessibleOutputFilesWithBundle(outputFilesWithManifest, Platform.getBundle(requiredSymbolicName)); } } } } for (URI uri : outputFilesWithManifest) { if (!outputURIs.contains(uri)) { outputURIs.add(uri); } } } /** * Computes the URIs of all the accessible output files (EMTL) in the given bundle. The bundle represents * a plug-in. It browses all the entries of the bundle, to get the '.emtl' files. * * @param outputURIs * is an output parameter with all the URIs * @param bundle * is the current bundle */ private static void computeAccessibleOutputFilesWithBundle(List<URI> outputURIs, Bundle bundle) { if (bundle != null) { if (bundle.getState() == Bundle.RESOLVED || bundle.getState() == Bundle.ACTIVE || bundle.getState() == Bundle.INSTALLED || bundle.getState() == Bundle.STARTING) { outputURIs.addAll(getOrCreatePlatformPluginSavedURIs(bundle)); } } } /** * Computes the URIs of all the accessible output files (EMTL) in the dependencies of the current project. * It browses the resolved classpath of the java project, and keeps each entry of type * 'IClasspathEntry.CPE_PROJECT'. * * @param outputURIs * is an output parameter with all the URIs * @param aProject * is the current project */ private void computeAccessibleOutputFilesWithProjectDependencies(List<URI> outputURIs, IProject aProject) { final IJavaProject javaProject = JavaCore.create(aProject); IClasspathEntry[] entries; try { entries = javaProject.getResolvedClasspath(true); } catch (JavaModelException e1) { AcceleoUIActivator.getDefault().getLog().log(e1.getStatus()); entries = new IClasspathEntry[] {}; } for (int i = 0; i < entries.length; i++) { IClasspathEntry entry = entries[i]; if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) { IProject requiredProject = ResourcesPlugin.getWorkspace().getRoot() .getProject(entry.getPath().toString()); if (requiredProject != null && requiredProject.exists()) { computeAccessibleOutputFilesInFolder(outputURIs, getOutputFolder(requiredProject)); } } } } /** * Gets all the accessible Acceleo projects of the workspace. It means that the current project is * included. * * @return the accessible Acceleo projects */ public List<AcceleoProject> getRecursivelyAccessibleAcceleoProjects() { List<AcceleoProject> result = new ArrayList<AcceleoProject>(); for (IProject aProject : getRecursivelyAccessibleProjects()) { try { if (aProject.isAccessible() && aProject.hasNature(IAcceleoConstants.ACCELEO_NATURE_ID)) { result.add(new AcceleoProject(aProject)); } } catch (CoreException e) { AcceleoUIActivator.getDefault().getLog().log(e.getStatus()); } } return result; } /** * Gets all the accessible projects of the workspace. It means that the current project is included. * * @return the accessible projects * @since 3.0 */ public List<IProject> getRecursivelyAccessibleProjects() { List<IProject> result = new ArrayList<IProject>(); computeAccessibleProjects(result, project); return result; } /** * Computes all the accessible projects. * * @param accessibleProjects * is the output list that will contain all the accessible projects * @param current * is the current project */ private void computeAccessibleProjects(List<IProject> accessibleProjects, IProject current) { if (!accessibleProjects.contains(current)) { accessibleProjects.add(current); IPluginModelBase plugin = PluginRegistry.findModel(current); if (plugin != null && plugin.getBundleDescription() != null) { BundleDescription[] requiredPlugins = plugin.getBundleDescription().getResolvedRequires(); for (int i = 0; i < requiredPlugins.length; i++) { String requiredSymbolicName = requiredPlugins[i].getSymbolicName(); IProject requiredProject = ResourcesPlugin.getWorkspace().getRoot() .getProject(requiredSymbolicName); if (requiredProject != null && requiredProject.isAccessible()) { computeAccessibleProjects(accessibleProjects, requiredProject); } } } final IJavaProject javaProject = JavaCore.create(current); IClasspathEntry[] entries; try { entries = javaProject.getResolvedClasspath(true); } catch (JavaModelException e1) { AcceleoUIActivator.getDefault().getLog().log(e1.getStatus()); entries = new IClasspathEntry[] {}; } for (int i = 0; i < entries.length; i++) { IClasspathEntry entry = entries[i]; if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) { IProject requiredProject = ResourcesPlugin.getWorkspace().getRoot() .getProject(entry.getPath().toString()); if (requiredProject != null && requiredProject.exists()) { computeAccessibleProjects(accessibleProjects, requiredProject); } } } } } /** * Gets in a single resource set all the accessible AST resources (EMTL). It means the files of the * project and the files of the required plugins. You must unload the resources of the returned resource * set by yourself. * * @return a resource set which contains all the accessible resources * @deprecated It's a long time operation, the monitor allows the operation to be canceled. Now you have * to use : loadAccessibleOutputFiles(IProgressMonitor monitor) */ @Deprecated public ResourceSet loadAccessibleOutputFiles() { return loadAccessibleOutputFiles(new NullProgressMonitor()); } /** * Gets in a single resource set all the accessible AST resources (EMTL). It means the files of the * project and the files of the required plugins. You must unload the resources of the returned resource * set by yourself. * * @param monitor * is the monitor * @return a resource set which contains all the accessible resources * @since 3.0 */ public ResourceSet loadAccessibleOutputFiles(IProgressMonitor monitor) { ResourceSet oResourceSet = new ResourceSetImpl(); List<URI> outputURIs = getAccessibleOutputFiles(); for (Iterator<URI> itOutputURIs = outputURIs.iterator(); itOutputURIs.hasNext() && !monitor.isCanceled();) { URI oURI = itOutputURIs.next(); try { ModelUtils.load(oURI, oResourceSet); } catch (WrappedException e) { // continue and do nothing because it occurs when the EMTL file has been deleted } catch (IOException e) { // continue and do nothing because it occurs when the EMTL file has been deleted } } return oResourceSet; } /** * Gets in a single resource set all the not accessible AST resources (EMTL). It means all the EMTL files * of the Eclipse instance (plugin and workspace) not in the project and not in the required plugins. You * must unload the resources of the returned resource set by yourself. * * @param monitor * is the monitor * @return a resource set which contains all the not accessible resources * @since 3.0 */ public ResourceSet loadNotAccessibleOutputFiles(IProgressMonitor monitor) { return loadAllPlatformOutputFiles(this, monitor); } /** * Gets in a single resource set all the EMTL files of the Eclipse instance, it means in the plug-ins and * in the workspace. You must unload the resources of the returned resource set by yourself. * * @param monitor * is the monitor * @return a resource set which contains all the not accessible resources * @since 3.0 */ public static ResourceSet loadAllPlatformOutputFiles(IProgressMonitor monitor) { if (!registryInitialized) { registryInitialized = true; registerPackages(); } return loadAllPlatformOutputFiles(null, monitor); } /** * Gets in a single resource set all the EMTL files of the Eclipse instance, it means in the plug-ins and * in the workspace. You must unload the resources of the returned resource set by yourself. We can ignore * the accessible output files, it means all the EMTL files of the given project and its required plugins. * * @param excludeAccessible * the accessible output files we want to exclude, null indicates that we don't want to ignore * anything * @param monitor * is the monitor * @return a resource set which contains all the not accessible resources */ private static ResourceSet loadAllPlatformOutputFiles(AcceleoProject excludeAccessible, IProgressMonitor monitor) { ResourceSet oResourceSet = new ResourceSetImpl(); List<URI> outputURIs = new ArrayList<URI>(); for (IProject aProject : ResourcesPlugin.getWorkspace().getRoot().getProjects()) { try { if (aProject.isAccessible() && aProject.hasNature(IAcceleoConstants.ACCELEO_NATURE_ID)) { computeAccessibleOutputFilesInFolder(outputURIs, getOutputFolder(aProject)); } } catch (CoreException e) { AcceleoUIActivator.getDefault().getLog().log(e.getStatus()); } } outputURIs.addAll(getAllPlatformPluginOutputFiles()); List<URI> excludeURIs; if (excludeAccessible != null) { excludeURIs = excludeAccessible.getAccessibleOutputFiles(); } else { excludeURIs = null; } for (Iterator<URI> itOutputURIs = outputURIs.iterator(); itOutputURIs.hasNext() && !monitor.isCanceled();) { URI oURI = itOutputURIs.next(); if (excludeURIs == null || !excludeURIs.contains(oURI)) { try { ModelUtils.load(oURI, oResourceSet); } catch (WrappedException e) { // continue and do nothing because it occurs when the EMTL file has been deleted } catch (IOException e) { // continue and do nothing because it occurs when the EMTL file has been deleted } } } return oResourceSet; } /** * Gets the URIs of all the EMTL files in the workspace. * * @return the URIs of all the EMTL files * @since 3.0 */ public static List<URI> getAllPlatformResourceOutputFiles() { List<URI> outputURIs = new ArrayList<URI>(); IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); for (IProject aProject : projects) { try { if (aProject.isAccessible() && aProject.hasNature(IAcceleoConstants.ACCELEO_NATURE_ID)) { computeAccessibleOutputFilesInFolder(outputURIs, getOutputFolder(aProject)); } } catch (CoreException e) { AcceleoUIActivator.getDefault().getLog().log(e.getStatus()); } } return outputURIs; } /** * Returns the URIs of the EMTL files in the bundle dependencies of the given project. * * @param project * The project * @return The URIs of the EMTL files in the bundle dependencies of the given project. * @since 3.3 */ public static List<URI> getAccessiblePluginModules(IProject project) { List<URI> outputURIs = new ArrayList<URI>(); List<String> bundles = new ArrayList<String>(); IPluginModelBase plugin = PluginRegistry.findModel(project); if (plugin != null && plugin.getBundleDescription() != null) { BundleDescription[] requiredPlugins = plugin.getBundleDescription().getResolvedRequires(); for (int i = 0; i < requiredPlugins.length; i++) { String requiredSymbolicName = requiredPlugins[i].getSymbolicName(); bundles.add(requiredSymbolicName); } } for (String bundle : bundles) { outputURIs.addAll(bundle2outputFiles.get(bundle)); } return outputURIs; } /** * Gets the URIs of all the EMTL files in the plug-ins. It also creates the EMTL files if only the MTL * files are available. The workspace files are ignored. * * @return the URIs of all the EMTL files * @since 3.0 */ public static List<URI> getAllPlatformPluginOutputFiles() { List<URI> outputURIs = new ArrayList<URI>(); if (!allBundlesOutputFilesFound) { Set<String> done = new CompactHashSet<String>(); IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); for (IProject aProject : projects) { try { if (aProject.isAccessible() && aProject.hasNature(IAcceleoConstants.ACCELEO_NATURE_ID)) { done.add(aProject.getName()); } } catch (CoreException e) { AcceleoUIActivator.getDefault().getLog().log(e.getStatus()); } } IBundleGroupProvider[] providers = Platform.getBundleGroupProviders(); for (IBundleGroupProvider provider : providers) { for (IBundleGroup group : provider.getBundleGroups()) { for (Bundle bundle : group.getBundles()) { String name = bundle.getSymbolicName(); if (!done.contains(name)) { if (bundle.getState() == Bundle.RESOLVED || bundle.getState() == Bundle.ACTIVE || bundle.getState() == Bundle.INSTALLED || bundle.getState() == Bundle.STARTING) { done.add(name); outputURIs.addAll(getOrCreatePlatformPluginSavedURIs(bundle)); } } } } } // Deprecated? Yes, but the following API give more results for (IPluginDescriptor descriptor : Platform.getPluginRegistry().getPluginDescriptors()) { String name = descriptor.getUniqueIdentifier(); if (!done.contains(name)) { done.add(name); Bundle bundle = Platform.getBundle(name); if (bundle != null) { outputURIs.addAll(getOrCreatePlatformPluginSavedURIs(bundle)); } } } allBundlesOutputFilesFound = true; } else { for (List<URI> values : bundle2outputFiles.values()) { outputURIs.addAll(values); } } return outputURIs; } /** * Gets and saves the URIs of all the EMTL files in the plug-ins. The workspace files are ignored. We * search the URIs only one time, because the bundles won't change. This method only saves the found URIs * of the EMTL files for the given plug-in. * * @param bundle * is the OSGI bundle of the plug-in * @return the URIs of all the EMTL files in the plug-ins */ private static List<URI> getOrCreatePlatformPluginSavedURIs(Bundle bundle) { String name = bundle.getSymbolicName(); List<URI> savedURIs = bundle2outputFiles.get(name); if (savedURIs == null) { savedURIs = new ArrayList<URI>(); bundle2outputFiles.put(name, savedURIs); String required = (String) bundle.getHeaders().get(Constants.REQUIRE_BUNDLE); if (required != null && required.indexOf(AcceleoEnginePlugin.PLUGIN_ID) != -1) { computeSaveURIs(bundle, savedURIs); } } return savedURIs; } /** * Computes the saved URIs of the given bundle. * * @param bundle * the bundle to browse * @param savedURIs * the EMTL files URIs to get, it is an input/output parameter */ @SuppressWarnings("unchecked") private static void computeSaveURIs(Bundle bundle, List<URI> savedURIs) { // The first time we would like to be sure to extract the MTL files of the plug-in jar. Enumeration<URL> entriesMTL = bundle.findEntries("/", "*." + IAcceleoConstants.MTL_FILE_EXTENSION, true); //$NON-NLS-1$ //$NON-NLS-2$ Enumeration<URL> entriesEMTL = bundle.findEntries("/", "*." + IAcceleoConstants.EMTL_FILE_EXTENSION, true); //$NON-NLS-1$ //$NON-NLS-2$ if (entriesEMTL != null && entriesEMTL.hasMoreElements()) { while (entriesEMTL.hasMoreElements()) { URL entry = entriesEMTL.nextElement(); if (entry != null) { IPath path = new Path(entry.getPath()); if (path.segmentCount() > 0) { savedURIs.add(URI.createPlatformPluginURI( new Path(bundle.getSymbolicName()).append(path).toString(), false)); } } } } } /** * Returns the list of source folders in the project. * * @return The list of source folders in the project. * @since 3.1 */ public List<IPath> getSourceFolders() { // We create a copy to prevent problems. return new ArrayList<IPath>(this.sourceFolders); } /** * Make relative to. * * @param path1 * The first path * @param path2 * the second path * @return The first path relative to the second path. * @since 3.1 */ public static IPath makeRelativeTo(IPath path1, IPath path2) { IPath path = path1; // can't make relative if devices are not equal if (path1.getDevice() == path2.getDevice() || (path1.getDevice() != null && path1.getDevice().equalsIgnoreCase(path2.getDevice()))) { int commonLength = path1.matchingFirstSegments(path2); final int differenceLength = path2.segmentCount() - commonLength; final int newSegmentLength = differenceLength + path1.segmentCount() - commonLength; if (newSegmentLength == 0) { return Path.EMPTY; } path = new Path(""); //$NON-NLS-1$ String[] newSegments = new String[newSegmentLength]; // add parent references for each segment different from the base Arrays.fill(newSegments, 0, differenceLength, ".."); //$NON-NLS-1$ // append the segments of this path not in common with the base System.arraycopy(path1.segments(), commonLength, newSegments, differenceLength, newSegmentLength - differenceLength); for (String segment : newSegments) { path = path.append(new Path(segment)); } } return path; } }