blob: 79db765c310ceb010e817b18a40de327e436dbf0 [file] [log] [blame]
/*******************************************************************************
* 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
}
}
}
}
}