blob: 6791ccb5e57694720b912b5c95a815591d47de2d [file] [log] [blame]
/*
* Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Mike Norman - July 13 2010
// fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=318207
package org.eclipse.persistence.tools.dbws;
//javase imports
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringWriter;
import java.net.URI;
import java.util.Arrays;
//java eXtension imports
import javax.tools.DiagnosticCollector;
import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
/**
* <p>
* <b>PRIVATE:</b> InMemoryCompiler wraps a {@link javax.tools.JavaCompiler}.
* Only supports compiling a single file in-memory.
*
* @author mnorman
*
*/
public class InMemoryCompiler {
static final Iterable<String> OPTIONS = Arrays.asList("-g:source,lines,vars");
protected String targetFileName;
protected JavaCompiler compiler;
protected DiagnosticCollector<JavaFileObject> diagnosticsCollector;
protected JavaFileManager fileManager;
public InMemoryCompiler(String targetFileName) {
super();
this.targetFileName = targetFileName;
compiler = ToolProvider.getSystemJavaCompiler();
diagnosticsCollector = new DiagnosticCollector<JavaFileObject>();
}
public JavaCompiler getCompiler() {
return compiler;
}
public DiagnosticCollector<JavaFileObject> getDiagnosticsCollector() {
return diagnosticsCollector;
}
public byte[] compile(CharSequence source) {
JavaFileObject targetSource =
new JavaSourceFromString(targetFileName, source.toString());
ByteArrayJavaFileObject targetClass =
new ByteArrayJavaFileObject(targetFileName);
Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(targetSource);
ByteArrayFileManager bafm = new ByteArrayFileManager(
compiler.getStandardFileManager(null, null, null), targetClass);
StringWriter sw = new StringWriter();
CompilationTask task = compiler.getTask(sw, bafm, diagnosticsCollector, OPTIONS, null,
compilationUnits);
task.call();
return targetClass.toByteArray();
}
// wrapper class - not really a 'FileObject', uses in-memory string 'source'
static class JavaSourceFromString extends SimpleJavaFileObject {
CharSequence source;
JavaSourceFromString(String name, CharSequence source) {
// URI trick from SimpleJavaFileObject constructor - it only recognizes
// ('file:/' or 'jar:/'); anything else forces the 'getCharContent' callback for Kind.SOURCE
super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension),
Kind.SOURCE);
this.source = source;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return source;
}
}
// wrapper class - not really a 'FileObject', uses in-memory ByteArrayOutputStream 'bos'
static class ByteArrayJavaFileObject extends SimpleJavaFileObject {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
public ByteArrayJavaFileObject(String name) {
// URI trick from SimpleJavaFileObject constructor - it only recognizes
// ('file:' or 'jar:'); anything else forces the 'openOutputStream' callback for Kind.CLASS
super(URI.create("string:///" + name.replace('.', '/') + Kind.CLASS.extension),
Kind.CLASS);
}
public byte[] toByteArray() {
return bos.toByteArray();
}
@Override
public OutputStream openOutputStream() throws IOException {
return bos;
}
}
// wrapper class - compiler will use this 'FileManager' to manage compiler output
static class ByteArrayFileManager extends ForwardingJavaFileManager<JavaFileManager> {
ByteArrayJavaFileObject bajfo;
ByteArrayFileManager(StandardJavaFileManager sjfm, ByteArrayJavaFileObject bajfo) {
super(sjfm);
this.bajfo = bajfo;
}
@Override
public JavaFileObject getJavaFileForOutput(Location location, String name, Kind kind,
FileObject sibling) throws IOException {
return bajfo;
}
}
}