package jetbrains.mps.build.ant;
/*Generated by MPS */
import java.util.Collection;
import java.io.File;
import org.apache.tools.ant.Project;
import java.util.List;
import java.util.ArrayList;
import org.apache.tools.ant.BuildException;
import org.jetbrains.annotations.NotNull;
import java.net.URL;
import java.net.URLDecoder;
import java.net.MalformedURLException;
import java.io.UnsupportedEncodingException;
import java.util.Set;
public class MPSClasspathUtil {
private static final String FILE = "file";
private static final String JAR = "jar";
private static final String JAR_DELIMITER = "!";
private static final String PROTOCOL_DELIMITER = ":";
private static final String[] CLASSPATH = new String[]{"trove4j.jar", "mps-collections.jar", "mps-closures.jar", "mps-tuples.jar", "mps-openapi.jar", "mps-core.jar", "mps-tool.jar", "mps-behavior-api.jar", "mps-behavior-runtime.jar", "mps-logging.jar", "mps-annotations.jar", "mps-boot-util.jar"};
private static final String[] FORK_CLASSPATH = new String[]{"jdom.jar", "log4j.jar", "ecj-4.6.2.jar", "xstream-1.4.8.jar", "asm4-all.jar", "asm-all.jar", "diffutils-1.2.1.jar", "junit-4.12.jar", "javac2.jar"};
public static Collection<File> buildClasspath(Project antProject, File mpsHomeArg, boolean fork) {
List<File> homeFolders = new ArrayList<File>();
boolean foundMpsHome = false;
// if there is mps_home either in property or passed to the task as attribute
if (mpsHomeArg == null || !(mpsHomeArg.isDirectory())) {
homeFolders.add(getAntJARRelativeHome());
mpsHomeArg = resolveMPSHome(antProject, false);
}
if (mpsHomeArg != null) {
File lib = new File(mpsHomeArg, "lib");
if (lib.isDirectory()) {
foundMpsHome = true;
homeFolders.add(lib);
}
}
// if there is no mps_home
if (!(foundMpsHome)) {
homeFolders.add(getAntJARRelativeHome());
homeFolders.addAll(getClassPathRootsFromDependencies(antProject));
}
List<File> result = new ArrayList<File>();
if (fork) {
MPSClasspathUtil.collectClasspath(FORK_CLASSPATH, homeFolders, result);
}
MPSClasspathUtil.collectClasspath(CLASSPATH, homeFolders, result);
return result;
}
public static List<File> getHomeFolders(Project antProject, File mpsHomeArg) {
List<File> homeFolders = new ArrayList<File>();
if (mpsHomeArg == null || !(mpsHomeArg.isDirectory())) {
homeFolders.add(getAntJARRelativeHome());
mpsHomeArg = resolveMPSHome(antProject, false);
}
if (mpsHomeArg != null) {
File lib = new File(mpsHomeArg, "lib");
if (lib.isDirectory()) {
homeFolders.add(lib);
}
}
if (homeFolders.isEmpty()) {
homeFolders.add(getAntJARRelativeHome());
}
return homeFolders;
}
private static void collectClasspath(String[] fileNames, List<File> homeFolders, List<File> result) {
for (String name : fileNames) {
File file = null;
for (File home : homeFolders) {
File f = new File(home, name);
if (f.isFile()) {
file = f;
break;
}
}
if (file == null) {
throw new BuildException("cannot find `" + name + "' in " + homeFolders.toString());
} else {
result.add(file);
}
}
}
public static File resolveMPSHome(Project antProject, boolean failOtherwise) {
String mpsHomePath = antProject.getProperty("mps.home");
if ((mpsHomePath == null || mpsHomePath.length() == 0)) {
mpsHomePath = antProject.getProperty("mps_home");
}
if (mpsHomePath == null || !(antProject.resolveFile(mpsHomePath).exists())) {
if (failOtherwise) {
throw new BuildException("Path to mps home expected. Specify mps.home property or mpsHome attribute.");
} else {
return null;
}
}
return antProject.resolveFile(mpsHomePath);
}
private static File getAntJARRelativeHome() {
String containingJar = getAntMPSJar();
if (!(containingJar.toLowerCase().endsWith(".jar"))) {
throw new BuildException("cannot detect jar location: got `" + containingJar + "'");
}
File current = new File(containingJar);
for (int i = 0; i < 3; i++) {
current = current.getParentFile();
if (current == null) {
throw new BuildException("cannot detect jar location, no parent: got `" + containingJar + "'");
}
if (new File(current, "mps-core.jar").isFile()) {
return current;
}
}
throw new BuildException("cannot detect jar location, no mps-core.jar `" + containingJar + "'");
}
@NotNull
private static String getAntMPSJar() {
Class aClass = MPSClasspathUtil.class;
return getResourceRoot(aClass, "/" + aClass.getName().replace('.', '/') + ".class");
}
/**
* Attempts to detect classpath entry which contains given resource
*/
@NotNull
private static String getResourceRoot(Class context, String path) {
URL url = context.getResource(path);
if (url == null) {
url = ClassLoader.getSystemResource(path.substring(1));
}
if (url == null) {
throw new BuildException("cannot detect jar location; no resource `" + path + "'");
}
// try to decode non-latin characters in url (MPS-20091)
try {
url = new URL(url.getProtocol(), url.getHost(), url.getPort(), URLDecoder.decode(url.getFile(), "UTF-8"));
} catch (MalformedURLException e) {
} catch (UnsupportedEncodingException e) {
}
return extractRoot(url, path);
}
/**
* Attempts to extract classpath entry part from passed URL.
*/
@NotNull
private static String extractRoot(@NotNull URL resourceURL, String resourcePath) {
if (!((resourcePath.startsWith("/") || resourcePath.startsWith("\\")))) {
throw new BuildException("cannot detect jar location: precondition failed for" + resourcePath);
}
String protocol = resourceURL.getProtocol();
String resultPath = null;
if (MPSClasspathUtil.FILE.equals(protocol)) {
String path = resourceURL.getFile();
String testPath = path.replace('\\', '/').toLowerCase();
String testResourcePath = resourcePath.replace('\\', '/').toLowerCase();
if (testPath.endsWith(testResourcePath)) {
resultPath = path.substring(0, path.length() - resourcePath.length());
}
} else
if (MPSClasspathUtil.JAR.equals(protocol)) {
String fullPath = resourceURL.getFile();
int delimiter = fullPath.indexOf(MPSClasspathUtil.JAR_DELIMITER);
if (delimiter >= 0) {
String archivePath = fullPath.substring(0, delimiter);
if (archivePath.startsWith(MPSClasspathUtil.FILE + MPSClasspathUtil.PROTOCOL_DELIMITER)) {
resultPath = archivePath.substring(MPSClasspathUtil.FILE.length() + MPSClasspathUtil.PROTOCOL_DELIMITER.length());
}
}
}
if (resultPath == null) {
throw new BuildException("cannot detect jar location: url=`" + resourceURL.toString() + "'");
}
if (resultPath.endsWith(File.separator)) {
resultPath = resultPath.substring(0, resultPath.length() - 1);
}
return replace(resultPath, "%20", " ");
}
@NotNull
private static String replace(@NotNull String text, @NotNull String from, @NotNull String to) {
final StringBuilder result = new StringBuilder(text.length());
final int len = from.length();
for (int i = 0; i < text.length(); i++) {
if (text.regionMatches(i, from, 0, len)) {
result.append(to);
i += len - 1;
continue;
}
result.append(text.charAt(i));
}
return result.toString();
}
public static List<File> getClassPathRootsFromDependencies(Project project) {
List<File> roots = new ArrayList<File>();
String mpsHome = project.getProperty("artifacts.mps");
String pluginHome = project.getProperty("artifacts.mpsPlugin");
String ideaHome = project.getProperty("artifacts.IDEA");
String mpsCoreHome = project.getProperty("artifacts.mpsBootstrapCore");
String mpsWorkbenchHome = project.getProperty("artifacts.mpsWorkbench");
if ((mpsHome != null && mpsHome.length() > 0)) {
// buildMPS
roots.add(new File(project.resolveFile(mpsHome).getPath(), "lib"));
} else if ((pluginHome != null && pluginHome.length() > 0) && (ideaHome != null && ideaHome.length() > 0)) {
// buildPlugin + IDEA
roots.add(new File(project.resolveFile(ideaHome).getPath(), "lib"));
roots.add(new File(project.resolveFile(pluginHome).getPath(), "mps-core/lib"));
} else if ((mpsCoreHome != null && mpsCoreHome.length() > 0) && (ideaHome != null && ideaHome.length() > 0)) {
// buildCore + IDEA
roots.add(new File(project.resolveFile(mpsCoreHome).getPath(), "lib"));
roots.add(new File(project.resolveFile(ideaHome).getPath(), "lib"));
if ((mpsWorkbenchHome != null && mpsWorkbenchHome.length() > 0)) {
roots.add(new File(project.resolveFile(mpsWorkbenchHome).getPath(), "lib"));
}
}
return roots;
}
public static void gatherAllClassesAndJarsUnder(File dir, Set<File> result) {
if (dir.getName().equals("classes") || dir.getName().equals("classes_gen") || dir.getName().equals("apiclasses")) {
result.add(dir);
return;
}
File[] children = dir.listFiles();
// we do not want trove different from ours in $mps.home$/lib
String troveJar = "trove" + File.separator + "lib" + File.separator + "trove";
// to provide right order of class loading,
// files go first
for (File f : children) {
if (!(f.isDirectory())) {
if (f.getName().endsWith(".jar") && !(f.getName().contains("ant.jar")) && !(f.getPath().contains(troveJar))) {
result.add(f);
}
}
}
for (File f : children) {
if (f.isDirectory()) {
if (f.getName().equals("classes") || f.getName().equals("classes_gen")) {
result.add(f);
} else {
gatherAllClassesAndJarsUnder(f, result);
}
}
}
}
}