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); } }