/*******************************************************************************
* Copyright (c) 2007, 2008 Edgar Espina.
* 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.deved.antlride.integration.jdt;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.deved.antlride.core.AntlrCore;
import org.deved.antlride.core.AntlrLanguageTargetName;
import org.deved.antlride.core.build.AntlrBuildUnit;
import org.deved.antlride.core.integration.AntlrLanguageTargetService;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.TextEdit;
public class AntlrJavaTargetService implements AntlrLanguageTargetService {
private static class Version {
private String version;
}
public Map<String, Object> getClasspathInformation(
IProgressMonitor monitor, AntlrBuildUnit unit) throws CoreException {
final IJavaProject javaProject = JavaCore.create(unit.getFile()
.getProject());
if (javaProject == null || !javaProject.exists()) {
return Collections.emptyMap();
}
IRuntimeClasspathEntry[] runtimeClassPath = computeDefaultRuntimeClassPath(javaProject);
Version v = new Version();
runtimeClassPath = mergeClasspath(v, monitor, unit, runtimeClassPath);
String[] classpath = getLocationClassPath(runtimeClassPath);
Map<String, Object> map = new HashMap<String, Object>();
map.put("classpath", classpath);
map.put("description", v.version);
return map;
}
public static String[] getMementoClassPath(IRuntimeClasspathEntry[] entries)
throws CoreException {
String[] classpath = new String[entries.length];
for (int i = 0; i < entries.length; i++) {
classpath[i] = entries[i].getMemento();
System.out.println(classpath[i]);
}
return classpath;
}
public static String[] getLocationClassPath(IRuntimeClasspathEntry[] entries)
throws CoreException {
String[] classpath = new String[entries.length];
for (int i = 0; i < entries.length; i++) {
classpath[i] = entries[i].getLocation();
}
return classpath;
}
public static IRuntimeClasspathEntry[] mergeClasspath(
IProgressMonitor monitor, AntlrBuildUnit unit,
IRuntimeClasspathEntry[] runtimeClassPath) throws CoreException {
return mergeClasspath(new Version(), monitor, unit, runtimeClassPath);
}
public static IRuntimeClasspathEntry[] mergeClasspath(Version version,
IProgressMonitor monitor, AntlrBuildUnit unit,
IRuntimeClasspathEntry[] runtimeClassPath) throws CoreException {
monitor.subTask("Checking classpath");
String[] classpath = getLocationClassPath(runtimeClassPath);
Collection<URL> urls = new LinkedHashSet<URL>();
for (int i = 0; i < classpath.length; i++) {
try {
URL url = new File(classpath[i]).toURI().toURL();
urls.add(url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
if (urls.size() > 0) {
URLClassLoader classLoader = new URLClassLoader(urls
.toArray(new URL[urls.size()]), null);
boolean valid = true;
String[] classes = { "org.antlr.runtime.Token", "org.antlr.Tool",
"antlr.Tool" };
String prefix = "ANTLR Parser Generator ";
for (String classname : classes) {
try {
// check the antlr runtime
Class<?> clazz = classLoader.loadClass(classname);
if (clazz.getName().equals("org.antlr.Tool")) {
// try 3.1.3+ or higher
InputStream in = clazz
.getResourceAsStream("antlr.properties");
if (in != null) {
try {
Properties prop = new Properties();
prop.load(in);
version.version = prefix
+ prop.getProperty("antlr.version");
} catch (IOException e) {
e.printStackTrace();
}
} else {
// 3.1.2 or minor
try {
Field vField = clazz
.getDeclaredField("VERSION");
version.version = prefix + vField.get(null);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
} catch (ClassNotFoundException e) {
valid = false;
break;
}
}
if (!valid) {
classpath = unit.getPackageClasspath()
.split(File.pathSeparator);
Collection<IRuntimeClasspathEntry> entries = new ArrayList<IRuntimeClasspathEntry>();
for (String jarLocation : classpath) {
IRuntimeClasspathEntry runtimeEntry = JavaRuntime
.newArchiveRuntimeClasspathEntry(Path
.fromOSString(jarLocation));
runtimeEntry
.setClasspathProperty(IRuntimeClasspathEntry.USER_CLASSES);
entries.add(runtimeEntry);
}
entries.addAll(Arrays.asList(runtimeClassPath));
return entries.toArray(new IRuntimeClasspathEntry[entries
.size()]);
}
}
return runtimeClassPath;
}
public static IRuntimeClasspathEntry[] computeDefaultRuntimeClassPath(
IJavaProject jproject) throws CoreException {
IRuntimeClasspathEntry[] unresolved = JavaRuntime
.computeUnresolvedRuntimeClasspath(jproject);
// 1. remove bootpath entries
// 2. resolve & translate to local file system paths
List<IRuntimeClasspathEntry> resolved = new ArrayList<IRuntimeClasspathEntry>(
unresolved.length);
for (int i = 0; i < unresolved.length; i++) {
IRuntimeClasspathEntry entry = unresolved[i];
if (entry.getClasspathProperty() == IRuntimeClasspathEntry.USER_CLASSES) {
IRuntimeClasspathEntry[] entries = JavaRuntime
.resolveRuntimeClasspathEntry(entry, jproject);
for (int j = 0; j < entries.length; j++) {
String location = entries[j].getLocation();
if (location != null) {
resolved.add(entries[j]);
}
}
}
}
return resolved.toArray(new IRuntimeClasspathEntry[resolved.size()]);
}
public boolean accept(IResource resource) {
boolean accept = false;
try {
IProject project = resource.getProject();
IJavaProject javaProject = JavaCore.create(project);
if (javaProject.exists()) {
IPath resourcePath = new Path(project.getName())
.append(resource.getProjectRelativePath());
IPath outputLocation = javaProject.getOutputLocation();
if (resourcePath.segmentCount() >= outputLocation
.segmentCount()) {
for (int segmentIndex = 0; segmentIndex < outputLocation
.segmentCount(); segmentIndex++) {
if (!outputLocation.segment(segmentIndex).equals(
resourcePath.segment(segmentIndex))) {
accept = true;
break;
}
}
}
} else {
accept = true;
}
} catch (JavaModelException e) {
e.printStackTrace();
}
// if (!accept) {
// System.out.println("Excluding " + resource);
// }
return accept;
}
public String format(String source) {
try {
@SuppressWarnings("unchecked")
Map<Object, Object> options = DefaultCodeFormatterConstants
.getEclipseDefaultSettings();
// initialize the compiler settings to be able to format 1.5 code
options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_5);
options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM,
JavaCore.VERSION_1_5);
options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_5);
final CodeFormatter codeFormatter = ToolFactory
.createCodeFormatter(options);
final int[] K = { CodeFormatter.K_STATEMENTS,
CodeFormatter.K_CLASS_BODY_DECLARATIONS,
CodeFormatter.K_EXPRESSION};
TextEdit edit = null;
for (int i = 0; i < K.length; i++) {
edit = codeFormatter.format(K[i], source,
0, source.length(), 0, System
.getProperty("line.separator"));
if (edit != null) {
// found
break;
}
}
if (edit != null) {
IDocument document = new Document(source);
edit.apply(document);
return document.get();
}
} catch (MalformedTreeException ex) {
AntlrCore.error(ex);
} catch (BadLocationException ex) {
AntlrCore.error(ex);
}
return source;
}
public AntlrLanguageTargetName getName() {
return AntlrLanguageTargetName.Java;
}
}