| /******************************************************************************* |
| * Copyright (c) 2007 Cisco Systems, Inc. |
| * 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: |
| * E. Dillon (Cisco Systems, Inc.) - reformat for Code Open-Sourcing |
| *******************************************************************************/ |
| package org.eclipse.tigerstripe.workbench.internal.api.impl; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.PrintWriter; |
| import java.lang.reflect.Constructor; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.net.URI; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.List; |
| import java.util.zip.ZipException; |
| |
| import javax.tools.JavaCompiler; |
| import javax.tools.JavaFileObject; |
| import javax.tools.StandardJavaFileManager; |
| import javax.tools.ToolProvider; |
| |
| import org.apache.commons.lang.StringUtils; |
| import org.apache.tools.ant.DirectoryScanner; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.tigerstripe.workbench.TigerstripeException; |
| import org.eclipse.tigerstripe.workbench.internal.core.NewTigerstripeRuntime; |
| import org.eclipse.tigerstripe.workbench.internal.core.model.PrimitiveTypeArtifact; |
| import org.eclipse.tigerstripe.workbench.internal.core.profile.PhantomTigerstripeProject; |
| import org.eclipse.tigerstripe.workbench.internal.core.project.ModelReference; |
| import org.eclipse.tigerstripe.workbench.internal.core.util.ZipFilePackager; |
| import org.eclipse.tigerstripe.workbench.model.deprecated_.IArtifactManagerSession; |
| import org.eclipse.tigerstripe.workbench.model.deprecated_.IPrimitiveTypeArtifact; |
| import org.eclipse.tigerstripe.workbench.profile.IWorkbenchProfile; |
| import org.eclipse.tigerstripe.workbench.profile.primitiveType.IPrimitiveTypeDef; |
| import org.eclipse.tigerstripe.workbench.project.IPhantomTigerstripeProject; |
| import org.eclipse.tigerstripe.workbench.project.IProjectDescriptor; |
| |
| public class TigerstripePhantomProjectHandle extends BaseTigerstripeModelProject |
| implements IPhantomTigerstripeProject { |
| |
| private final static String classes = "classes"; |
| private final static String CouldntCompilePhantomProjectContent = "Couldn't compile Phantom Project Content "; |
| |
| /** |
| * |
| * @param projectURI - |
| * URI of the project directory |
| */ |
| public TigerstripePhantomProjectHandle(NewTigerstripeRuntime runtime) throws TigerstripeException { |
| super(runtime, runtime.getPhantomTigerstripeProjectMgr().getPhantomURI()); |
| } |
| |
| public Collection<IPrimitiveTypeArtifact> getReservedPrimitiveTypes() |
| throws TigerstripeException { |
| return getArtifactManagerSession().getReservedPrimitiveTypes(); |
| } |
| |
| @Override |
| public IProjectDescriptor getTSProject() throws TigerstripeException { |
| if (tsProject == null) { |
| // try and create a project for the URI |
| File baseDir = new File(this.getProjectContainerURI()); |
| baseDir.mkdirs(); |
| if (baseDir.isDirectory()) { |
| tsProject = new PhantomTigerstripeProject(runtime, baseDir); |
| } else |
| throw new TigerstripeException("Invalid project " |
| + baseDir.toString()); |
| } |
| |
| tsProject.reload(false); |
| return this.tsProject; |
| |
| } |
| |
| public PhantomTigerstripeProject getPhantomProject() |
| throws TigerstripeException { |
| // there's only one phantom project it's maintained exclusively by |
| // the PhantomTigerstripeProjectMgr |
| return (PhantomTigerstripeProject) runtime.getPhantomTigerstripeProjectMgr().getPhantomProject(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @seeorg.eclipse.tigerstripe.workbench.project.ITigerstripeModelProject# |
| * getReferencingModels() |
| */ |
| public ModelReference[] getReferencingModels(int level) throws TigerstripeException { |
| return new ModelReference[0]; |
| } |
| |
| |
| |
| |
| |
| public URI getPhantomURI() { |
| return runtime.getPhantomTigerstripeProjectMgr() |
| .getPhantomURI(); |
| } |
| |
| public void init() throws TigerstripeException { |
| boolean needACompile = populatePrimitiveTypes(new NullProgressMonitor()) != 0; |
| createJarForEclipsePath(needACompile); |
| } |
| |
| /** |
| * Because each Tigerstripe project is a Java Project, we need to make sure |
| * all the artifact from the Phantom project are actually in the classpath |
| * of the Tigerstripe projects. |
| * |
| * This is done by compiling all the artifacts in the Phantom project and |
| * putting them in a .zip file that's going to be added as a library to eacy |
| * project. |
| * |
| * This method creates this jar file (it is added into the classpath by the |
| * org.eclipse.tigerstripe.ui.eclipse.builder.ClasspathUpdater |
| * |
| */ |
| private void createJarForEclipsePath(boolean needACompile) throws TigerstripeException { |
| if (needACompile) // only trigger a compile if there's something to compile |
| compileArtifacts(); |
| zipUpCompiledArtifacts(); |
| } |
| |
| /** |
| * Creates PrimitiveType artifacts in the phantom project corresponding to |
| * all definitions in the profile. |
| * |
| * @return returns the number of PrimitiveType artifacts created |
| * @throws TigerstripeException |
| */ |
| private int populatePrimitiveTypes(IProgressMonitor monitor) { |
| |
| int numberCreated = 0; |
| IArtifactManagerSession artifactMgrSession = null; |
| try { |
| artifactMgrSession = getArtifactManagerSession(); |
| |
| // Bug 536 |
| artifactMgrSession.getArtifactManager().reset(monitor); |
| artifactMgrSession.getArtifactManager().lock(true); |
| |
| |
| IWorkbenchProfile profile = artifactMgrSession.getArtifactManager().getRuntime() |
| .getWorkbenchProfileSession().getActiveProfile(); |
| Collection<IPrimitiveTypeDef> defs = profile |
| .getPrimitiveTypeDefs(false); |
| for (IPrimitiveTypeDef def : defs) { |
| IPrimitiveTypeArtifact artifact = (IPrimitiveTypeArtifact) artifactMgrSession |
| .makeArtifact(IPrimitiveTypeArtifact.class.getName()); |
| artifact.setName(def.getName()); |
| artifact.setComment(def.getDescription()); |
| artifact.setFullyQualifiedName(def.getPackageName() + "." |
| + def.getName()); |
| |
| try { |
| artifactMgrSession.addArtifact(artifact); |
| if (artifact instanceof PrimitiveTypeArtifact) { |
| ((PrimitiveTypeArtifact) artifact).doSilentSave(); |
| } |
| runtime.logInfoMessage("Added " + def.getName()); |
| numberCreated++; |
| } catch (TigerstripeException e) { |
| // this was an invalid artifact, ignore here. |
| } |
| } |
| } catch (TigerstripeException e) { |
| runtime.logErrorMessage("Exception populating primitive types ", e); |
| } finally { |
| if (artifactMgrSession != null) { |
| artifactMgrSession.getArtifactManager().lock(false); |
| try { |
| artifactMgrSession.refresh(true, monitor); |
| } catch (TigerstripeException e) { |
| runtime.logErrorMessage( |
| "TigerstripeException detected", e); |
| } |
| } |
| } |
| return numberCreated; |
| } |
| |
| private void compileArtifacts() throws TigerstripeException { |
| |
| String projectDir = getPhantomURI().getPath(); |
| |
| // First clean up |
| File classesDir = new File(projectDir, classes); |
| if (classesDir.exists()) { |
| classesDir.delete(); |
| } |
| |
| classesDir.mkdirs(); |
| |
| String outputDir = classesDir.getAbsolutePath(); |
| |
| // Add all artifacts from the src dir |
| DirectoryScanner scanner = new DirectoryScanner(); |
| scanner.setBasedir(projectDir); |
| |
| String[] includes = { "src/**/*.java" }; |
| String[] excludes = {}; |
| scanner.setIncludes(includes); |
| scanner.setExcludes(excludes); |
| scanner.scan(); |
| String[] files = scanner.getIncludedFiles(); |
| |
| // Try and compile |
| if (runtime.getRuntype() == NewTigerstripeRuntime.CLI_RUN |
| || runtime.getRuntype() == NewTigerstripeRuntime.ANT_RUN |
| || runtime.getRuntype() == NewTigerstripeRuntime.STANDALONE_RUN ) { |
| |
| List<File> filesToCompile = new ArrayList<>(); |
| for (String filePath : files) { |
| if (StringUtils.isNotEmpty(filePath)) { |
| filesToCompile.add(new File (projectDir, filePath)); |
| } |
| } |
| |
| // We are not inside eclipse, so use the system compiler |
| try { |
| |
| JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); |
| StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); |
| |
| Iterable<? extends JavaFileObject> compilationUnits = |
| fileManager.getJavaFileObjectsFromFiles(filesToCompile); |
| |
| final Iterable<String> options = Arrays.asList("-d", outputDir); |
| Boolean compileResult = compiler.getTask(null, null, null, options, null, compilationUnits).call(); |
| |
| fileManager.close(); |
| |
| if (!compileResult.booleanValue()) { |
| throw new TigerstripeException( |
| CouldntCompilePhantomProjectContent); |
| } |
| |
| } catch (Exception e) { |
| runtime |
| .logErrorMessage( |
| CouldntCompilePhantomProjectContent+" : " |
| + e.getMessage() |
| + "\nAre you a JDK or JRE. JDK is required when running headless", |
| e); |
| throw new TigerstripeException( |
| CouldntCompilePhantomProjectContent+" : " |
| + e.getMessage() |
| + "\nAre you a JDK or JRE. JDK is required when running headless", |
| e); |
| } |
| } else { |
| |
| try { |
| |
| // Assemble proper command line for compile |
| |
| List<String> compilerArgs = new ArrayList<>(); |
| for (String filePath : files) { |
| if (StringUtils.isNotEmpty(filePath)) { |
| compilerArgs.add(new File (projectDir, filePath).getAbsolutePath()); |
| } |
| } |
| compilerArgs.add("-d"); |
| compilerArgs.add(outputDir); |
| |
| Class<?> mainClass = Class |
| .forName("org.eclipse.jdt.internal.compiler.batch.Main"); |
| Constructor<?> mainClassConstructor = mainClass |
| .getConstructor(new Class[] { PrintWriter.class, |
| PrintWriter.class, boolean.class }); |
| PrintWriter out = new PrintWriter(System.out); |
| PrintWriter err = new PrintWriter(System.err); |
| Object compiler = mainClassConstructor |
| .newInstance(new Object[] { out, err, false }); |
| |
| Method compileMethod = mainClass.getMethod("compile", |
| new Class[] { String[].class }); |
| |
| |
| compileMethod.invoke(compiler, |
| new Object[] { compilerArgs |
| .toArray(new String[compilerArgs.size()]) }); |
| |
| } catch (InstantiationException | |
| InvocationTargetException | |
| IllegalAccessException | |
| NoSuchMethodException | |
| ClassNotFoundException e) { |
| runtime.logErrorMessage( |
| CouldntCompilePhantomProjectContent+" : " |
| + e.getMessage() |
| + "\nProblem built-in Java Compiler", e); |
| throw new TigerstripeException( |
| CouldntCompilePhantomProjectContent+" : " |
| + e.getMessage() |
| + "\nProblem built-in Java Compiler", e); |
| } |
| } |
| } |
| |
| private void zipUpCompiledArtifacts() throws TigerstripeException { |
| ZipFilePackager zipper = null; |
| File[] binFiles = null; |
| try { |
| File libDir = new File(getPhantomURI().getPath() + "/lib/"); |
| if (!libDir.exists()) { |
| libDir.mkdirs(); |
| } |
| |
| zipper = new ZipFilePackager(getPhantomURI().getPath() |
| + "/lib/phantom.zip", true); |
| |
| // the dir with all compiled artifact |
| String binDir = getPhantomURI().getPath() + File.separator |
| + classes; |
| File binDirFile = new File(binDir); |
| binFiles = binDirFile.listFiles(); |
| |
| if (binFiles != null && binFiles.length != 0) |
| zipper.write(binFiles, ""); |
| |
| // make sure there's at least one file in the zip or else it's not valid |
| File empty = new File(getPhantomURI().getPath() + "/empty.txt"); |
| empty.createNewFile(); |
| zipper.write(empty, "empty.txt"); |
| |
| zipper.finished(); |
| |
| } catch (IOException e) { |
| if (e instanceof ZipException |
| && (binFiles == null || binFiles.length == 0)) { |
| // Ignore, Zip complains when creating a zip file with zero |
| // entry |
| } else |
| throw new TigerstripeException( |
| "Error while packaging up Phantom Project:" |
| + e.getMessage(), e); |
| } finally { |
| if (zipper != null) { |
| try { |
| zipper.finished(); |
| } catch (IOException e) { |
| // just ignore it |
| } |
| } |
| } |
| |
| } |
| } |