/*******************************************************************************
* Copyright (c) 2005, 2012 eBay 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
*
*******************************************************************************/
package org.eclipse.vjet.eclipse.internal.launching;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.filesystem.IFileSystem;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.sourcelookup.containers.ZipEntryStorage;
import org.eclipse.dltk.mod.core.IScriptProject;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.vjet.eclipse.core.ClassPathUtils;
import org.eclipse.vjet.eclipse.core.VjetPlugin;
import org.eclipse.vjet.eclipse.launching.VjetLaunchingPlugin;
import org.eclipse.vjet.vjo.tool.codecompletion.StringUtils;
/**
* Copied from com.ebay.tools.applauncher.launch.LauncherUtil, to fix "arg too
* long" issue
*
*
*
*/
public class LauncherUtil {
public static final String TEMP_VJET_LAUNCH = "c:\\vjetl";
public static final String EXCLAMATION_MARK = "!";
public static final String SCHEME_FILE = "file";
public static final String SCHEME_JAR = "jar";
public static final String SCHEME_ZIP = "zip";
/**
* Return the classpath using /* for java 6.
*
* @param classpath
* @param rootDir
*/
private static void copyClasspathFiles(Set<String> classpath) {
Set<String> libSet = new HashSet<String>(20000);
System.out.println("Classpath:");
try {
File destDir = new File(TEMP_VJET_LAUNCH);
destDir.mkdirs();
for (String path : classpath) {
System.out.println("\t" + path);
File inputFile = new File(path);
if (libSet.contains(inputFile.getName())) {
continue;
}
if (path.endsWith(".jar")) {
LauncherUtil.copyFile(destDir, inputFile);
libSet.add(inputFile.getName());
}
}
} catch (Exception e) {// Catch exception if any
VjetPlugin.error("Failed to copy the jars to destination : "
+ TEMP_VJET_LAUNCH, e, IStatus.ERROR);
}
}
public static String[] getOptimizedClasspath(IJavaProject javaProject) {
try {
Set<String> paths = ClassPathUtils
.getProjectDependencyUrls(javaProject);
boolean isJava6 = isJava6Vm(null);
if (!isJava6) {
copyClasspathFiles(paths);
}
String[] optimizedClasspath = getOptimizedClasspath(paths, isJava6,
TEMP_VJET_LAUNCH);
return optimizedClasspath;
} catch (CoreException e) {
VjetPlugin.error("Failed to get optimized class path ", e,
IStatus.ERROR);
return new String[0];
} catch (MalformedURLException e) {
VjetPlugin.error("Failed to get optimized class path ", e,
IStatus.ERROR);
return new String[0];
}
}
public static Set<String> getRawClasspath(IJavaProject javaProject)
throws JavaModelException {
Map<String, IJavaProject> transitiveClosureProjectList = new LinkedHashMap<String, IJavaProject>();
getTransitiveClosureProjectDependnecyList(javaProject,
transitiveClosureProjectList);
Set<String> jars = new LinkedHashSet<String>();
getProjectDependentJars(jars, javaProject.getRawClasspath());
for (IJavaProject project : transitiveClosureProjectList.values()) {
getProjectDependentJars(jars, project.getRawClasspath());
}
return jars;
}
/**
*
* @param classpath
* the raw class path array
* @param isJava6
* @param rootDir
* @return classPath array based on jre6 version as argument string as
* argName (-cp or -Djava.class.path)
* @throws CoreException
*/
public static String[] getOptimizedClasspath(Set<String> classpath,
boolean isJava6, String rootDir) throws CoreException {
StringBuilder m_vmArg = new StringBuilder(20000);
try {
// Create file
if (isJava6) {
getJava6Classpath(classpath, m_vmArg);
} else {
getJava5Classpath(classpath, rootDir, m_vmArg);
}
} catch (Exception e) {// Catch exception if any
VjetPlugin.error("Failed to get optimized class path", e,
IStatus.ERROR);
}
return m_vmArg.toString().split(";");
}
/**
*
* @param classpath
* the raw class path array
* @param isJava6
* @param rootDir
* @return classPath array based on jre6 version as argument string as
* argName (-cp or -Djava.class.path)
* @throws CoreException
*/
public static String getOptimizedClasspathArg(Set<String> classpath,
boolean isJava6, String rootDir) throws CoreException {
StringBuilder m_vmArg = new StringBuilder(20000);
try {
// Create file
if (isJava6) {
m_vmArg.append("-cp \"");
getJava6Classpath(classpath, m_vmArg);
} else {
m_vmArg.append("-Djava.class.path=\"");
getJava5Classpath(classpath, rootDir, m_vmArg);
}
m_vmArg.append("\"");
} catch (Exception e) {// Catch exception if any
VjetPlugin.error("Failed to get optimized class path", e,
IStatus.ERROR);
}
return m_vmArg.toString();
}
public static void getTransitiveClosureProjectDependnecyList(
IJavaProject javaProject,
Map<String, IJavaProject> transitiveClosureProjectList)
throws JavaModelException {
IClasspathEntry[] classPathEntries = javaProject
.getResolvedClasspath(true);
if (classPathEntries != null) {
for (IClasspathEntry classPathEntry : classPathEntries) {
if (classPathEntry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
IResource classPathProject = ResourcesPlugin.getWorkspace()
.getRoot().findMember(classPathEntry.getPath());
if (classPathProject != null) {
if (!transitiveClosureProjectList
.containsKey(classPathProject.getName())) {
IJavaProject subJavaProject = getJavaProject(classPathProject);
transitiveClosureProjectList.put(classPathProject
.getName(), subJavaProject);
getTransitiveClosureProjectDependnecyList(
subJavaProject,
transitiveClosureProjectList);
}
}
}
}
}
}
public static IJavaProject getJavaProject(IResource resource) {
if (resource instanceof IProject) {
return getJavaProject((IProject) resource);
}
return null;
}
public static IJavaProject getJavaProject(IProject project) {
IJavaProject javaProject = JavaCore.create(project);
return javaProject.exists() ? javaProject : null;
}
private static void getProjectDependentJars(Set<String> jars,
IClasspathEntry[] classPathEntries) {
if (classPathEntries != null) {
for (IClasspathEntry classPathEntry : classPathEntries) {
if (classPathEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY
|| classPathEntry.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
IPath path = JavaCore.getResolvedClasspathEntry(
classPathEntry).getPath();
if (path != null) {
String s = path.toString();
if (!StringUtils.isBlankOrEmpty(s)) {
jars.add(s);
}
}
}
}
}
}
/**
* This method is used to get the class path for java6 based jvms. This
* method will use the existing directories and will take advantage of a
* feature in jvm6 that allows wildcards in the classpath.
*
* @param classpath
* @param m_vmArg
*/
private static void getJava6Classpath(Set<String> classpath,
StringBuilder m_vmArg) {
Set<String> parentFolders = new HashSet<String>(1000);
for (String path : classpath) {
File inputFile = new File(path);
String classPathEntry = "";
if (inputFile.isFile()) {
File parentFolder = inputFile.getParentFile();
if (parentFolders.contains(parentFolder.getAbsolutePath())) {
continue;
}
classPathEntry = parentFolder.getAbsolutePath() + "\\*;";
parentFolders.add(parentFolder.getAbsolutePath());
} else {
classPathEntry = path + ";";
}
m_vmArg.append(classPathEntry);
}
}
private static void getJava5Classpath(Set<String> classpath,
String rootDir, StringBuilder m_vmArg) {
Set<String> libSet = new HashSet<String>(1000);
for (String path : classpath) {
File inputFile = new File(path);
String classPathEntry = "";
if (libSet.contains(inputFile.getName())) {
continue;
}
if (path.contains(".jar")) {
classPathEntry = rootDir + "\\" + inputFile.getName() + ";";
libSet.add(inputFile.getName());
} else {
classPathEntry = path + ";";
}
m_vmArg.append(classPathEntry);
}
}
private static void copyFile(File destDir, File inputFile) throws Exception {
IFileSystem fs = EFS.getLocalFileSystem();
File outputFile = new File(destDir, inputFile.getName());
// If the modified dates are different. Then do the copy.
if (inputFile.lastModified() != outputFile.lastModified()) {
long inputDateTime = inputFile.lastModified();
IFileStore source = fs.getStore(inputFile.toURI());
IFileStore dest = fs.getStore(outputFile.toURI());
source.copy(dest, EFS.OVERWRITE, new NullProgressMonitor());
outputFile.setLastModified(inputDateTime);
}
}
/**
* Tries to determine the version of Java.
*
* Warning: This assumes the version of java eclipse is running is the same
* version that the launcher is going to run.
*
* @param configuration
* @return
* @throws CoreException
*/
public static boolean isJava6Vm(ILaunchConfiguration configuration)
throws CoreException {
boolean isJava6 = false;
String javaVersion = System.getProperty("java.version");
if (javaVersion.contains("1.6")) {
isJava6 = true;
}
return isJava6;
}
public static ZipEntryStorage createZipEntryFile(final URI uri)
throws ZipException, IOException {
URI tempURI = uri;
String schemeSpecificPart = null;
// remove all schemes
do {
schemeSpecificPart = tempURI.getSchemeSpecificPart();
tempURI = URI.create(schemeSpecificPart);
} while (tempURI.getScheme() != null);
// get the jar file name
int pos = schemeSpecificPart.indexOf(EXCLAMATION_MARK);
if (pos == -1) {
return null;
}
String[] paths = schemeSpecificPart.split(EXCLAMATION_MARK);
if (paths.length != 2) {
return null;
}
File jarFile = new File(paths[0]);
ZipEntry zipEntry = new ZipEntry(paths[1].substring(1));
ZipFile zipFile = new ZipFile(jarFile);
return new ZipEntryStorage(zipFile, zipEntry) {
@Override
public IPath getFullPath() {
return new Path(uri.toString());
}
};
}
public static boolean isFileScheme(String scheme) {
return SCHEME_FILE.equals(scheme);
}
public static boolean isZipScheme(String scheme) {
return SCHEME_JAR.equals(scheme) || SCHEME_ZIP.equals(scheme);
}
public static String[] getOptimizedBuildpath(IScriptProject scriptProject) {
try {
Set<String> urlsString = ClassPathUtils
.getProjectDependencyUrls(scriptProject);
boolean isJava6 = isJava6Vm(null);
if (!isJava6) {
copyClasspathFiles(urlsString);
}
return getOptimizedClasspath(urlsString, isJava6, TEMP_VJET_LAUNCH);
} catch (Exception e) {
VjetLaunchingPlugin.error(e.getLocalizedMessage(), e);
}
return new String[0];
}
}