com.caucho.java.InternalCompiler2 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of resin-kernel Show documentation
Show all versions of resin-kernel Show documentation
Kernel for Resin Java Application Server
The newest version!
/*
* Copyright (c) 1998-2012 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.java;
import com.caucho.loader.*;
import com.caucho.util.*;
import com.caucho.vfs.*;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.tools.*;
/**
* Experimental internal compiler API using JDK 1.6 JavaCompiler.
*
* Based on initial tests, the performance difference does not seem
* to be large.
*/
public class InternalCompiler2 extends AbstractJavaCompiler {
private static final Logger log
= Logger.getLogger(InternalCompiler2.class.getName());
private static final List NULL_FILE_LIST
= Collections.emptyList();
private static final EnvironmentLocal _fileCacheLocal
= new EnvironmentLocal();
private static final FreeList _freeSystemManager
= new FreeList(4);
public InternalCompiler2(JavaCompilerUtil compiler)
{
super(compiler);
}
protected void compileInt(String []path, LineMap lineMap)
throws IOException, JavaCompileException
{
executeInt(path, lineMap);
}
protected Path getClassDir()
{
return _compiler.getClassDir();
}
/**
* Compiles the names files.
*/
private void executeInt(String []path, LineMap lineMap)
throws JavaCompileException, IOException
{
MemoryStream tempStream = new MemoryStream();
WriteStream error = new WriteStream(tempStream);
try {
// String parent = javaPath.getParent().getNativePath();
ArrayList optionList = new ArrayList();
optionList.add("-d");
optionList.add(_compiler.getClassDirName());
if (_compiler.getEncoding() != null) {
String encoding = Encoding.getJavaName(_compiler.getEncoding());
if (encoding != null && ! encoding.equals("ISO8859_1")) {
optionList.add("-encoding");
optionList.add(_compiler.getEncoding());
}
}
optionList.add("-classpath");
optionList.add(_compiler.getClassPath());
ArrayList options = _compiler.getArgs();
if (options != null)
optionList.addAll(options);
ArrayList classes = null;
ArrayList files = new ArrayList();
for (int i = 0; i < path.length; i++) {
Path javaPath = _compiler.getSourceDir().lookup(path[i]);
files.add(createJavaFileObject(javaPath));
}
if (log.isLoggable(Level.FINER)) {
logJavac(optionList);
}
Thread thread = Thread.currentThread();
ClassLoader oldLoader = thread.getContextClassLoader();
try {
// thread.setContextClassLoader(env);
try {
javax.tools.JavaCompiler compiler
= ToolProvider.getSystemJavaCompiler();
DiagnosticListener super JavaFileObject> diagnosticListener
= new DiagnosticListenerImpl();
JavaFileManager parentFileManager
= buildFileManager(compiler, oldLoader, diagnosticListener);
JavaFileManager fileManager
= new CauchoFileManager(parentFileManager);
javax.tools.JavaCompiler.CompilationTask value;
value = compiler.getTask(error.getPrintWriter(),
fileManager,
diagnosticListener,
options,
classes,
files);
Boolean result = value.call();
} catch (Exception e) {
throw new JavaCompileException(e);
}
error.close();
tempStream.close();
} finally {
thread.setContextClassLoader(oldLoader);
}
int status = 0;
ReadStream read = tempStream.openReadAndSaveBuffer();
JavacErrorParser parser = new JavacErrorParser(this, path[0], _compiler.getEncoding());
String errors = parser.parseErrors((InputStream) read, lineMap);
read.close();
if (errors != null)
errors = errors.trim();
if (log.isLoggable(Level.FINE)) {
read = tempStream.openReadAndSaveBuffer();
CharBuffer cb = new CharBuffer();
int ch;
while ((ch = read.read()) >= 0) {
cb.append((char) ch);
}
read.close();
log.fine(cb.toString());
}
else if (status == 0 && errors != null && ! errors.equals("")) {
final String msg = errors;
new com.caucho.loader.ClassLoaderContext(_compiler.getClassLoader()) {
public void run()
{
log.warning(msg);
}
};
}
if (status != 0)
throw new JavaCompileException(errors);
} finally {
tempStream.destroy();
}
}
private void logJavac(ArrayList optionList)
{
CharBuffer msg = new CharBuffer();
msg.append("javac(int)");
for (int i = 0; i < optionList.size(); i++) {
if (optionList.get(i).equals("-classpath")
&& ! log.isLoggable(Level.FINEST)) {
i++;
continue;
}
msg.append(" ");
msg.append(optionList.get(i));
}
log.finer(msg.toString());
}
private JavaFileObject createJavaFileObject(Path path)
{
return new PathFileObject(path, JavaFileObject.Kind.SOURCE);
}
private JavaFileManager buildFileManager(javax.tools.JavaCompiler compiler,
ClassLoader loader,
DiagnosticListener listener)
{
if (loader instanceof DynamicClassLoader) {
JavaFileManager parent = buildFileManager(compiler,
loader.getParent(),
listener);
return new EnvironmentFileManager(parent, (DynamicClassLoader) loader);
}
else {
JavaFileManager standardFileManager = _freeSystemManager.allocate();
if (standardFileManager == null) {
standardFileManager
= compiler.getStandardFileManager(listener, null, null);
}
return new CacheFileManager(standardFileManager, loader);
}
}
static class PathFileObject extends SimpleJavaFileObject {
private final Path _path;
PathFileObject(Path path, JavaFileObject.Kind kind)
{
super(createURI(path), kind);
_path = path;
}
private static URI createURI(Path path)
{
try {
return new URI(path.getURL());
} catch (Exception e) {
throw new JavaCompileException(e);
}
}
public String getName()
{
return _path.getFullPath();
}
public long getLastModified()
{
return _path.getLastModified();
}
public boolean delete()
{
try {
return _path.remove();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public CharSequence getCharContent(boolean ignoreEncodingErrors)
throws IOException
{
StringBuilder sb = new StringBuilder();
ReadStream is = _path.openRead();
try {
char []buffer = new char[1024];
int len;
while ((len = is.read(buffer, 0, buffer.length)) > 0) {
sb.append(buffer, 0, len);
}
return sb;
} finally {
is.close();
}
}
public InputStream openInputStream()
throws IOException
{
return _path.openRead();
}
public OutputStream openOutputStream()
throws IOException
{
_path.getParent().mkdirs();
return _path.openWrite();
}
@Override
public String toString()
{
return getClass().getSimpleName() + "[" + _path + "]";
}
}
static class DiagnosticListenerImpl implements DiagnosticListener {
public void report(Diagnostic extends S> diagnostic)
{
System.out.println("ERROR: " + diagnostic);
}
}
class DelegatingFileManager implements JavaFileManager {
protected JavaFileManager _parent;
DelegatingFileManager(JavaFileManager parent)
{
_parent = parent;
}
public ClassLoader getClassLoader(JavaFileManager.Location location)
{
return _parent.getClassLoader(location);
}
public FileObject getFileForInput(JavaFileManager.Location location,
String packageName,
String relativeName)
throws IOException
{
FileObject result
= _parent.getFileForInput(location, packageName, relativeName);
return result;
}
public FileObject getFileForOutput(JavaFileManager.Location location,
String packageName,
String relativeName,
FileObject sibling)
throws IOException
{
FileObject result = _parent.getFileForOutput(location,
packageName, relativeName,
sibling);
return result;
}
public JavaFileObject getJavaFileForInput(JavaFileManager.Location location,
String className,
JavaFileObject.Kind kind)
throws IOException
{
return _parent.getJavaFileForInput(location, className, kind);
}
public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location,
String className,
JavaFileObject.Kind kind,
FileObject sibling)
throws IOException
{
JavaFileObject result
= _parent.getJavaFileForOutput(location, className, kind, sibling);
return result;
}
public int isSupportedOption(String option)
{
return _parent.isSupportedOption(option);
}
public boolean handleOption(String current, Iterator remaining)
{
return _parent.handleOption(current, remaining);
}
public boolean hasLocation(JavaFileManager.Location location)
{
return _parent.hasLocation(location);
}
public String inferBinaryName(JavaFileManager.Location location,
JavaFileObject file)
{
return _parent.inferBinaryName(location, file);
}
public boolean isSameFile(FileObject a, FileObject b)
{
return _parent.isSameFile(a, b);
}
public Iterable list(JavaFileManager.Location location,
String packageName,
Set kinds,
boolean recurse)
throws IOException
{
Iterable result
= _parent.list(location, packageName, kinds, recurse);
// System.out.println("LIST: " + result);
return result;
}
public void flush()
throws IOException
{
_parent.flush();
}
public void close()
throws IOException
{
_parent.close();
}
}
class CauchoFileManager extends DelegatingFileManager {
CauchoFileManager(JavaFileManager parent)
{
super(parent);
}
public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location,
String className,
JavaFileObject.Kind kind,
FileObject sibling)
throws IOException
{
Path path;
switch (kind) {
case CLASS:
{
String name = className.replace('.', '/') + ".class";
path = getClassDir().lookup(name);
return new PathFileObject(path, kind);
}
}
return super.getJavaFileForOutput(location, className, kind, sibling);
}
}
class EnvironmentFileManager extends DelegatingFileManager {
private final DynamicClassLoader _loader;
EnvironmentFileManager(JavaFileManager parent,
DynamicClassLoader loader)
{
super(parent);
_loader = loader;
}
}
class CacheFileManager extends DelegatingFileManager {
private final FileCache _fileCache;
CacheFileManager(JavaFileManager parent, ClassLoader loader)
{
super(parent);
FileCache fileCache = _fileCacheLocal.getLevel(loader);
if (fileCache == null) {
fileCache = new FileCache();
_fileCacheLocal.set(fileCache, loader);
}
_fileCache = fileCache;
}
public int isSupportedOption(String option)
{
return 0;
}
public boolean handleOption(String current, Iterator remaining)
{
return false;
}
public Iterable list(JavaFileManager.Location location,
String packageName,
Set kinds,
boolean recurse)
throws IOException
{
ListKey key = new ListKey(location, packageName, kinds, recurse);
Iterable result = _fileCache.getList(key);
if (result == null) {
result = super.list(location, packageName, kinds, recurse);
if (result == null)
result = NULL_FILE_LIST;
_fileCache.putList(key, result);
}
else {
}
if (result == NULL_FILE_LIST)
return null;
else
return result;
}
public void close()
{
JavaFileManager parent = _parent;
_parent = null;
if (parent != null)
_freeSystemManager.free(parent);
}
}
static class ListKey {
private final JavaFileManager.Location _location;
private final String _packageName;
private final Set _kinds;
private final boolean _recurse;
ListKey(JavaFileManager.Location location,
String packageName,
Set kinds,
boolean recurse)
{
_location = location;
_packageName = packageName;
_kinds = kinds;
_recurse = recurse;
}
@Override
public int hashCode()
{
return _packageName.hashCode() * 65521 + _kinds.hashCode();
}
@Override
public boolean equals(Object o)
{
if (o == null || o.getClass() != getClass())
return false;
ListKey key = (ListKey) o;
return (_packageName.equals(key._packageName)
&& _kinds.equals(key._kinds)
&& _location.equals(key._location)
&& _recurse == key._recurse);
}
}
static class FileCache {
private final LruCache> _listCache
= new LruCache>(1024);
Iterable getList(ListKey key)
{
return _listCache.get(key);
}
void putList(ListKey key, Iterable list)
{
_listCache.put(key, list);
}
}
}