package jetbrains.mps.build.ant;
/*Generated by MPS */
import org.apache.tools.ant.Task;
import java.io.File;
import jetbrains.mps.tool.common.Script;
import java.util.List;
import java.util.ArrayList;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import java.util.Set;
import java.util.Hashtable;
import org.apache.tools.ant.util.JavaEnvUtils;
import java.util.HashSet;
import java.io.IOException;
import org.apache.tools.ant.taskdefs.Execute;
import java.net.URL;
import java.net.MalformedURLException;
import java.net.URLClassLoader;
import org.apache.tools.ant.ProjectComponent;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.io.FileInputStream;
import java.util.LinkedHashSet;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.log4j.Level;
import java.util.Scanner;
public abstract class MpsLoadTask extends Task {
public static final String CONFIGURATION_NAME = "configuration.name";
public static final String BUILD_NUMBER = "build.number";
private File myMpsHome;
protected final Script myWhatToDo = new Script();
private boolean myUsePropertiesAsMacro = false;
private boolean myFork = true;
private final List<String> myJvmArgs = new ArrayList<String>();
public MpsLoadTask() {
}
public void setMpsHome(File mpsHome) {
myMpsHome = mpsHome;
}
public File getMpsHome() {
return myMpsHome;
}
public void setFailOnError(boolean failOnError) {
myWhatToDo.updateFailOnError(failOnError);
}
public void setLogLevel(MpsLoadTask.LogLevelAttribute logLevel) {
myWhatToDo.updateLogLevel(logLevel.getLevel());
}
public void setFork(boolean fork) {
myFork = fork;
}
public void addConfiguredExclude(ExcludeNested excludeInner) {
for (File file : excludeInner.getExcludedFromDiffFiles()) {
myWhatToDo.excludeFileFromDiff(file);
}
}
public void addConfiguredMacro(Macro macro) {
myWhatToDo.addMacro(macro.getName(), macro.getPath().getAbsolutePath());
}
public boolean getUsePropertiesAsMacro() {
return myUsePropertiesAsMacro;
}
public void setUsePropertiesAsMacro(boolean usePropertiesAsMacro) {
myUsePropertiesAsMacro = usePropertiesAsMacro;
}
public void addConfiguredJvmArg(Arg jvmArg) {
if (!(myFork)) {
throw new BuildException("Nested jvmarg is only allowed in fork mode.");
}
log("Nested jvmarg is deprecated. Use jvmargs instead.", Project.MSG_WARN);
myJvmArgs.add(jvmArg.getValue());
}
public void addConfiguredJvmArgs(JvmArgs jvmArg) {
if (!(myFork)) {
throw new BuildException("Nested jvmargs is only allowed in fork mode.");
}
myJvmArgs.addAll(jvmArg.getArgs());
}
@Override
public void execute() throws BuildException {
Set<File> classPaths = calculateClassPath(myFork);
if (myUsePropertiesAsMacro) {
Hashtable properties = getProject().getProperties();
for (Object name : properties.keySet()) {
Object value = properties.get(name);
myWhatToDo.addMacro((String) name, (String) value);
}
}
if (myFork) {
String currentClassPathString = System.getProperty("java.class.path");
List<String> commandLine = new ArrayList<String>();
commandLine.add(JavaEnvUtils.getJreExecutable("java"));
if (myJvmArgs.isEmpty()) {
commandLine.addAll(new JvmArgs().getArgs());
} else {
commandLine.addAll(myJvmArgs);
}
String javaHome = JavaEnvUtils.getJavaHome();
StringBuilder sb = new StringBuilder();
Set<String> entries = new HashSet<String>();
String pathSeparator = "";
for (String entry : currentClassPathString.split(File.pathSeparator)) {
if (!(entries.contains(entry)) && !(startsWith(entry, javaHome))) {
entries.add(entry);
sb.append(pathSeparator);
sb.append(entry);
pathSeparator = File.pathSeparator;
}
}
for (File cp : classPaths) {
String entry = cp.getAbsolutePath();
if (!(entries.contains(entry))) {
entries.add(entry);
sb.append(pathSeparator);
sb.append(entry);
pathSeparator = File.pathSeparator;
}
}
commandLine.add("-classpath");
commandLine.add(sb.toString());
commandLine.add("jetbrains.mps.tool.builder.AntBootstrap");
commandLine.add(getWorkerClass());
dumpPropertiesToWhatToDo();
try {
commandLine.add(myWhatToDo.dumpToTmpFile().getAbsolutePath());
} catch (IOException e) {
throw new BuildException(e);
}
Execute exe = new Execute(new MyExecuteStreamHandler(this));
exe.setAntRun(this.getProject());
exe.setWorkingDirectory(this.getProject().getBaseDir());
exe.setCommandline(commandLine.toArray(new String[commandLine.size()]));
try {
int i = exe.execute();
if (i != 0) {
processNonZeroExitCode(i);
}
} catch (IOException e) {
throw new BuildException(e);
}
} else {
List<URL> classPathUrls = new ArrayList<URL>();
for (File path : classPaths) {
try {
classPathUrls.add(new URL("file:///" + path + ((path.isDirectory() ? "/" : ""))));
} catch (MalformedURLException e) {
throw new BuildException(e);
}
}
URLClassLoader classLoader = new URLClassLoader(classPathUrls.toArray(new URL[classPathUrls.size()]), ProjectComponent.class.getClassLoader());
Thread.currentThread().setContextClassLoader(classLoader);
try {
Class<?> whatToGenerateClass = classLoader.loadClass(Script.class.getCanonicalName());
Object whatToGenerate = whatToGenerateClass.newInstance();
myWhatToDo.cloneTo(whatToGenerate);
Class<?> generatorClass = classLoader.loadClass(getWorkerClass());
Constructor<?> constructor = generatorClass.getConstructor(whatToGenerateClass, ProjectComponent.class);
Object generator = constructor.newInstance(whatToGenerate, this);
Method method = generatorClass.getMethod("work");
method.invoke(generator);
} catch (Throwable t) {
throw new BuildException(t.getMessage() + "\n" + "Used class path: " + classPathUrls.toString());
}
}
}
private void outputBuildNumber() {
String antTaskBuildNumber;
URL resource = getClass().getResource("/build.number");
if (resource == null) {
log("Can't determine version of ant task.", Project.MSG_DEBUG);
return;
}
try {
antTaskBuildNumber = MpsLoadTask.readBuildNumber(resource.openStream());
if (antTaskBuildNumber == null || antTaskBuildNumber.isEmpty()) {
log("Can't determine version of ant task.", Project.MSG_DEBUG);
return;
}
} catch (IOException ignore) {
log("Can't determine version of ant task.", Project.MSG_DEBUG);
return;
}
String mpsBuildNumber;
try {
mpsBuildNumber = MpsLoadTask.readBuildNumber(new FileInputStream(new File(myMpsHome.getAbsolutePath() + File.separator + "build.number")));
if (mpsBuildNumber == null || mpsBuildNumber.isEmpty()) {
log("Can't determine version of MPS.", Project.MSG_DEBUG);
return;
}
} catch (IOException ignore) {
log("Can't determine version of MPS.", Project.MSG_DEBUG);
return;
}
if (mpsBuildNumber.equals(antTaskBuildNumber)) {
log("Build number " + mpsBuildNumber, Project.MSG_INFO);
} else {
log("MPS build number is " + mpsBuildNumber + ", while ant task build number is " + antTaskBuildNumber + ".\n" + "This may cause errors.", Project.MSG_WARN);
}
}
private void processNonZeroExitCode(int i) {
throw new BuildException("Process exited with code " + i + ".");
}
private void dumpPropertiesToWhatToDo() {
Hashtable properties = getProject().getProperties();
for (Object key : properties.keySet()) {
myWhatToDo.putProperty((String) key, (String) properties.get(key));
}
}
private void checkMpsHome() {
if (myMpsHome == null) {
myMpsHome = MPSClasspathUtil.resolveMPSHome(getProject(), true);
}
outputBuildNumber();
}
private boolean startsWith(String path, String prefix) {
return path.startsWith(prefix) && (path.length() == prefix.length() || prefix.endsWith(File.separator) || path.charAt(prefix.length()) == File.separatorChar);
}
protected Set<File> calculateClassPath(boolean fork) {
checkMpsHome();
LinkedHashSet<File> result = new LinkedHashSet<File>();
result.addAll(MPSClasspathUtil.buildClasspath(getProject(), myMpsHome, fork));
return result;
}
protected abstract String getWorkerClass();
public static String readBuildNumber(InputStream stream) {
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new InputStreamReader(stream));
String buildNumber = null;
String configurationName = null;
while (true) {
String line = bufferedReader.readLine();
if (line == null) {
break;
}
if (line.startsWith(CONFIGURATION_NAME)) {
String tmp = line.substring(CONFIGURATION_NAME.length());
configurationName = tmp.replaceAll("(\\s*)=(\\s*)(.*)", "$3");
} else
if (line.startsWith(BUILD_NUMBER)) {
String tmp = line.substring(BUILD_NUMBER.length());
buildNumber = tmp.replaceAll("(\\s*)=(\\s*)(.*)", "$3");
}
}
if (buildNumber != null && configurationName != null) {
return configurationName + "." + buildNumber;
}
} catch (IOException ignore) {
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ignore) {
}
}
}
return null;
}
public static class LogLevelAttribute extends EnumeratedAttribute {
public LogLevelAttribute() {
}
@Override
public String[] getValues() {
return new String[]{"error", "warn", "warning", "info", "debug"};
}
public Level getLevel() {
String val = getValue();
if ("warning".equalsIgnoreCase(val)) {
val = "warn";
}
return Level.toLevel(val);
}
}
public static abstract class AbstractOutputReader extends Thread {
private InputStream myInputStream;
public AbstractOutputReader(InputStream inputStream) {
this.myInputStream = inputStream;
}
@Override
public void run() {
Scanner s = new Scanner(this.myInputStream);
try {
while (!((this.isInterrupted())) && s.hasNextLine()) {
this.addMessage(s.nextLine());
}
} catch (Exception e) {
}
}
protected abstract void addMessage(String message);
}
}