| /** |
| * Copyright (c) 2002-2006 IBM Corporation and others. |
| * 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: |
| * IBM - Initial API and implementation |
| */ |
| package org.eclipse.emf.codegen.jet; |
| |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.StringWriter; |
| import java.io.UnsupportedEncodingException; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.ListIterator; |
| import java.util.StringTokenizer; |
| |
| 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.IWorkspaceRoot; |
| import org.eclipse.core.resources.IWorkspaceRunnable; |
| import org.eclipse.core.resources.IncrementalProjectBuilder; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| 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.codegen.CodeGenPlugin; |
| import org.eclipse.emf.common.CommonPlugin; |
| import org.eclipse.emf.common.util.BasicMonitor; |
| import org.eclipse.emf.common.util.DiagnosticException; |
| import org.eclipse.emf.common.util.URI; |
| |
| |
| public class JETCompileTemplateOperation implements IWorkspaceRunnable |
| { |
| protected static final String JET_EXTENSION = "jet"; |
| |
| protected IProject project; |
| protected Collection<?> containers; |
| protected List<Object> files = new ArrayList<Object>(); |
| protected boolean inBuild; |
| |
| /** |
| * Creates an instance given the collection of resources. |
| */ |
| public JETCompileTemplateOperation(IProject project, Collection<?> containers) throws CoreException |
| { |
| this.project = project; |
| this.containers = containers; |
| for (Object container : containers) |
| { |
| if (container instanceof IContainer) |
| { |
| consider((IContainer)container); |
| } |
| else |
| { |
| consider(container.toString()); |
| } |
| } |
| } |
| |
| /** |
| * Creates an instance given the collection of resources. |
| */ |
| public JETCompileTemplateOperation(IProject project, Collection<?> containers, Collection<?> resources) throws CoreException |
| { |
| super(); |
| |
| this.project = project; |
| this.containers = containers; |
| for (Object object : resources) |
| { |
| if (object instanceof IFile) |
| { |
| IFile file = (IFile)object; |
| for (IContainer container = file.getParent(); container != null; container = container.getParent()) |
| { |
| if (containers.contains(container)) |
| { |
| consider(file); |
| break; |
| } |
| } |
| } |
| else if (object instanceof IContainer) |
| { |
| for (IContainer container = (IContainer)object; container != null; container = container.getParent()) |
| { |
| if (containers.contains(container)) |
| { |
| consider(container); |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Returns true if there are files to compile. |
| */ |
| public boolean shouldCompile() |
| { |
| return !files.isEmpty(); |
| } |
| |
| /** |
| * Adds the URI. |
| */ |
| protected void consider(String uri) |
| { |
| URI baseURI = URI.createURI(uri); |
| URI localURI = CommonPlugin.asLocalURI(baseURI); |
| if (localURI.isFile() && !localURI.isRelative()) |
| { |
| File file = new File(localURI.toFileString()); |
| if (file.isDirectory() && !uri.endsWith("/")) |
| { |
| baseURI = URI.createURI(uri + "/"); |
| } |
| consider(baseURI, localURI, new File(localURI.toFileString())); |
| } |
| } |
| |
| protected void consider(URI baseURI, URI localURI, File file) |
| { |
| if (file.isDirectory()) |
| { |
| File [] files = file.listFiles(); |
| for (int i = 0; i < files.length; ++i) |
| { |
| consider(baseURI, localURI, files[i]); |
| } |
| } |
| else if (file.isFile() && file.getName().endsWith(JET_EXTENSION) && file.getName().indexOf('.') != -1) |
| { |
| files.add(URI.createFileURI(file.getAbsolutePath()).deresolve(localURI).resolve(baseURI)); |
| } |
| } |
| |
| /** |
| * Adds the file to {@link #files} the file ends with the {@link #JET_EXTENSION} extension. |
| */ |
| protected void consider(IFile file) |
| { |
| if (file.getFileExtension() != null && file.getFileExtension().endsWith(JET_EXTENSION)) |
| { |
| files.add(file); |
| } |
| } |
| |
| /** |
| * Considers all the files of a container and all its subcontainer. |
| */ |
| protected void consider(IContainer container) throws CoreException |
| { |
| IResource[] children = container.members(); |
| if (children != null) |
| { |
| for (int i = 0; i < children.length; ++i) |
| { |
| IResource resource = children[i]; |
| if (resource instanceof IFile) |
| { |
| consider((IFile)resource); |
| } |
| else if (resource instanceof IContainer) |
| { |
| consider((IContainer)resource); |
| } |
| } |
| } |
| } |
| |
| /** |
| */ |
| public void run(IProgressMonitor progressMonitor) throws CoreException |
| { |
| try |
| { |
| progressMonitor.beginTask("", 3 * files.size()); |
| progressMonitor.subTask(CodeGenPlugin.getPlugin().getString("_UI_JETCompilingTemplates_message")); |
| |
| IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); |
| Collection<IProject> jetProjects = new HashSet<IProject>(); |
| |
| HashSet<String> visitedRelativePaths = new HashSet<String>(); |
| for (Object file : files) |
| { |
| String fileName = file instanceof IFile ? ((IFile)file).getName() : file.toString(); |
| |
| progressMonitor.subTask(CodeGenPlugin.getPlugin().getString("_UI_JETCompile_message", new Object [] { fileName })); |
| |
| JETNature nature = JETNature.getRuntime(project); |
| IContainer directory = nature.getJavaSourceContainer(); |
| |
| if(!directory.exists()) |
| { |
| project.getFolder(directory.getProjectRelativePath()).create(true, true, BasicMonitor.subProgress(progressMonitor, 1)); |
| } |
| |
| IPath filePath = file instanceof IFile ? ((IFile)file).getFullPath() : new Path(file.toString()); |
| List<Object> templateContainers = nature.getTemplateContainers(); |
| List<Object> templateSourceContainers = nature.getTemplateSourceContainers(); |
| |
| String [] containerLocations = new String [templateContainers.size()]; |
| for (ListIterator<Object> j = templateContainers.listIterator(); j.hasNext(); ) |
| { |
| Object container = j.next(); |
| if (container instanceof IContainer) |
| { |
| containerLocations[j.previousIndex()] = URI.createPlatformResourceURI(((IContainer)container).getFullPath().toString(), true).toString(); |
| } |
| else |
| { |
| containerLocations[j.previousIndex()] = container.toString(); |
| } |
| } |
| |
| for (Object container : templateSourceContainers) |
| { |
| IPath containerPath = container instanceof IContainer ? ((IContainer)container).getFullPath() : new Path(container.toString()); |
| if (containerPath.isPrefixOf(filePath)) |
| { |
| String relativePath = filePath.removeFirstSegments(containerPath.segmentCount()).setDevice(null).toString(); |
| if (visitedRelativePaths.add(relativePath)) |
| { |
| JETCompiler compiler = new JETCompiler(containerLocations, relativePath); |
| compiler.parse(); |
| |
| StringWriter stringWriter = new StringWriter(); |
| compiler.generate(stringWriter); |
| |
| JETSkeleton skeleton = compiler.getSkeleton(); |
| if (skeleton.getClassName().equals("")) |
| { |
| skeleton.setClassName(fileName.substring(0, fileName.indexOf('.'))); |
| } |
| if (skeleton.getPackageName() != null) |
| { |
| directory = getPackageContainer(directory, skeleton.getPackageName(), BasicMonitor.subProgress(progressMonitor, 1)); |
| } |
| else |
| { |
| progressMonitor.worked(1); |
| } |
| |
| IFile outputFile = |
| workspaceRoot.getFile(directory.getFullPath().append(skeleton.getClassName() + ".java")); |
| |
| progressMonitor.subTask(CodeGenPlugin.getPlugin().getString("_UI_JETUpdate_message", new Object [] { fileName })); |
| |
| String encoding = outputFile.getCharset(); |
| String result = stringWriter.getBuffer().toString(); |
| byte [] bytes; |
| try |
| { |
| bytes = encoding == null ? result.getBytes() : result.getBytes(encoding); |
| } |
| catch (UnsupportedEncodingException exception) |
| { |
| bytes = result.getBytes(); |
| } |
| |
| if (!outputFile.exists()) |
| { |
| outputFile.create(new ByteArrayInputStream(bytes), true, progressMonitor); |
| } |
| else |
| { |
| boolean changed = true; |
| try |
| { |
| InputStream inputStream = outputFile.getContents(); |
| byte [] oldBytes = new byte[inputStream.available()]; |
| inputStream.read(oldBytes); |
| inputStream.close(); |
| changed = !Arrays.equals(oldBytes, bytes); |
| } |
| catch (IOException exception) |
| { |
| // Ignore |
| } |
| |
| if (changed) |
| { |
| if (outputFile.isReadOnly()) |
| { |
| // This call should get the files checked out from version control if the project is a 'team' project. |
| // |
| IStatus status = ResourcesPlugin.getWorkspace().validateEdit(new IFile [] { outputFile }, null); |
| if (!status.isOK()) |
| { |
| throw new CoreException(status); |
| } |
| } |
| outputFile.setContents(new ByteArrayInputStream(bytes), true, true, progressMonitor); |
| } |
| } |
| |
| jetProjects.add(outputFile.getProject()); |
| |
| progressMonitor.worked(1); |
| |
| break; |
| } |
| } |
| } |
| } |
| |
| // Kick of a Java build if not already in a build. |
| // |
| if (!isInBuild()) |
| { |
| for (IProject project : jetProjects) |
| { |
| progressMonitor.subTask |
| (CodeGenPlugin.getPlugin().getString("_UI_JETJavaCompileProject_message", new Object [] { project.getFullPath() })); |
| project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, BasicMonitor.subProgress(progressMonitor, 1)); |
| } |
| } |
| } |
| catch (JETException exception) |
| { |
| throw DiagnosticException.toCoreException(exception); |
| } |
| finally |
| { |
| progressMonitor.done(); |
| } |
| } |
| |
| protected IContainer getPackageContainer(IContainer root, String packagename, IProgressMonitor monitor) throws CoreException |
| { |
| for (StringTokenizer stringTokenizer = new StringTokenizer(packagename, "."); stringTokenizer.hasMoreTokens(); ) |
| { |
| IFolder newContainer = root.getFolder(new Path(stringTokenizer.nextToken())); |
| if (!newContainer.exists()) |
| { |
| newContainer.create(true, true, monitor); |
| } |
| root = newContainer; |
| } |
| |
| return root; |
| } |
| |
| public boolean isInBuild() |
| { |
| return inBuild; |
| } |
| |
| public void setInBuild(boolean build) |
| { |
| inBuild = build; |
| } |
| } |