Code polishing and general cleanup

This commit is contained in:
Oleg Zhurakousky
2018-06-27 08:43:28 -04:00
parent bb397c6a07
commit 377c4d93f0
7 changed files with 61 additions and 89 deletions

View File

@@ -1,12 +1,12 @@
/* /*
* Copyright 2016 the original author or authors. * Copyright 2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -18,7 +18,7 @@ package org.springframework.cloud.function.compiler.java;
/** /**
* Encapsulates a name with the bytes for its class definition. * Encapsulates a name with the bytes for its class definition.
* *
* @author Andy Clement * @author Andy Clement
*/ */
public class CompiledClassDefinition { public class CompiledClassDefinition {
@@ -34,9 +34,7 @@ public class CompiledClassDefinition {
if (classname.startsWith("/")) { if (classname.startsWith("/")) {
classname = classname.substring(1); classname = classname.substring(1);
} }
classname = classname.replace('/', '.').substring(0, classname.length() - 6); // strip classname = classname.replace('/', '.').substring(0, classname.length() - 6); // strip off .class
// off
// .class
} }
public String getName() { public String getName() {
@@ -57,4 +55,4 @@ public class CompiledClassDefinition {
return this.classname; return this.classname;
} }
} }

View File

@@ -1,12 +1,12 @@
/* /*
* Copyright 2016 the original author or authors. * Copyright 2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -24,21 +24,19 @@ import java.util.NoSuchElementException;
/** /**
* Walks a directory hierarchy from some base directory discovering files. * Walks a directory hierarchy from some base directory discovering files.
* *
* @author Andy Clement * @author Andy Clement
*/ */
public class DirEnumeration implements Enumeration<File> { public class DirEnumeration implements Enumeration<File> {
// private final static Logger logger = LoggerFactory.getLogger(DirEnumeration.class);
// The starting point // The starting point
private File basedir; private File basedir;
// Candidates collected so far // Candidates collected so far
private List<File> filesToReturn; private List<File> filesToReturn;
// Places still to explore for candidates // Places still to explore for candidates
private List<File> directoriesToExplore; private List<File> directoriesToExplore;
public DirEnumeration(File basedir) { public DirEnumeration(File basedir) {
this.basedir = basedir; this.basedir = basedir;
@@ -58,7 +56,7 @@ public class DirEnumeration implements Enumeration<File> {
} }
} }
} }
@Override @Override
public boolean hasMoreElements() { public boolean hasMoreElements() {
computeValue(); computeValue();
@@ -87,7 +85,6 @@ public class DirEnumeration implements Enumeration<File> {
} }
} }
} }
// logger.debug("after visiting {} filesToReturn=#{} dirsToExplore=#{}",dir,filesToReturn.size(), directoriesToExplore.size());
} }
public File getDirectory() { public File getDirectory() {
@@ -97,7 +94,7 @@ public class DirEnumeration implements Enumeration<File> {
/** /**
* Return the relative path of this file to the base directory that the directory enumeration was * Return the relative path of this file to the base directory that the directory enumeration was
* started for. * started for.
* @param file a file discovered returned by this enumeration * @param file a file discovered returned by this enumeration
* @return the relative path of the file (for example: a/b/c/D.class) * @return the relative path of the file (for example: a/b/c/D.class)
*/ */
public String getName(File file) { public String getName(File file) {

View File

@@ -1,12 +1,12 @@
/* /*
* Copyright 2016 the original author or authors. * Copyright 2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -39,17 +39,17 @@ import org.springframework.cloud.function.compiler.java.MemoryBasedJavaFileManag
/** /**
* Iterable that will produce an iterator that returns classes found * Iterable that will produce an iterator that returns classes found
* on a specified classpath that meet specified criteria. For jars it finds, the * on a specified classpath that meet specified criteria. For jars it finds, the
* iterator will go into nested jars - this handles the situation with a * iterator will go into nested jars - this handles the situation with a
* spring boot uberjar. * spring boot uberjar.
* *
* @author Andy Clement * @author Andy Clement
*/ */
public class IterableClasspath extends CloseableFilterableJavaFileObjectIterable { public class IterableClasspath extends CloseableFilterableJavaFileObjectIterable {
private static Logger logger = LoggerFactory.getLogger(IterableClasspath.class); private static Logger logger = LoggerFactory.getLogger(IterableClasspath.class);
private List<File> classpathEntries = new ArrayList<>(); private List<File> classpathEntries = new ArrayList<>();
private List<ZipFile> openArchives = new ArrayList<>(); private List<ZipFile> openArchives = new ArrayList<>();
/** /**
@@ -134,7 +134,7 @@ public class IterableClasspath extends CloseableFilterableJavaFileObjectIterable
String entryName = entry.getName(); String entryName = entry.getName();
if (accept(entryName)) { if (accept(entryName)) {
if (nestedZip!=null) { if (nestedZip!=null) {
nextEntry = new NestedZipEntryJavaFileObject(openFile, openArchive,nestedZip, entry); nextEntry = new NestedZipEntryJavaFileObject(openFile, openArchive,nestedZip, entry);
} else { } else {
nextEntry = new ZipEntryJavaFileObject(openFile, openArchive, entry); nextEntry = new ZipEntryJavaFileObject(openFile, openArchive, entry);
} }
@@ -143,7 +143,6 @@ public class IterableClasspath extends CloseableFilterableJavaFileObjectIterable
// nested jar in uber jar // nested jar in uber jar
logger.debug("opening nested archive {}",entry.getName()); logger.debug("opening nested archive {}",entry.getName());
ZipInputStream zis = new ZipInputStream(openArchive.getInputStream(entry)); ZipInputStream zis = new ZipInputStream(openArchive.getInputStream(entry));
// nextEntry = new NestedZipEntryJavaFileObject(openArchive.firstElement(),openArchive.peek(),entry);
Enumeration<? extends ZipEntry> nestedZipEnumerator = new ZipEnumerator(zis); Enumeration<? extends ZipEntry> nestedZipEnumerator = new ZipEnumerator(zis);
nestedZip = entry; nestedZip = entry;
openArchiveEnumeration.push(nestedZipEnumerator); openArchiveEnumeration.push(nestedZipEnumerator);
@@ -217,10 +216,10 @@ public class IterableClasspath extends CloseableFilterableJavaFileObjectIterable
nextEntry = null; nextEntry = null;
return retval; return retval;
} }
} }
public void reset() { public void reset() {
close(); close();
} }
} }

View File

@@ -62,24 +62,22 @@ public class MemoryBasedJavaFileManager implements JavaFileManager {
final static String BOOT_PACKAGING_PREFIX_FOR_CLASSES = "BOOT-INF/classes/"; final static String BOOT_PACKAGING_PREFIX_FOR_CLASSES = "BOOT-INF/classes/";
final static String BOOT_PACKAGING_PREFIX_FOR_LIBRARIES = "BOOT-INF/lib/"; final static String BOOT_PACKAGING_PREFIX_FOR_LIBRARIES = "BOOT-INF/lib/";
private static Logger logger = LoggerFactory private static Logger logger = LoggerFactory
.getLogger(MemoryBasedJavaFileManager.class); .getLogger(MemoryBasedJavaFileManager.class);
private CompilationOutputCollector outputCollector; private CompilationOutputCollector outputCollector;
// private List<CloseableFilterableJavaFileObjectIterable> toClose = new ArrayList<>();
private Map<String, File> resolvedAdditionalDependencies = new LinkedHashMap<>(); private Map<String, File> resolvedAdditionalDependencies = new LinkedHashMap<>();
private String platformClasspath; private String platformClasspath;
private String classpath; private String classpath;
private CompilationInfoCache compilationInfoCache; private CompilationInfoCache compilationInfoCache;
private Map<Key, IterableClasspath> iterables = new HashMap<>(); private Map<Key, IterableClasspath> iterables = new HashMap<>();
public MemoryBasedJavaFileManager() { public MemoryBasedJavaFileManager() {
outputCollector = new CompilationOutputCollector(); outputCollector = new CompilationOutputCollector();
compilationInfoCache = new CompilationInfoCache(); compilationInfoCache = new CompilationInfoCache();
@@ -98,19 +96,19 @@ public class MemoryBasedJavaFileManager implements JavaFileManager {
logger.debug("getClassLoader({})", location); logger.debug("getClassLoader({})", location);
return null; // Do not currently need to load plugins return null; // Do not currently need to load plugins
} }
// Holds information that may help speed up compilation // Holds information that may help speed up compilation
static class CompilationInfoCache { static class CompilationInfoCache {
private Map<File, ArchiveInfo> archivePackageCache; private Map<File, ArchiveInfo> archivePackageCache;
static class ArchiveInfo { static class ArchiveInfo {
// The packages identified in a particular archive // The packages identified in a particular archive
private List<String> packageNames; private List<String> packageNames;
private boolean isBootJar = false; private boolean isBootJar = false;
public ArchiveInfo(List<String> packageNames, boolean isBootJar) { public ArchiveInfo(List<String> packageNames, boolean isBootJar) {
this.packageNames = packageNames; this.packageNames = packageNames;
Collections.sort(this.packageNames); Collections.sort(this.packageNames);
@@ -140,7 +138,7 @@ public class MemoryBasedJavaFileManager implements JavaFileManager {
} }
} }
} }
ArchiveInfo getArchiveInfoFor(File archive) { ArchiveInfo getArchiveInfoFor(File archive) {
if (!archive.isFile() || !(archive.getName().endsWith(".zip") || archive.getName().endsWith(".jar"))) { if (!archive.isFile() || !(archive.getName().endsWith(".zip") || archive.getName().endsWith(".jar"))) {
// it is not an archive // it is not an archive
@@ -160,12 +158,12 @@ public class MemoryBasedJavaFileManager implements JavaFileManager {
throw new IllegalStateException("Unexpected problem caching entries from "+archive.getName(), e); throw new IllegalStateException("Unexpected problem caching entries from "+archive.getName(), e);
} }
} }
/** /**
* Walk the specified archive and collect up the package names of any .class files encountered. If * Walk the specified archive and collect up the package names of any .class files encountered. If
* the archive contains nested jars packaged in a BOOT style way (under a BOOT-INF/lib folder) then * the archive contains nested jars packaged in a BOOT style way (under a BOOT-INF/lib folder) then
* walk those too and include relevant packages. * walk those too and include relevant packages.
* *
* @param file archive file to discover packages from * @param file archive file to discover packages from
* @return an ArchiveInfo encapsulating package info from the archive * @return an ArchiveInfo encapsulating package info from the archive
*/ */
@@ -194,9 +192,6 @@ public class MemoryBasedJavaFileManager implements JavaFileManager {
} }
} else { } else {
int idx = name.lastIndexOf('/') + 1; int idx = name.lastIndexOf('/') + 1;
// if (name.contains("TestX")) {
// System.out.println("For TestX: "+name+" "+idx+" "+BOOT_PACKAGING_PREFIX_FOR_CLASSES.length());
// }
if (idx != 0 ) { if (idx != 0 ) {
// Normalize to forward slashes // Normalize to forward slashes
name = name.replace('\\', '/'); name = name.replace('\\', '/');
@@ -243,19 +238,19 @@ public class MemoryBasedJavaFileManager implements JavaFileManager {
private String packageName; private String packageName;
private Set<Kind> kinds; private Set<Kind> kinds;
private boolean recurse; private boolean recurse;
public Key(String classpath, String packageName, Set<Kind> kinds, boolean recurse) { public Key(String classpath, String packageName, Set<Kind> kinds, boolean recurse) {
this.classpath = classpath; this.classpath = classpath;
this.packageName = packageName; this.packageName = packageName;
this.kinds = kinds; this.kinds = kinds;
this.recurse = recurse; this.recurse = recurse;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return ((classpath.hashCode()*37+(packageName==null?0:packageName.hashCode()))*37+kinds.hashCode())*37+(recurse?1:0); return ((classpath.hashCode()*37+(packageName==null?0:packageName.hashCode()))*37+kinds.hashCode())*37+(recurse?1:0);
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (!(obj instanceof Key)) { if (!(obj instanceof Key)) {
@@ -270,12 +265,12 @@ public class MemoryBasedJavaFileManager implements JavaFileManager {
} }
private String getPlatformClassPath() { private String getPlatformClassPath() {
if (platformClasspath == null) { if (platformClasspath == null) {
platformClasspath = System.getProperty("sun.boot.class.path"); platformClasspath = System.getProperty("sun.boot.class.path");
} }
return platformClasspath; return platformClasspath;
} }
@Override @Override
public Iterable<JavaFileObject> list(Location location, String packageName, public Iterable<JavaFileObject> list(Location location, String packageName,
Set<Kind> kinds, boolean recurse) throws IOException { Set<Kind> kinds, boolean recurse) throws IOException {
@@ -487,4 +482,4 @@ public class MemoryBasedJavaFileManager implements JavaFileManager {
return resolvedAdditionalDependencies; return resolvedAdditionalDependencies;
} }
} }

View File

@@ -34,15 +34,15 @@ import org.slf4j.LoggerFactory;
/** /**
* Compile Java source at runtime and load it. * Compile Java source at runtime and load it.
* *
* @author Andy Clement * @author Andy Clement
*/ */
public class RuntimeJavaCompiler { public class RuntimeJavaCompiler {
private JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); private JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
private static Logger logger = LoggerFactory.getLogger(RuntimeJavaCompiler.class); private static Logger logger = LoggerFactory.getLogger(RuntimeJavaCompiler.class);
/** /**
* Compile the named class consisting of the supplied source code. If successful load the class * Compile the named class consisting of the supplied source code. If successful load the class
* and return it. Multiple classes may get loaded if the source code included anonymous/inner/local * and return it. Multiple classes may get loaded if the source code included anonymous/inner/local
@@ -54,18 +54,12 @@ public class RuntimeJavaCompiler {
*/ */
public CompilationResult compile(String className, String classSourceCode, String... dependencies) { public CompilationResult compile(String className, String classSourceCode, String... dependencies) {
logger.info("Compiling source for class {} using compiler {}",className,compiler.getClass().getName()); logger.info("Compiling source for class {} using compiler {}",className,compiler.getClass().getName());
DiagnosticCollector<JavaFileObject> diagnosticCollector = new DiagnosticCollector<JavaFileObject>(); DiagnosticCollector<JavaFileObject> diagnosticCollector = new DiagnosticCollector<JavaFileObject>();
MemoryBasedJavaFileManager fileManager = new MemoryBasedJavaFileManager(); MemoryBasedJavaFileManager fileManager = new MemoryBasedJavaFileManager();
List<CompilationMessage> resolutionMessages = fileManager.addAndResolveDependencies(dependencies); List<CompilationMessage> resolutionMessages = fileManager.addAndResolveDependencies(dependencies);
// JavaFileObject sourceFile = new StringBasedJavaSourceFileObject(className, classSourceCode);
JavaFileObject sourceFile = InMemoryJavaFileObject.getSourceJavaFileObject(className, classSourceCode); JavaFileObject sourceFile = InMemoryJavaFileObject.getSourceJavaFileObject(className, classSourceCode);
// new InMemoryJavaFileObject(StandardLocation.SOURCE_PATH, className, javax.tools.JavaFileObject.Kind.SOURCE, null);
// try (Writer w = sourceFile.openWriter()) {
// w.write(classSourceCode);
// } catch (IOException ioe) {
// ioe.printStackTrace();
// }
Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(sourceFile); Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(sourceFile);
CompilationTask task = compiler.getTask(null, fileManager , diagnosticCollector, null, null, compilationUnits); CompilationTask task = compiler.getTask(null, fileManager , diagnosticCollector, null, null, compilationUnits);
@@ -73,7 +67,7 @@ public class RuntimeJavaCompiler {
CompilationResult compilationResult = new CompilationResult(success); CompilationResult compilationResult = new CompilationResult(success);
compilationResult.recordCompilationMessages(resolutionMessages); compilationResult.recordCompilationMessages(resolutionMessages);
compilationResult.setResolvedAdditionalDependencies(new ArrayList<>(fileManager.getResolvedAdditionalDependencies().values())); compilationResult.setResolvedAdditionalDependencies(new ArrayList<>(fileManager.getResolvedAdditionalDependencies().values()));
// If successful there may be no errors but there might be info/warnings // If successful there may be no errors but there might be info/warnings
for (Diagnostic<? extends JavaFileObject> diagnostic : diagnosticCollector.getDiagnostics()) { for (Diagnostic<? extends JavaFileObject> diagnostic : diagnosticCollector.getDiagnostics()) {
CompilationMessage.Kind kind = (diagnostic.getKind()==Kind.ERROR?CompilationMessage.Kind.ERROR:CompilationMessage.Kind.OTHER); CompilationMessage.Kind kind = (diagnostic.getKind()==Kind.ERROR?CompilationMessage.Kind.ERROR:CompilationMessage.Kind.OTHER);
@@ -95,8 +89,8 @@ public class RuntimeJavaCompiler {
CompilationMessage compilationMessage = new CompilationMessage(kind,diagnostic.getMessage(null),sourceCode,startPosition,(int)diagnostic.getEndPosition()); CompilationMessage compilationMessage = new CompilationMessage(kind,diagnostic.getMessage(null),sourceCode,startPosition,(int)diagnostic.getEndPosition());
compilationResult.recordCompilationMessage(compilationMessage); compilationResult.recordCompilationMessage(compilationMessage);
} }
if (success) { if (success) {
List<CompiledClassDefinition> ccds = fileManager.getCompiledClasses(); List<CompiledClassDefinition> ccds = fileManager.getCompiledClasses();
List<Class<?>> classes = new ArrayList<>(); List<Class<?>> classes = new ArrayList<>();
try (SimpleClassLoader ccl = new SimpleClassLoader(this.getClass().getClassLoader())) { try (SimpleClassLoader ccl = new SimpleClassLoader(this.getClass().getClassLoader())) {
for (CompiledClassDefinition ccd: ccds) { for (CompiledClassDefinition ccd: ccds) {
@@ -111,4 +105,4 @@ public class RuntimeJavaCompiler {
} }
return compilationResult; return compilationResult;
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2016-2017 the original author or authors. * Copyright 2016-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -19,7 +19,6 @@ package org.springframework.cloud.function.context.catalog;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
@@ -66,28 +65,18 @@ public class InMemoryFunctionCatalog
@Override @Override
public <T> void register(FunctionRegistration<T> registration) { public <T> void register(FunctionRegistration<T> registration) {
FunctionRegistrationEvent event; Class<?> type = Object.class;
Class<?> type;
if (registration.getTarget() instanceof Function) { if (registration.getTarget() instanceof Function) {
type = Function.class; type = Function.class;
event = new FunctionRegistrationEvent(this, Function.class,
registration.getNames());
} }
else if (registration.getTarget() instanceof Supplier) { else if (registration.getTarget() instanceof Supplier) {
type = Supplier.class; type = Supplier.class;
event = new FunctionRegistrationEvent(this, Supplier.class,
registration.getNames());
} }
else if (registration.getTarget() instanceof Consumer) { else if (registration.getTarget() instanceof Consumer) {
type = Consumer.class; type = Consumer.class;
event = new FunctionRegistrationEvent(this, Consumer.class,
registration.getNames());
}
else {
type = Object.class;
event = new FunctionRegistrationEvent(this, Object.class,
registration.getNames());
} }
FunctionRegistrationEvent event = new FunctionRegistrationEvent(this, type, registration.getNames());
registrations.put(registration.getTarget(), registration); registrations.put(registration.getTarget(), registration);
FunctionRegistration<T> wrapped = registration.wrap(); FunctionRegistration<T> wrapped = registration.wrap();
if (wrapped != registration) { if (wrapped != registration) {

View File

@@ -39,7 +39,7 @@ public abstract class MessageUtils {
* isolated class loader, then the message will be created with the target class * isolated class loader, then the message will be created with the target class
* loader (therefore the {@link Message} class must be on the classpath of the target * loader (therefore the {@link Message} class must be on the classpath of the target
* class loader). * class loader).
* *
* @param handler the function that will be applied to the message * @param handler the function that will be applied to the message
* @param payload the payload of the message * @param payload the payload of the message
* @param headers the headers for the message * @param headers the headers for the message
@@ -71,10 +71,10 @@ public abstract class MessageUtils {
/** /**
* Convert a message from the handler into one that is safe to consume in the caller's * Convert a message from the handler into one that is safe to consume in the caller's
* class laoder. If the handler is a wrapper for a function in an isolated class * class loader. If the handler is a wrapper for a function in an isolated class
* loader, then the message will be created with the target class loader (therefore * loader, then the message will be created with the target class loader (therefore
* the {@link Message} class must be on the classpath of the target class loader). * the {@link Message} class must be on the classpath of the target class loader).
* *
* @param handler the function that generated the message * @param handler the function that generated the message
* @param message the message to convert * @param message the message to convert
* @return a message with the correct class loader * @return a message with the correct class loader