From 1896d1e474583606ddd8a083d9f8d00ccfb70e86 Mon Sep 17 00:00:00 2001 From: onobc Date: Fri, 11 Feb 2022 20:29:54 -0600 Subject: [PATCH] Remove spring-cloud-function-compiler module Fixes gh-805 --- README.adoc | 1 - docs/src/main/asciidoc/_intro.adoc | 1 - docs/src/main/asciidoc/sagan-index.adoc | 1 - scripts/function-registry.sh | 3 - scripts/registerConsumer.sh | 17 - scripts/registerFunction.sh | 21 - scripts/registerSupplier.sh | 17 - scripts/stream.sh | 56 -- scripts/task.sh | 18 - scripts/web.sh | 27 - spring-cloud-function-compiler/.jdk8 | 0 .../compiler/AbstractFunctionCompiler.java | 189 ----- .../compiler/CompilationResultFactory.java | 27 - .../compiler/CompiledFunctionFactory.java | 110 --- .../function/compiler/ConsumerCompiler.java | 45 - .../function/compiler/FunctionCompiler.java | 55 -- .../function/compiler/SupplierCompiler.java | 45 - .../app/CompiledFunctionRegistry.java | 112 --- .../compiler/app/CompilerApplication.java | 31 - .../compiler/app/CompilerController.java | 52 -- .../FunctionProxyApplicationListener.java | 183 ----- ...eableFilterableJavaFileObjectIterable.java | 124 --- .../java/CompilationFailedException.java | 42 - .../compiler/java/CompilationMessage.java | 137 ---- .../java/CompilationOutputCollector.java | 72 -- .../compiler/java/CompilationResult.java | 101 --- .../java/CompiledClassDefinition.java | 63 -- .../compiler/java/CompositeProxySelector.java | 50 -- .../compiler/java/DependencyResolver.java | 485 ----------- .../compiler/java/DirEntryJavaFileObject.java | 143 ---- .../compiler/java/DirEnumeration.java | 112 --- .../compiler/java/InMemoryJavaFileObject.java | 239 ------ .../compiler/java/IterableClasspath.java | 298 ------- .../compiler/java/IterableJrtModule.java | 114 --- .../compiler/java/JrtEntryJavaFileObject.java | 159 ---- .../compiler/java/JrtFsEnumeration.java | 140 ---- .../function/compiler/java/MavenSettings.java | 325 -------- .../compiler/java/MavenSettingsReader.java | 157 ---- .../java/MemoryBasedJavaFileManager.java | 769 ------------------ .../java/NestedZipEntryJavaFileObject.java | 187 ----- .../compiler/java/RuntimeJavaCompiler.java | 128 --- .../compiler/java/SimpleClassLoader.java | 59 -- .../compiler/java/ZipEntryJavaFileObject.java | 159 ---- .../proxy/AbstractByteCodeLoadingProxy.java | 88 -- .../proxy/AbstractLambdaCompilingProxy.java | 83 -- .../proxy/ByteCodeLoadingConsumer.java | 41 - .../proxy/ByteCodeLoadingFunction.java | 43 - .../proxy/ByteCodeLoadingSupplier.java | 41 - .../proxy/LambdaCompilingConsumer.java | 40 - .../proxy/LambdaCompilingFunction.java | 43 - .../proxy/LambdaCompilingSupplier.java | 41 - .../main/resources/META-INF/spring.factories | 2 - .../CompilerDependencyResolutionTests.java | 466 ----------- .../compiler/ConsumerCompilerTests.java | 50 -- .../compiler/FunctionCompilerTests.java | 53 -- .../compiler/SupplierCompilerTests.java | 63 -- .../java/RuntimeJavaCompilerTests.java | 174 ---- .../proxy/ByteCodeLoadingFunctionTests.java | 106 --- .../function/core/FunctionFactoryUtils.java | 146 ---- .../core/FunctionFactoryUtilsTests.java | 94 --- .../src/test/resources/logback.xml | 8 - .../function-sample-compiler/.jdk8 | 0 .../function-sample-compiler/build.gradle | 51 -- .../gradle/wrapper/gradle-wrapper.jar | Bin 53556 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 - .../function-sample-compiler/gradlew | 164 ---- .../function-sample-compiler/gradlew.bat | 90 -- .../java/com/example/SampleApplication.java | 31 - .../example/SampleCompiledConsumerTests.java | 58 -- .../example/SampleCompiledFunctionTests.java | 47 -- .../function-sample-pof/build.gradle | 1 - .../function-sample-pojo/build.gradle | 1 - .../function-sample-task/build.gradle | 1 - .../function-sample-task/pom.xml | 4 - .../function-sample/build.gradle | 1 - 75 files changed, 7110 deletions(-) delete mode 100755 scripts/function-registry.sh delete mode 100755 scripts/registerConsumer.sh delete mode 100755 scripts/registerFunction.sh delete mode 100755 scripts/registerSupplier.sh delete mode 100755 scripts/stream.sh delete mode 100755 scripts/task.sh delete mode 100755 scripts/web.sh delete mode 100644 spring-cloud-function-compiler/.jdk8 delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/AbstractFunctionCompiler.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/CompilationResultFactory.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/CompiledFunctionFactory.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/ConsumerCompiler.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/FunctionCompiler.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/SupplierCompiler.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/app/CompiledFunctionRegistry.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/app/CompilerApplication.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/app/CompilerController.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/config/FunctionProxyApplicationListener.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CloseableFilterableJavaFileObjectIterable.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompilationFailedException.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompilationMessage.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompilationOutputCollector.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompilationResult.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompiledClassDefinition.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompositeProxySelector.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/DependencyResolver.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/DirEntryJavaFileObject.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/DirEnumeration.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/InMemoryJavaFileObject.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/IterableClasspath.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/IterableJrtModule.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/JrtEntryJavaFileObject.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/JrtFsEnumeration.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/MavenSettings.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/MavenSettingsReader.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/MemoryBasedJavaFileManager.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/NestedZipEntryJavaFileObject.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/RuntimeJavaCompiler.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/SimpleClassLoader.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/ZipEntryJavaFileObject.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/AbstractByteCodeLoadingProxy.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/AbstractLambdaCompilingProxy.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/ByteCodeLoadingConsumer.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/ByteCodeLoadingFunction.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/ByteCodeLoadingSupplier.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/LambdaCompilingConsumer.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/LambdaCompilingFunction.java delete mode 100644 spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/LambdaCompilingSupplier.java delete mode 100644 spring-cloud-function-compiler/src/main/resources/META-INF/spring.factories delete mode 100644 spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/CompilerDependencyResolutionTests.java delete mode 100644 spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/ConsumerCompilerTests.java delete mode 100644 spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/FunctionCompilerTests.java delete mode 100644 spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/SupplierCompilerTests.java delete mode 100644 spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/java/RuntimeJavaCompilerTests.java delete mode 100644 spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/proxy/ByteCodeLoadingFunctionTests.java delete mode 100644 spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/core/FunctionFactoryUtils.java delete mode 100644 spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/core/FunctionFactoryUtilsTests.java delete mode 100644 spring-cloud-function-compiler/src/test/resources/logback.xml delete mode 100644 spring-cloud-function-samples/function-sample-compiler/.jdk8 delete mode 100644 spring-cloud-function-samples/function-sample-compiler/build.gradle delete mode 100644 spring-cloud-function-samples/function-sample-compiler/gradle/wrapper/gradle-wrapper.jar delete mode 100644 spring-cloud-function-samples/function-sample-compiler/gradle/wrapper/gradle-wrapper.properties delete mode 100755 spring-cloud-function-samples/function-sample-compiler/gradlew delete mode 100644 spring-cloud-function-samples/function-sample-compiler/gradlew.bat delete mode 100644 spring-cloud-function-samples/function-sample-compiler/src/main/java/com/example/SampleApplication.java delete mode 100644 spring-cloud-function-samples/function-sample-compiler/src/test/java/com/example/SampleCompiledConsumerTests.java delete mode 100644 spring-cloud-function-samples/function-sample-compiler/src/test/java/com/example/SampleCompiledFunctionTests.java diff --git a/README.adoc b/README.adoc index 595bac1d8..a96231d59 100644 --- a/README.adoc +++ b/README.adoc @@ -62,7 +62,6 @@ endpoints and/or message stream listeners/publishers with RabbitMQ, Kafka etc. * _Packaging functions for deployments, specific to the target platform (e.g., Project Riff, AWS Lambda and more)_ * _Adapters to expose function to the outside world as HTTP endpoints etc._ * _Deploying a JAR file containing such an application context with an isolated classloader, so that you can pack them together in a single JVM._ -* _Compiling strings which are Java function bodies into bytecode, and then turning them into `@Beans` that can be wrapped as above._ * _Adapters for https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-aws[AWS Lambda], https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-azure[Azure], https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp[Google Cloud Functions], https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-openwhisk[Apache OpenWhisk] and possibly other "serverless" service providers._ == Getting Started diff --git a/docs/src/main/asciidoc/_intro.adoc b/docs/src/main/asciidoc/_intro.adoc index 3812b572c..c1895c454 100644 --- a/docs/src/main/asciidoc/_intro.adoc +++ b/docs/src/main/asciidoc/_intro.adoc @@ -49,5 +49,4 @@ endpoints and/or message stream listeners/publishers with RabbitMQ, Kafka etc. * _Packaging functions for deployments, specific to the target platform (e.g., Project Riff, AWS Lambda and more)_ * _Adapters to expose function to the outside world as HTTP endpoints etc._ * _Deploying a JAR file containing such an application context with an isolated classloader, so that you can pack them together in a single JVM._ -* _Compiling strings which are Java function bodies into bytecode, and then turning them into `@Beans` that can be wrapped as above._ * _Adapters for https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-aws[AWS Lambda], https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-azure[Azure], https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp[Google Cloud Functions], https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-openwhisk[Apache OpenWhisk] and possibly other "serverless" service providers._ diff --git a/docs/src/main/asciidoc/sagan-index.adoc b/docs/src/main/asciidoc/sagan-index.adoc index 5e4faf7e1..71e9b2113 100644 --- a/docs/src/main/asciidoc/sagan-index.adoc +++ b/docs/src/main/asciidoc/sagan-index.adoc @@ -18,7 +18,6 @@ Spring Cloud Function features: * _Packaging functions for deployments, specific to the target platform (e.g., Project Riff, AWS Lambda and more)_ * _Adapters to expose function to the outside world as HTTP endpoints etc._ * _Deploying a JAR file containing such an application context with an isolated classloader, so that you can pack them together in a single JVM._ -* _Compiling strings which are Java function bodies into bytecode, and then turning them into `@Beans` that can be wrapped as above._ * _Adapters for https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-aws[AWS Lambda], https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-azure[Microsoft Azure], https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-gcp[Google Cloud Functions], https://github.com/spring-cloud/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-openwhisk[Apache OpenWhisk] and possibly other "serverless" service providers._ Here's a complete, executable, testable Spring Boot application (implementing a simple string manipulation): diff --git a/scripts/function-registry.sh b/scripts/function-registry.sh deleted file mode 100755 index 2655daf11..000000000 --- a/scripts/function-registry.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -java -jar ../spring-cloud-function-compiler/target/spring-cloud-function-compiler-2.0.0.BUILD-SNAPSHOT.jar diff --git a/scripts/registerConsumer.sh b/scripts/registerConsumer.sh deleted file mode 100755 index 0cfbf985b..000000000 --- a/scripts/registerConsumer.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -while getopts ":n:f:t:" opt; do - case $opt in - n) - NAME=$OPTARG - ;; - f) - FUNC=$OPTARG - ;; - t) - TYPE=$OPTARG - ;; - esac -done - -curl -X POST -H "Content-Type: text/plain" -d $FUNC localhost:8080/consumer/$NAME?type=$TYPE diff --git a/scripts/registerFunction.sh b/scripts/registerFunction.sh deleted file mode 100755 index 5638f4db8..000000000 --- a/scripts/registerFunction.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -while getopts ":n:f:i:o:" opt; do - case $opt in - n) - NAME=$OPTARG - ;; - f) - FUNC=$OPTARG - ;; - i) - INTYPE=$OPTARG - ;; - o) - OUTTYPE=$OPTARG - ;; - esac -done - -curl -X POST -H "Content-Type: text/plain" -d $FUNC "localhost:8080/function/$NAME?inputType=$INTYPE&outputType=$OUTTYPE" - diff --git a/scripts/registerSupplier.sh b/scripts/registerSupplier.sh deleted file mode 100755 index df853198f..000000000 --- a/scripts/registerSupplier.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -while getopts ":n:f:t:" opt; do - case $opt in - n) - NAME=$OPTARG - ;; - f) - FUNC=$OPTARG - ;; - t) - TYPE=$OPTARG - ;; - esac -done - -curl -X POST -H "Content-Type: text/plain" -d $FUNC localhost:8080/supplier/$NAME?type=$TYPE diff --git a/scripts/stream.sh b/scripts/stream.sh deleted file mode 100755 index 0d22c78e4..000000000 --- a/scripts/stream.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash - -PREFIX="--spring.cloud.function.import" -DIR="file:///tmp/function-registry" - -tokenize() { - local IFS=, - local TOKENS=($1) - echo ${TOKENS[@]} -} - -DURATION=0 - -while getopts ":i:s:f:c:o:p:d:" opt; do - case $opt in - i) - IN=--spring.cloud.stream.bindings.input.destination=$OPTARG - ;; - s) - FUNC=$OPTARG - TYPE="$PREFIX.$FUNC.type=supplier" - RESOURCE="$PREFIX.$FUNC.location=$DIR/suppliers/$FUNC.fun" - ;; - f) - FUNC=$OPTARG - for i in `tokenize $OPTARG`; do - RESOURCE="$RESOURCE $PREFIX.${i}.location=$DIR/functions/${i}.fun" - TYPE="$TYPE $PREFIX.${i}.type=function" - done - ;; - c) - FUNC=$OPTARG - TYPE="$PREFIX.$FUNC.type=consumer" - RESOURCE="$PREFIX.$FUNC.location=$DIR/consumers/$FUNC.fun" - ;; - o) - OUT=--spring.cloud.stream.bindings.output.destination=$OPTARG - ;; - p) - PORT=$OPTARG - ;; - d) - DURATION=$OPTARG - ;; - esac -done - -java -jar ../spring-cloud-function-samples/function-sample-compiler/target/function-sample-compiler-2.0.0.BUILD-SNAPSHOT.jar\ - --management.security.enabled=false\ - --server.port=$PORT\ - --spring.cloud.function.stream.endpoint=$FUNC\ - --spring.cloud.function.stream.interval=$DURATION\ - $IN\ - $OUT\ - $RESOURCE\ - $TYPE diff --git a/scripts/task.sh b/scripts/task.sh deleted file mode 100755 index cc804d1e2..000000000 --- a/scripts/task.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -while getopts ":s:f:c:" opt; do - case $opt in - s) - SUPP=$OPTARG - ;; - f) - FUNC=$OPTARG - ;; - c) - CONS=$OPTARG - ;; - esac -done - -java -noverify -XX:TieredStopAtLevel=1 -Xss256K -Xms16M -Xmx256M -XX:MaxMetaspaceSize=128M -jar ../spring-cloud-function-task/target/spring-cloud-function-task-2.0.0.BUILD-SNAPSHOT.jar\ - --lambda.supplier=$SUPP --lambda.function=$FUNC --lambda.consumer=$CONS diff --git a/scripts/web.sh b/scripts/web.sh deleted file mode 100755 index 58b3d065c..000000000 --- a/scripts/web.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -while getopts ":s:f:c:p:" opt; do - case $opt in - s) - FUNC=$OPTARG - TYPE=supplier - ;; - f) - FUNC=$OPTARG - TYPE=function - ;; - c) - FUNC=$OPTARG - TYPE=consumer - ;; - p) - PORT=$OPTARG - ;; - esac -done - -java -jar ../spring-cloud-function-samples/function-sample-compiler/target/function-sample-compiler-2.0.0.BUILD-SNAPSHOT.jar\ - --spring.cloud.function.import.$FUNC.type=$TYPE\ - --spring.cloud.function.import.$FUNC.location=file:///tmp/function-registry/$TYPE's'/$FUNC.fun\ - --management.security.enabled=false\ - --server.port=$PORT diff --git a/spring-cloud-function-compiler/.jdk8 b/spring-cloud-function-compiler/.jdk8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/AbstractFunctionCompiler.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/AbstractFunctionCompiler.java deleted file mode 100644 index e9f1179be..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/AbstractFunctionCompiler.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler; - -import java.util.List; -import java.util.regex.Matcher; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.cloud.function.compiler.java.CompilationFailedException; -import org.springframework.cloud.function.compiler.java.CompilationMessage; -import org.springframework.cloud.function.compiler.java.CompilationResult; -import org.springframework.cloud.function.compiler.java.RuntimeJavaCompiler; -import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; - -/** - * @param result type - * @author Andy Clement - * @author Mark Fisher - * @author Oleg Zhurakousky - */ -public abstract class AbstractFunctionCompiler { - - // Newlines in the property are escaped - private static final String NEWLINE_ESCAPE = Matcher.quoteReplacement("\\n"); - - // Individual double-quote characters are represented by two double quotes in the DSL - private static final String DOUBLE_DOUBLE_QUOTE = Matcher.quoteReplacement("\"\""); - - private static Logger logger = LoggerFactory - .getLogger(AbstractFunctionCompiler.class); - - /** - * The user supplied code snippet is inserted into the template and then the result is - * compiled. - */ - // @formatter:off - private static String SOURCE_CODE_TEMPLATE = "package " - + AbstractFunctionCompiler.class.getPackage().getName() + ";\n" - + "import java.util.*;\n" // Helpful to include this - + "import java.time.*;\n" // Helpful to include this - + "import java.util.function.*;\n" - + "import reactor.core.publisher.Flux;\n" - + "public class %s implements CompilationResultFactory<%s> {\n" - + " public %s<%s> getResult() {\n" - + " %s\n" - + " }\n" - + "}\n"; - // @formatter:on - private final ResultType resultType; - - private final String[] defaultResultTypeParameterizations; - - private final RuntimeJavaCompiler compiler = new RuntimeJavaCompiler(); - - AbstractFunctionCompiler(ResultType type, - String... defaultResultTypeParameterizations) { - this.resultType = type; - this.defaultResultTypeParameterizations = defaultResultTypeParameterizations; - } - - private static String decode(String input) { - return input.replaceAll(NEWLINE_ESCAPE, "\n").replaceAll(DOUBLE_DOUBLE_QUOTE, - "\""); - } - - /** - * Produce a factory instance by: - *
    - *
  • Decoding the code String to process any newlines/double-double-quotes - *
  • Insert the code into the source code template for a class - *
  • Compiling the class using the JDK provided Java Compiler - *
  • Loading the compiled class - *
  • Invoking a well known method on the factory class to produce a Consumer, - * Function, or Supplier instance - *
  • Returning that instance. - *
- * @param name - name of the function - * @param code - code of the function - * @param resultTypeParameterizations - result types - * @return a factory instance - */ - public final CompiledFunctionFactory compile(String name, String code, - String... resultTypeParameterizations) { - if (name == null || name.length() == 0) { - throw new IllegalArgumentException("name must not be empty"); - } - logger.info("Initial code property value :'{}'", code); - String[] parameterizedTypes = (!ObjectUtils.isEmpty(resultTypeParameterizations)) - ? resultTypeParameterizations : this.defaultResultTypeParameterizations; - code = decode(code); - if (code.startsWith("\"") && code.endsWith("\"")) { - code = code.substring(1, code.length() - 1); - } - if (!code.startsWith("return ") && !code.endsWith(";")) { - code = String.format("return (%s<%s> & java.io.Serializable) %s;", - this.resultType, - StringUtils.arrayToCommaDelimitedString(parameterizedTypes), code); - } - logger.info("Processed code property value :\n{}\n", code); - String firstLetter = name.substring(0, 1).toUpperCase(); - name = (name.length() > 1) ? firstLetter + name.substring(1) : firstLetter; - String className = String.format("%s.%s%sFactory", - this.getClass().getPackage().getName(), name, this.resultType); - CompilationResult compilationResult = buildAndCompileSourceCode(className, code, - parameterizedTypes); - if (compilationResult.wasSuccessful()) { - CompiledFunctionFactory factory = new CompiledFunctionFactory<>(className, - compilationResult); - return this.postProcessCompiledFunctionFactory(factory); - } - List compilationMessages = compilationResult - .getCompilationMessages(); - throw new CompilationFailedException(compilationMessages); - } - - /** - * Implementing subclasses may override this, e.g. to set the input and/or output - * types. - * @param factory the {@link CompiledFunctionFactory} produced by - * {@link #compile(String, String, String...)} - * @return the post-processed {@link CompiledFunctionFactory} - */ - protected CompiledFunctionFactory postProcessCompiledFunctionFactory( - CompiledFunctionFactory factory) { - return factory; - } - - /** - * Create the source for and then compile and load a class that embodies the supplied - * methodBody. The methodBody is inserted into a class template that returns the - * specified parameterized type. This method can return more than one class if the - * method body includes local class declarations. An example methodBody would be - * return input -> input.buffer(5).map(list->list.get(0));. - * @param className the name of the class - * @param methodBody the source code for a method - * @param parameterizedTypes the array of String representations for the parameterized - * input and/or output types, e.g.: <Flux<Object>> - * @return the list of Classes produced by compiling and then loading the snippet of - * code - */ - private CompilationResult buildAndCompileSourceCode(String className, - String methodBody, String[] parameterizedTypes) { - String sourceCode = makeSourceClassDefinition(className, methodBody, - parameterizedTypes); - return this.compiler.compile(className, sourceCode); - } - - /** - * Make a full source code definition for a class by applying the specified method - * body to the Reactive template. - * @param className the name of the class - * @param methodBody the code to insert into the Reactive source class template - * @param types the parameterized input and/or output types as Strings - * @return a complete Java Class definition - */ - private String makeSourceClassDefinition(String className, String methodBody, - String[] types) { - String shortClassName = className.substring(className.lastIndexOf('.') + 1); - String s = String.format(SOURCE_CODE_TEMPLATE, shortClassName, this.resultType, - this.resultType, StringUtils.arrayToCommaDelimitedString(types), - methodBody); - logger.info("\n" + s); - return s; - } - - enum ResultType { - - Consumer, Function, Supplier - - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/CompilationResultFactory.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/CompilationResultFactory.java deleted file mode 100644 index 1f643b80b..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/CompilationResultFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler; - -/** - * @param result type - * @author Mark Fisher - */ -public interface CompilationResultFactory { - - T getResult(); - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/CompiledFunctionFactory.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/CompiledFunctionFactory.java deleted file mode 100644 index 0083b2fdc..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/CompiledFunctionFactory.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler; - -import java.lang.reflect.Method; -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; - -import org.springframework.cloud.function.compiler.java.CompilationResult; -import org.springframework.util.ReflectionUtils; - -/** - * @param result type - * @author Mark Fisher - */ -public class CompiledFunctionFactory implements CompilationResultFactory { - - private final T result; - - private final byte[] generatedClassBytes; - - private String inputType; - - private String outputType; - - private Method method; - - public CompiledFunctionFactory(String className, - CompilationResult compilationResult) { - List> clazzes = compilationResult.getCompiledClasses(); - T result = null; - Method method = null; - for (Class clazz : clazzes) { - if (clazz.getName().equals(className)) { - try { - @SuppressWarnings("unchecked") - CompilationResultFactory factory = (CompilationResultFactory) clazz - .newInstance(); - result = factory.getResult(); - method = findFactoryMethod(clazz); - } - catch (Exception e) { - throw new IllegalArgumentException( - "Unexpected problem during retrieval of Function from compiled class", - e); - } - } - } - if (result == null) { - throw new IllegalArgumentException("Failed to extract compilation result."); - } - this.result = result; - this.method = method; - this.generatedClassBytes = compilationResult.getClassBytes(className); - } - - private Method findFactoryMethod(Class clazz) { - AtomicReference method = new AtomicReference<>(); - ReflectionUtils.doWithLocalMethods(clazz, m -> { - if (m.getName().equals("getResult") - && m.getReturnType().getName().startsWith("java.util.function")) { - method.set(m); - } - }); - return method.get(); - } - - public T getResult() { - return this.result; - } - - public Method getFactoryMethod() { - return this.method; - } - - public String getInputType() { - return this.inputType; - } - - public void setInputType(String inputType) { - this.inputType = inputType; - } - - public String getOutputType() { - return this.outputType; - } - - public void setOutputType(String outputType) { - this.outputType = outputType; - } - - public byte[] getGeneratedClassBytes() { - return this.generatedClassBytes; - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/ConsumerCompiler.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/ConsumerCompiler.java deleted file mode 100644 index e098f9049..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/ConsumerCompiler.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler; - -import java.util.function.Consumer; - -/** - * @param result type - * @author Mark Fisher - */ -public class ConsumerCompiler extends AbstractFunctionCompiler> { - - private final String inputType; - - public ConsumerCompiler() { - this("Flux"); - } - - public ConsumerCompiler(String inputType) { - super(ResultType.Consumer, inputType); - this.inputType = inputType; - } - - @Override - protected CompiledFunctionFactory> postProcessCompiledFunctionFactory( - CompiledFunctionFactory> factory) { - factory.setInputType(this.inputType); - return factory; - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/FunctionCompiler.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/FunctionCompiler.java deleted file mode 100644 index ad3ce77dd..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/FunctionCompiler.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler; - -import java.util.function.Function; - -/** - * @param function input type - * @param function output type - * @author Mark Fisher - */ -public class FunctionCompiler extends AbstractFunctionCompiler> { - - private final String inputType; - - private final String outputType; - - public FunctionCompiler() { - this("Flux"); - } - - public FunctionCompiler(String type) { - this(type, type); - } - - public FunctionCompiler(String inputType, String outputType) { - super(ResultType.Function, inputType, outputType); - this.inputType = inputType; - this.outputType = outputType; - } - - @Override - protected CompiledFunctionFactory> postProcessCompiledFunctionFactory( - CompiledFunctionFactory> factory) { - factory.setInputType(this.inputType); - factory.setOutputType(this.outputType); - - return factory; - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/SupplierCompiler.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/SupplierCompiler.java deleted file mode 100644 index 57ab191bd..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/SupplierCompiler.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler; - -import java.util.function.Supplier; - -/** - * @param input type - * @author Mark Fisher - */ -public class SupplierCompiler extends AbstractFunctionCompiler> { - - private final String outputType; - - public SupplierCompiler() { - this("Flux"); - } - - public SupplierCompiler(String outputType) { - super(ResultType.Supplier, outputType); - this.outputType = outputType; - } - - @Override - protected CompiledFunctionFactory> postProcessCompiledFunctionFactory( - CompiledFunctionFactory> factory) { - factory.setOutputType(this.outputType); - return factory; - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/app/CompiledFunctionRegistry.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/app/CompiledFunctionRegistry.java deleted file mode 100644 index 3717514d5..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/app/CompiledFunctionRegistry.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.app; - -import java.io.File; -import java.io.IOException; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import reactor.core.publisher.Flux; - -import org.springframework.cloud.function.compiler.AbstractFunctionCompiler; -import org.springframework.cloud.function.compiler.CompiledFunctionFactory; -import org.springframework.cloud.function.compiler.ConsumerCompiler; -import org.springframework.cloud.function.compiler.FunctionCompiler; -import org.springframework.cloud.function.compiler.SupplierCompiler; -import org.springframework.util.Assert; -import org.springframework.util.FileCopyUtils; - -/** - * @author Mark Fisher - * @author Oleg Zhurakousky - */ -public class CompiledFunctionRegistry { - - private static final String SUPPLIER_DIRECTORY = "suppliers"; - - private static final String FUNCTION_DIRECTORY = "functions"; - - private static final String CONSUMER_DIRECTORY = "consumers"; - - private final File supplierDirectory; - - private final File functionDirectory; - - private final File consumerDirectory; - - private final AbstractFunctionCompiler>> supplierCompiler = new SupplierCompiler<>(); - - private final AbstractFunctionCompiler, Flux>> functionCompiler = new FunctionCompiler<>(); - - private final AbstractFunctionCompiler>> consumerCompiler = new ConsumerCompiler<>(); - - public CompiledFunctionRegistry() { - this(new File("/tmp/function-registry")); - } - - public CompiledFunctionRegistry(File directory) { - Assert.notNull(directory, "Directory must not be null"); - if (!directory.exists()) { - directory.mkdirs(); - } - else { - Assert.isTrue(directory.isDirectory(), - String.format("%s is not a directory.", directory.getAbsolutePath())); - } - this.supplierDirectory = new File(directory, SUPPLIER_DIRECTORY); - this.functionDirectory = new File(directory, FUNCTION_DIRECTORY); - this.consumerDirectory = new File(directory, CONSUMER_DIRECTORY); - this.supplierDirectory.mkdir(); - this.functionDirectory.mkdir(); - this.consumerDirectory.mkdir(); - } - - public void registerSupplier(String name, String lambda, String type) { - this.doRegister(this.supplierCompiler, this.supplierDirectory, name, lambda, - type); - } - - public void registerFunction(String name, String lambda, String... types) { - this.doRegister(this.functionCompiler, this.functionDirectory, name, lambda, - types); - } - - public void registerConsumer(String name, String lambda, String type) { - this.doRegister(this.consumerCompiler, this.consumerDirectory, name, lambda, - type); - } - - private void doRegister(AbstractFunctionCompiler compiler, File directory, - String name, String lambda, String... types) { - CompiledFunctionFactory factory = compiler.compile(name, lambda, types); - File file = new File(directory, fileName(name)); - try { - FileCopyUtils.copy(factory.getGeneratedClassBytes(), file); - } - catch (IOException e) { - throw new IllegalArgumentException( - String.format("failed to register '%s'", name), e); - } - } - - private String fileName(String functionName) { - return String.format("%s.%s", functionName, "fun"); - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/app/CompilerApplication.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/app/CompilerApplication.java deleted file mode 100644 index 1997ad6d2..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/app/CompilerApplication.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.app; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -// @checkstyle:off -@SpringBootApplication -public class CompilerApplication { - - public static void main(String[] args) { - SpringApplication.run(CompilerApplication.class, args); - } - -} -// @checkstyle:on diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/app/CompilerController.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/app/CompilerController.java deleted file mode 100644 index ca949d66f..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/app/CompilerController.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.app; - -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author Mark Fisher - */ -@RestController -public class CompilerController { - - private final CompiledFunctionRegistry registry = new CompiledFunctionRegistry(); - - @PostMapping(path = "/supplier/{name}") - public void registerSupplier(@PathVariable String name, @RequestBody String lambda, - @RequestParam(defaultValue = "Flux") String type) { - this.registry.registerSupplier(name, lambda, type); - } - - @PostMapping(path = "/function/{name}") - public void registerFunction(@PathVariable String name, @RequestBody String lambda, - @RequestParam(defaultValue = "Flux") String inputType, - @RequestParam(defaultValue = "Flux") String outputType) { - this.registry.registerFunction(name, lambda, inputType, outputType); - } - - @PostMapping(path = "/consumer/{name}") - public void registerConsumer(@PathVariable String name, @RequestBody String lambda, - @RequestParam(defaultValue = "Flux") String type) { - this.registry.registerConsumer(name, lambda, type); - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/config/FunctionProxyApplicationListener.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/config/FunctionProxyApplicationListener.java deleted file mode 100644 index 1d93c74b0..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/config/FunctionProxyApplicationListener.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.config; - -import java.util.HashMap; -import java.util.Map; - -import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.factory.config.ConstructorArgumentValues; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.boot.context.event.ApplicationPreparedEvent; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.bind.Bindable; -import org.springframework.boot.context.properties.bind.Binder; -import org.springframework.cloud.function.compiler.ConsumerCompiler; -import org.springframework.cloud.function.compiler.FunctionCompiler; -import org.springframework.cloud.function.compiler.SupplierCompiler; -import org.springframework.cloud.function.compiler.proxy.ByteCodeLoadingConsumer; -import org.springframework.cloud.function.compiler.proxy.ByteCodeLoadingFunction; -import org.springframework.cloud.function.compiler.proxy.ByteCodeLoadingSupplier; -import org.springframework.cloud.function.compiler.proxy.LambdaCompilingConsumer; -import org.springframework.cloud.function.compiler.proxy.LambdaCompilingFunction; -import org.springframework.cloud.function.compiler.proxy.LambdaCompilingSupplier; -import org.springframework.context.ApplicationListener; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.core.io.Resource; -import org.springframework.util.Assert; - -/** - * @author Mark Fisher - */ -@ConfigurationProperties("spring.cloud.function") -public class FunctionProxyApplicationListener - implements ApplicationListener { - - private final SupplierCompiler supplierCompiler = new SupplierCompiler<>(); - - private final FunctionCompiler functionCompiler = new FunctionCompiler<>(); - - private final ConsumerCompiler consumerCompiler = new ConsumerCompiler<>(); - - /** - * Configuration for function bodies, which will be compiled. The key in the map is - * the function name and the value is a map containing a key "lambda" which is the - * body to compile, and optionally a "type" (defaults to "function"). Can also contain - * "inputType" and "outputType" in case it is ambiguous. - */ - private final Map compile = new HashMap<>(); - - /** - * Configuration for a set of files containing function bodies, which will be imported - * and compiled. The key in the map is the function name and the value is another map, - * containing a "location" of the file to compile and (optionally) a "type" (defaults - * to "function"). - */ - private final Map imports = new HashMap<>(); - - public Map getCompile() { - return this.compile; - } - - public Map getImports() { - return this.imports; - } - - @Override - public void onApplicationEvent(ApplicationPreparedEvent event) { - ConfigurableApplicationContext context = event.getApplicationContext(); - DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context - .getBeanFactory(); - bind(context, beanFactory); - for (Map.Entry entry : this.compile.entrySet()) { - String name = entry.getKey(); - @SuppressWarnings("unchecked") - Map properties = (Map) entry.getValue(); - String type = (properties.get("type") != null) ? properties.get("type") - : "function"; - String lambda = properties.get("lambda"); - Assert.notNull(lambda, () -> String.format( - "The 'lambda' property is required for compiling Function: %s", - name)); - String inputType = properties.get("inputType"); - String outputType = properties.get("outputType"); - registerLambdaCompilingProxy(name, type, inputType, outputType, lambda, - beanFactory); - } - for (Map.Entry entry : this.imports.entrySet()) { - String name = entry.getKey(); - @SuppressWarnings("unchecked") - Map properties = (Map) entry.getValue(); - String type = (properties.get("type") != null) ? properties.get("type") - : "function"; - String location = properties.get("location"); - Assert.notNull(location, String.format( - "The 'location' property is required for importing Function: %s", - name)); - registerByteCodeLoadingProxy(name, type, context.getResource(location), - beanFactory); - } - } - - private void bind(ConfigurableApplicationContext application, - DefaultListableBeanFactory context) { - Binder.get(application.getEnvironment()).bind("spring.cloud.function", - Bindable.ofInstance(this)); - } - - private void registerByteCodeLoadingProxy(String name, String type, Resource resource, - DefaultListableBeanFactory beanFactory) { - Class proxyClass = null; - if ("supplier".equals(type.toLowerCase())) { - proxyClass = ByteCodeLoadingSupplier.class; - } - else if ("consumer".equals(type.toLowerCase())) { - proxyClass = ByteCodeLoadingConsumer.class; - } - else { - proxyClass = ByteCodeLoadingFunction.class; - } - RootBeanDefinition beanDefinition = new RootBeanDefinition(proxyClass); - ConstructorArgumentValues args = new ConstructorArgumentValues(); - args.addGenericArgumentValue(resource); - beanDefinition.setConstructorArgumentValues(args); - beanFactory.registerBeanDefinition(name, beanDefinition); - } - - private void registerLambdaCompilingProxy(String name, String type, String inputType, - String outputType, String lambda, DefaultListableBeanFactory beanFactory) { - Resource resource = new ByteArrayResource(lambda.getBytes()); - ConstructorArgumentValues args = new ConstructorArgumentValues(); - MutablePropertyValues props = new MutablePropertyValues(); - args.addGenericArgumentValue(resource); - Class proxyClass = null; - if ("supplier".equals(type.toLowerCase())) { - proxyClass = LambdaCompilingSupplier.class; - args.addGenericArgumentValue(this.supplierCompiler); - if (outputType != null) { - props.add("typeParameterizations", outputType); - } - } - else if ("consumer".equals(type.toLowerCase())) { - proxyClass = LambdaCompilingConsumer.class; - args.addGenericArgumentValue(this.consumerCompiler); - if (inputType != null) { - props.add("typeParameterizations", inputType); - } - } - else { - proxyClass = LambdaCompilingFunction.class; - args.addGenericArgumentValue(this.functionCompiler); - if ((inputType == null && outputType != null) - || (outputType == null && inputType != null)) { - throw new IllegalArgumentException( - "if either input or output type is set, the other is also required"); - } - if (inputType != null) { - props.add("typeParameterizations", - new String[] { inputType, outputType }); - } - } - RootBeanDefinition beanDefinition = new RootBeanDefinition(proxyClass); - beanDefinition.setConstructorArgumentValues(args); - beanDefinition.setPropertyValues(props); - beanFactory.registerBeanDefinition(name, beanDefinition); - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CloseableFilterableJavaFileObjectIterable.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CloseableFilterableJavaFileObjectIterable.java deleted file mode 100644 index 80605e030..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CloseableFilterableJavaFileObjectIterable.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.io.File; - -import javax.tools.JavaFileObject; - -import org.springframework.cloud.function.compiler.java.MemoryBasedJavaFileManager.CompilationInfoCache; - -/** - * Common superclass for iterables that need to handle closing when finished with and that - * need to handle possible constraints on the values that are iterated over. - * - * @author Andy Clement - */ -public abstract class CloseableFilterableJavaFileObjectIterable - implements Iterable { - - // private final static Logger logger = - // LoggerFactory.getLogger(CloseableFilterableJavaFileObjectIterable.class); - - private final static boolean BOOT_PACKAGING_AWARE = true; - - private final static String BOOT_PACKAGING_PREFIX_FOR_CLASSES = "BOOT-INF/classes/"; - - // If set specifies the package the iterator consumer is interested in. Only - // return results in this package. Will have a trailing separator to speed - // matching. '/' on its own represents the default package - protected String packageNameFilter; - - // Indicates whether the consumer of the iterator wants to see classes - // that are in subpackages of those matching the filter. - protected boolean includeSubpackages; - - protected CompilationInfoCache compilationInfoCache; - - public CloseableFilterableJavaFileObjectIterable( - CompilationInfoCache compilationInfoCache, String packageNameFilter, - boolean includeSubpackages) { - if (packageNameFilter != null && packageNameFilter.contains(File.separator)) { - throw new IllegalArgumentException( - "Package name filters should use dots to separate components: " - + packageNameFilter); - } - this.compilationInfoCache = compilationInfoCache; - // Normalize filter to forward slashes - this.packageNameFilter = packageNameFilter == null ? null - : packageNameFilter.replace('.', '/') + '/'; - this.includeSubpackages = includeSubpackages; - } - - /** - * Used by subclasses to check values against any specified constraints. - * @param name the name to check against the criteria - * @return true if the name is a valid iterator result based on the specified criteria - */ - protected boolean accept(String name) { - // logger.debug("checking {} against constraints packageNameFilter={} - // includeSubpackages={}",name,packageNameFilter,includeSubpackages); - if (!name.endsWith(".class")) { - return false; - } - if (this.packageNameFilter == null) { - return true; - } - boolean accept; - // Normalize to forward slashes (some jars are producing paths with forward - // slashes, some with backward slashes) - name = name.replace('\\', '/'); - if (this.packageNameFilter.length() == 1 && this.packageNameFilter.equals("/")) { - // This is the 'default package' filter representation - if (name.indexOf('/') == -1) { - accept = true; - } - else if (BOOT_PACKAGING_AWARE) { - accept = name.startsWith(BOOT_PACKAGING_PREFIX_FOR_CLASSES) && name - .indexOf('/', BOOT_PACKAGING_PREFIX_FOR_CLASSES.length()) == -1; - } - return accept; - } - if (this.includeSubpackages) { - accept = name.startsWith(this.packageNameFilter); - if (!accept && BOOT_PACKAGING_AWARE) { - accept = name.startsWith(BOOT_PACKAGING_PREFIX_FOR_CLASSES) - && name.indexOf( - this.packageNameFilter) == BOOT_PACKAGING_PREFIX_FOR_CLASSES - .length(); - } - } - else { - accept = name.startsWith(this.packageNameFilter) - && name.indexOf("/", this.packageNameFilter.length()) == -1; - if (!accept && BOOT_PACKAGING_AWARE) { - accept = name.startsWith(BOOT_PACKAGING_PREFIX_FOR_CLASSES) - && name.indexOf( - this.packageNameFilter) == BOOT_PACKAGING_PREFIX_FOR_CLASSES - .length() - && name.indexOf("/", BOOT_PACKAGING_PREFIX_FOR_CLASSES.length() - + this.packageNameFilter.length()) == -1; - } - } - return accept; - } - - abstract void close(); - - abstract void reset(); - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompilationFailedException.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompilationFailedException.java deleted file mode 100644 index 503e7a0c6..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompilationFailedException.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.util.List; - -/** - * @author Mark Fisher - */ -@SuppressWarnings("serial") -public class CompilationFailedException extends RuntimeException { - - public CompilationFailedException(List messages) { - super(consolidateMessages(messages)); - } - - private static String consolidateMessages(List messages) { - if (messages == null || messages.isEmpty()) { - return ""; - } - StringBuilder sb = new StringBuilder(); - for (CompilationMessage message : messages) { - sb.append(message.toString()); - } - return sb.toString(); - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompilationMessage.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompilationMessage.java deleted file mode 100644 index bd3bcc933..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompilationMessage.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -/** - * Encapsulate information produced during compilation. A message may be an error or - * something less serious (warning/informational). The toString() method will - * produce a formatted error include source context indicating the precise location of the - * problem. - * - * @author Andy Clement - */ -public class CompilationMessage { - - private Kind kind; - - private String message; - - private String sourceCode; - - private int startPosition; - - private int endPosition; - - public CompilationMessage(Kind kind, String message, String sourceCode, - int startPosition, int endPosition) { - this.kind = kind; - this.message = message; - this.sourceCode = sourceCode; - this.startPosition = startPosition; - this.endPosition = endPosition; - } - - /** - * @return the type of message - */ - public Kind getKind() { - return this.kind; - } - - /** - * @return the message text - */ - public String getMessage() { - return this.message; - } - - /** - * @return the source code for the file associated with the message - */ - public String getSourceCode() { - return this.sourceCode; - } - - /** - * @return offset from start of source file where the error begins - */ - public int getStartPosition() { - return this.startPosition; - } - - /** - * @return offset from start of source file where the error ends - */ - public int getEndPosition() { - return this.endPosition; - } - - public String toString() { - StringBuilder s = new StringBuilder(); - s.append("==========\n"); - if (this.sourceCode != null) { // Cannot include source context if no source - // available - int[] lineStartEnd = getLineStartEnd(this.startPosition); - s.append(this.sourceCode.substring(lineStartEnd[0], lineStartEnd[1])) - .append("\n"); - int col = lineStartEnd[0]; - // When inserting the whitespace, ensure tabs in the source line are respected - while ((col) < this.startPosition) { - s.append(this.sourceCode.charAt(col++) == '\t' ? "\t" : " "); - } - // Want at least one ^ - s.append("^"); - col++; - while ((col++) < this.endPosition) { - s.append("^"); - } - s.append("\n"); - } - s.append(this.kind).append(":").append(this.message).append("\n"); - s.append("==========\n"); - return s.toString(); - } - - /** - * For a given position in the source code this method returns a pair of int that - * indicate the start and end of the line within the source code that contain the - * position. - * @param searchPos the position of interest in the source code - * @return an int array of length 2 containing the start and end positions of the line - */ - private int[] getLineStartEnd(int searchPos) { - int previousPos = -1; - int pos = 0; - do { - pos = this.sourceCode.indexOf('\n', previousPos + 1); - if (searchPos < pos) { - return new int[] { previousPos + 1, pos }; - } - previousPos = pos; - } - while (pos != -1); - return new int[] { previousPos + 1, this.sourceCode.length() }; - } - - enum Kind { - - ERROR, OTHER - - } - // TODO test coverage for first line/last line situations - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompilationOutputCollector.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompilationOutputCollector.java deleted file mode 100644 index 2dfe424b6..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompilationOutputCollector.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.util.ArrayList; -import java.util.List; - -import javax.tools.FileObject; -import javax.tools.JavaFileManager.Location; -import javax.tools.JavaFileObject.Kind; - -/** - * During compilation instances of this class will collect up the output files from the - * compilation process. Any kind of file is collected upon but access is only currently - * provided to retrieve classes produced during compilation. Annotation processors that - * run may create other kinds of artifact. - * - * @author Andy Clement - */ -public class CompilationOutputCollector { - - private List outputFiles = new ArrayList<>(); - - /** - * Retrieve compiled classes that have been collected since this collector was built. - * Due to annotation processing it is possible other source files or metadata files - * may be produced during compilation - those are not included in the returned list. - * @return list of compiled classes - */ - public List getCompiledClasses() { - List compiledClassDefinitions = new ArrayList<>(); - for (InMemoryJavaFileObject outputFile : this.outputFiles) { - if (outputFile.getKind() == Kind.CLASS) { - CompiledClassDefinition compiledClassDefinition = new CompiledClassDefinition( - outputFile.getName(), outputFile.getBytes()); - compiledClassDefinitions.add(compiledClassDefinition); - } - } - return compiledClassDefinitions; - } - - public InMemoryJavaFileObject getJavaFileForOutput(Location location, - String className, Kind kind, FileObject sibling) { - InMemoryJavaFileObject jfo = InMemoryJavaFileObject.getJavaFileObject(location, - className, kind, sibling); - this.outputFiles.add(jfo); - return jfo; - } - - public InMemoryJavaFileObject getFileForOutput(Location location, String packageName, - String relativeName, FileObject sibling) { - InMemoryJavaFileObject ojfo = InMemoryJavaFileObject.getFileObject(location, - packageName, relativeName, sibling); - this.outputFiles.add(ojfo); - return ojfo; - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompilationResult.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompilationResult.java deleted file mode 100644 index 373ecb80c..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompilationResult.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Holder for the results of compilation. If compilation was successful the set of classes - * that resulted from compilation will be available. If compilation was not successful the - * error messages should provide information about why. Note that compilation may succeed - * and yet there will still be informational or warning messages collected. - * - * @author Andy Clement - * @author Mark Fisher - */ -public class CompilationResult { - - List compilationMessages = new ArrayList<>(); - - List> compiledClasses = new ArrayList<>(); - - private boolean successfulCompilation; - - private Map classBytes = new HashMap<>(); - - private List resolvedAdditionalDependencies = new ArrayList<>(); - - public CompilationResult(boolean successfulCompilation) { - this.successfulCompilation = successfulCompilation; - } - - public void addClassBytes(String name, byte[] bytes) { - this.classBytes.put(name, bytes); - } - - public List getResolvedAdditionalDependencies() { - return this.resolvedAdditionalDependencies; - } - - public void setResolvedAdditionalDependencies( - List resolvedAdditionalDependencies) { - this.resolvedAdditionalDependencies = resolvedAdditionalDependencies; - } - - public byte[] getClassBytes(String classname) { - return this.classBytes.get(classname); - } - - public boolean wasSuccessful() { - return this.successfulCompilation; - } - - public List> getCompiledClasses() { - return this.compiledClasses; - } - - public void setCompiledClasses(List> compiledClasses) { - this.compiledClasses = compiledClasses; - } - - public List getCompilationMessages() { - return Collections.unmodifiableList(this.compilationMessages); - } - - public void recordCompilationMessage(CompilationMessage message) { - this.compilationMessages.add(message); - } - - public void recordCompilationMessages(List messages) { - this.compilationMessages.addAll(messages); - } - - public String toString() { - StringBuilder s = new StringBuilder(); - s.append("Compilation result: #classes=" + this.compiledClasses.size() - + " #messages=" + this.compilationMessages.size() + "\n"); - s.append("Compiled classes:\n").append(this.compiledClasses).append("\n"); - s.append("Compilation messages:\n").append(this.compilationMessages).append("\n"); - return s.toString(); - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompiledClassDefinition.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompiledClassDefinition.java deleted file mode 100644 index 9502f5ff9..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompiledClassDefinition.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -/** - * Encapsulates a name with the bytes for its class definition. - * - * @author Andy Clement - */ -public class CompiledClassDefinition { - - private byte[] bytes; - - private String filename; - - private String classname; - - public CompiledClassDefinition(String filename, byte[] bytes) { - this.filename = filename; - this.bytes = bytes; - this.classname = filename; - if (this.classname.startsWith("/")) { - this.classname = this.classname.substring(1); - } - this.classname = this.classname.replace('/', '.').substring(0, - this.classname.length() - 6); // strip - // off - // .class - } - - public String getName() { - return this.filename; - } - - public byte[] getBytes() { - return this.bytes; - } - - @Override - public String toString() { - return "CompiledClassDefinition(name=" + getName() + ",#bytes=" - + getBytes().length + ")"; - } - - public String getClassName() { - return this.classname; - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompositeProxySelector.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompositeProxySelector.java deleted file mode 100644 index 0e3cc7f4d..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/CompositeProxySelector.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.aether.repository.Proxy; -import org.eclipse.aether.repository.ProxySelector; -import org.eclipse.aether.repository.RemoteRepository; - -/** - * Composite {@link ProxySelector}. - * - * @author Dave Syer - */ -public class CompositeProxySelector implements ProxySelector { - - private List selectors = new ArrayList(); - - public CompositeProxySelector(List selectors) { - this.selectors = selectors; - } - - @Override - public Proxy getProxy(RemoteRepository repository) { - for (ProxySelector selector : this.selectors) { - Proxy proxy = selector.getProxy(repository); - if (proxy != null) { - return proxy; - } - } - return null; - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/DependencyResolver.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/DependencyResolver.java deleted file mode 100644 index a7ee52c50..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/DependencyResolver.java +++ /dev/null @@ -1,485 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Properties; -import java.util.Set; - -import javax.inject.Singleton; - -import com.google.inject.AbstractModule; -import com.google.inject.Provides; -import com.google.inject.name.Named; -import com.google.inject.name.Names; -import org.apache.maven.artifact.repository.ArtifactRepository; -import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy; -import org.apache.maven.artifact.repository.MavenArtifactRepository; -import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout; -import org.apache.maven.model.Model; -import org.apache.maven.model.io.DefaultModelReader; -import org.apache.maven.model.io.ModelReader; -import org.apache.maven.model.locator.DefaultModelLocator; -import org.apache.maven.model.locator.ModelLocator; -import org.apache.maven.model.validation.DefaultModelValidator; -import org.apache.maven.model.validation.ModelValidator; -import org.apache.maven.project.DefaultProjectBuildingRequest; -import org.apache.maven.project.DependencyResolutionResult; -import org.apache.maven.project.ProjectBuilder; -import org.apache.maven.project.ProjectBuildingException; -import org.apache.maven.project.ProjectBuildingRequest; -import org.apache.maven.project.ProjectBuildingRequest.RepositoryMerging; -import org.apache.maven.project.ProjectBuildingResult; -import org.apache.maven.repository.internal.DefaultArtifactDescriptorReader; -import org.apache.maven.repository.internal.DefaultVersionRangeResolver; -import org.apache.maven.repository.internal.DefaultVersionResolver; -import org.apache.maven.repository.internal.MavenRepositorySystemUtils; -import org.apache.maven.repository.internal.SnapshotMetadataGeneratorFactory; -import org.apache.maven.repository.internal.VersionsMetadataGeneratorFactory; -import org.apache.maven.settings.Profile; -import org.apache.maven.settings.Repository; -import org.codehaus.plexus.ContainerConfiguration; -import org.codehaus.plexus.DefaultContainerConfiguration; -import org.codehaus.plexus.DefaultPlexusContainer; -import org.codehaus.plexus.MutablePlexusContainer; -import org.codehaus.plexus.PlexusConstants; -import org.codehaus.plexus.PlexusContainer; -import org.codehaus.plexus.classworlds.ClassWorld; -import org.eclipse.aether.DefaultRepositorySystemSession; -import org.eclipse.aether.RepositorySystem; -import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory; -import org.eclipse.aether.graph.Dependency; -import org.eclipse.aether.impl.ArtifactDescriptorReader; -import org.eclipse.aether.impl.MetadataGeneratorFactory; -import org.eclipse.aether.impl.VersionRangeResolver; -import org.eclipse.aether.impl.VersionResolver; -import org.eclipse.aether.impl.guice.AetherModule; -import org.eclipse.aether.repository.LocalRepository; -import org.eclipse.aether.repository.NoLocalRepositoryManagerException; -import org.eclipse.aether.repository.ProxySelector; -import org.eclipse.aether.repository.RemoteRepository; -import org.eclipse.aether.repository.RepositoryPolicy; -import org.eclipse.aether.resolution.ArtifactRequest; -import org.eclipse.aether.resolution.ArtifactResult; -import org.eclipse.aether.spi.connector.RepositoryConnectorFactory; -import org.eclipse.aether.spi.connector.transport.TransporterFactory; -import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory; -import org.eclipse.aether.transport.file.FileTransporterFactory; -import org.eclipse.aether.transport.http.HttpTransporterFactory; -import org.eclipse.aether.util.repository.JreProxySelector; -import org.eclipse.sisu.inject.DefaultBeanLocator; -import org.eclipse.sisu.plexus.ClassRealmManager; - -import org.springframework.core.io.Resource; -import org.springframework.util.StringUtils; - -/** - * Dependency resolver utility class. - * - * @author Andy Clement - */ -public final class DependencyResolver { - - private static DependencyResolver instance = new DependencyResolver(); - - private static Properties globals; - - private final Object lock = new Object(); - - private LocalRepositoryManagerFactory localRepositoryManagerFactory; - - private PlexusContainer container; - - private ProjectBuilder projectBuilder; - - private RepositorySystem repositorySystem; - - private MavenSettings settings; - - private DependencyResolver() { - } - - public static DependencyResolver instance() { - return instance; - } - - public static void close() { - instance = new DependencyResolver(); - } - - static Properties getGlobals() { - return globals; - } - - private void initialize() { - if (this.container == null) { - synchronized (this.lock) { - if (this.container == null) { - ClassWorld classWorld = new ClassWorld("plexus.core", - Thread.currentThread().getContextClassLoader()); - ContainerConfiguration config = new DefaultContainerConfiguration() - .setClassWorld(classWorld) - .setRealm(classWorld.getClassRealm("plexus.core")) - .setClassPathScanning(PlexusConstants.SCANNING_INDEX) - .setAutoWiring(true).setName("maven"); - PlexusContainer container; - try { - container = new DefaultPlexusContainer(config, new AetherModule(), - new DependencyResolutionModule()); - this.localRepositoryManagerFactory = container - .lookup(LocalRepositoryManagerFactory.class); - container.addComponent( - new ClassRealmManager((MutablePlexusContainer) container, - new DefaultBeanLocator()), - ClassRealmManager.class.getName()); - this.projectBuilder = container.lookup(ProjectBuilder.class); - this.repositorySystem = container.lookup(RepositorySystem.class); - } - catch (Exception e) { - throw new IllegalStateException("Cannot create container", e); - } - this.container = container; - this.settings = new MavenSettingsReader().readSettings(); - } - } - } - } - - public List dependencies(Resource resource) { - return dependencies(resource, new Properties()); - } - - public List dependencies(final Resource resource, - final Properties properties) { - initialize(); - try { - ProjectBuildingRequest request = getProjectBuildingRequest(properties); - request.setResolveDependencies(true); - synchronized (DependencyResolver.class) { - ProjectBuildingResult result = this.projectBuilder - .build(new PropertiesModelSource(properties, resource), request); - DependencyResolver.globals = null; - DependencyResolutionResult dependencies = result - .getDependencyResolutionResult(); - if (!dependencies.getUnresolvedDependencies().isEmpty()) { - StringBuilder builder = new StringBuilder(); - for (Dependency dependency : dependencies - .getUnresolvedDependencies()) { - List errors = dependencies - .getResolutionErrors(dependency); - for (Exception exception : errors) { - if (builder.length() > 0) { - builder.append("\n"); - } - builder.append(exception.getMessage()); - } - } - throw new RuntimeException(builder.toString()); - } - return runtime(dependencies.getDependencies()); - } - } - catch (ProjectBuildingException | NoLocalRepositoryManagerException e) { - throw new IllegalStateException("Cannot build model", e); - } - } - - public File resolve(Dependency dependency) { - initialize(); - return collectNonTransitive(Arrays.asList(dependency)).iterator().next() - .getArtifact().getFile(); - } - - private List runtime(List dependencies) { - List list = new ArrayList<>(); - for (Dependency dependency : dependencies) { - if (!"test".equals(dependency.getScope()) - && !"provided".equals(dependency.getScope())) { - list.add(dependency); - } - } - return list; - } - - private ProjectBuildingRequest getProjectBuildingRequest(Properties properties) - throws NoLocalRepositoryManagerException { - DefaultProjectBuildingRequest projectBuildingRequest = new DefaultProjectBuildingRequest(); - DefaultRepositorySystemSession session = createSession(properties); - projectBuildingRequest.setRepositoryMerging(RepositoryMerging.REQUEST_DOMINANT); - projectBuildingRequest.setRemoteRepositories(mavenRepositories(properties)); - projectBuildingRequest.getRemoteRepositories() - .addAll(mavenRepositories(this.settings)); - projectBuildingRequest.setRepositorySession(session); - projectBuildingRequest.setProcessPlugins(false); - projectBuildingRequest.setBuildStartTime(new Date()); - projectBuildingRequest.setUserProperties(properties); - projectBuildingRequest.setSystemProperties(System.getProperties()); - return projectBuildingRequest; - } - - private Collection mavenRepositories( - MavenSettings settings) { - List list = new ArrayList<>(); - for (Profile profile : settings.getActiveProfiles()) { - for (Repository repository : profile.getRepositories()) { - addRepositoryIfMissing(list, repository.getId(), repository.getUrl(), - repository.getReleases() != null - ? repository.getReleases().isEnabled() : true, - repository.getSnapshots() != null - ? repository.getSnapshots().isEnabled() : false); - } - } - return list; - } - - private List mavenRepositories(Properties properties) { - List list = new ArrayList<>(); - addRepositoryIfMissing(list, "spring-snapshots", - "https://repo.spring.io/libs-snapshot", true, true); - addRepositoryIfMissing(list, "central", "https://repo1.maven.org/maven2", true, - false); - return list; - } - - private List aetherRepositories(Properties properties) { - List list = new ArrayList<>(); - for (ArtifactRepository input : mavenRepositories(properties)) { - list.add(remote(input)); - } - return list; - } - - private RemoteRepository remote(ArtifactRepository input) { - return new RemoteRepository.Builder(input.getId(), input.getLayout().getId(), - input.getUrl()).setSnapshotPolicy(policy(input.getSnapshots())) - .setReleasePolicy(policy(input.getReleases())).build(); - } - - private RepositoryPolicy policy(ArtifactRepositoryPolicy input) { - RepositoryPolicy policy = new RepositoryPolicy(input.isEnabled(), - RepositoryPolicy.UPDATE_POLICY_DAILY, - RepositoryPolicy.CHECKSUM_POLICY_WARN); - return policy; - } - - private void addRepositoryIfMissing(List list, String id, - String url, boolean releases, boolean snapshots) { - for (ArtifactRepository repo : list) { - if (url.equals(repo.getUrl())) { - return; - } - if (id.equals(repo.getId())) { - return; - } - } - list.add(repo(id, url, releases, snapshots)); - } - - private ArtifactRepository repo(String id, String url, boolean releases, - boolean snapshots) { - MavenArtifactRepository repository = new MavenArtifactRepository(); - repository.setLayout(new DefaultRepositoryLayout()); - repository.setId(id); - repository.setUrl(url); - ArtifactRepositoryPolicy enabled = new ArtifactRepositoryPolicy(); - enabled.setEnabled(true); - ArtifactRepositoryPolicy disabled = new ArtifactRepositoryPolicy(); - disabled.setEnabled(false); - repository.setReleaseUpdatePolicy(releases ? enabled : disabled); - repository.setSnapshotUpdatePolicy(snapshots ? enabled : disabled); - return repository; - } - - private DefaultRepositorySystemSession createSession(Properties properties) - throws NoLocalRepositoryManagerException { - DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession(); - LocalRepository repository = localRepository(properties); - session.setLocalRepositoryManager( - this.localRepositoryManagerFactory.newInstance(session, repository)); - applySettings(session); - ProxySelector existing = session.getProxySelector(); - if (existing == null || !(existing instanceof CompositeProxySelector)) { - JreProxySelector fallback = new JreProxySelector(); - ProxySelector selector = existing == null ? fallback - : new CompositeProxySelector(Arrays.asList(existing, fallback)); - session.setProxySelector(selector); - } - return session; - } - - private void applySettings(DefaultRepositorySystemSession session) { - MavenSettingsReader.applySettings(this.settings, session); - } - - private LocalRepository localRepository(Properties properties) { - return new LocalRepository(getM2RepoDirectory()); - } - - public Model readModel(Resource resource) { - return readModel(resource, new Properties()); - } - - public Model readModel(final Resource resource, final Properties properties) { - initialize(); - try { - ProjectBuildingRequest request = getProjectBuildingRequest(properties); - request.setResolveDependencies(false); - ProjectBuildingResult result = this.projectBuilder - .build(new PropertiesModelSource(properties, resource), request); - return result.getProject().getModel(); - } - catch (Exception e) { - throw new IllegalStateException("Failed to build model from effective pom", - e); - } - } - - private File getM2RepoDirectory() { - return new File(getDefaultM2HomeDirectory(), "repository"); - } - - private File getDefaultM2HomeDirectory() { - String mavenRoot = System.getProperty("maven.home"); - if (StringUtils.hasLength(mavenRoot)) { - return new File(mavenRoot); - } - return new File(System.getProperty("user.home"), ".m2"); - } - - private List collectNonTransitive(List dependencies) { - try { - List artifactRequests = getArtifactRequests(dependencies); - List result = this.repositorySystem - .resolveArtifacts(createSession(new Properties()), artifactRequests); - return result; - } - catch (Exception ex) { - throw new IllegalStateException(ex); - } - } - - private List getArtifactRequests(List dependencies) { - List list = new ArrayList<>(); - for (Dependency dependency : dependencies) { - ArtifactRequest request = new ArtifactRequest(dependency.getArtifact(), null, - null); - request.setRepositories(aetherRepositories(new Properties())); - list.add(request); - } - return list; - } - - @SuppressWarnings("deprecation") - private static final class PropertiesModelSource - implements org.apache.maven.model.building.ModelSource { - - private final Properties properties; - - private final Resource resource; - - private PropertiesModelSource(Properties properties, Resource resource) { - this.properties = properties; - this.resource = resource; - } - - @Override - public InputStream getInputStream() throws IOException { - DependencyResolver.globals = this.properties; - return new BufferedInputStream(this.resource.getInputStream()) { - @Override - public void close() throws IOException { - DependencyResolver.globals = null; - super.close(); - } - }; - } - - @Override - public String getLocation() { - return this.resource.getDescription(); - } - - } - -} - -class DependencyResolutionModule extends AbstractModule { - - @Override - protected void configure() { - bind(ModelLocator.class).to(DefaultModelLocator.class).in(Singleton.class); - bind(ModelReader.class).to(DefaultModelReader.class).in(Singleton.class); - bind(ModelValidator.class).to(DefaultModelValidator.class).in(Singleton.class); - bind(RepositoryConnectorFactory.class).to(BasicRepositoryConnectorFactory.class) - .in(Singleton.class); - bind(ArtifactDescriptorReader.class) // - .to(DefaultArtifactDescriptorReader.class).in(Singleton.class); - bind(VersionResolver.class) // - .to(DefaultVersionResolver.class).in(Singleton.class); - bind(VersionRangeResolver.class) // - .to(DefaultVersionRangeResolver.class).in(Singleton.class); - bind(MetadataGeneratorFactory.class).annotatedWith(Names.named("snapshot")) // - .to(SnapshotMetadataGeneratorFactory.class).in(Singleton.class); - bind(MetadataGeneratorFactory.class).annotatedWith(Names.named("versions")) // - .to(VersionsMetadataGeneratorFactory.class).in(Singleton.class); - bind(TransporterFactory.class).annotatedWith(Names.named("http")) - .to(HttpTransporterFactory.class).in(Singleton.class); - bind(TransporterFactory.class).annotatedWith(Names.named("file")) - .to(FileTransporterFactory.class).in(Singleton.class); - } - - @Provides - @Singleton - Set provideMetadataGeneratorFactories( - @Named("snapshot") MetadataGeneratorFactory snapshot, - @Named("versions") MetadataGeneratorFactory versions) { - Set factories = new HashSet<>(); - factories.add(snapshot); - factories.add(versions); - return Collections.unmodifiableSet(factories); - } - - @Provides - @Singleton - Set provideRepositoryConnectorFactories( - RepositoryConnectorFactory factory) { - return Collections.singleton(factory); - } - - @Provides - @Singleton - Set provideTransporterFactories( - @Named("file") TransporterFactory file, - @Named("http") TransporterFactory http) { - // Order is decided elsewhere (by priority) - Set factories = new HashSet(); - factories.add(file); - factories.add(http); - return Collections.unmodifiableSet(factories); - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/DirEntryJavaFileObject.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/DirEntryJavaFileObject.java deleted file mode 100644 index c4557ddff..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/DirEntryJavaFileObject.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.io.Writer; -import java.net.URI; - -import javax.lang.model.element.Modifier; -import javax.lang.model.element.NestingKind; -import javax.tools.JavaFileObject; - -/** - * A JavaFileObject that represents a file in a directory. - * - * @author Andy Clement - */ -public class DirEntryJavaFileObject implements JavaFileObject { - - private File file; - - private File basedir; - - public DirEntryJavaFileObject(File basedir, File file) { - this.basedir = basedir; - this.file = file; - } - - @Override - public URI toUri() { - return this.file.toURI(); - } - - /** - * @return the path of the file relative to the base directory, for example: - * a/b/c/D.class - */ - @Override - public String getName() { - String basedirPath = this.basedir.getPath(); - String filePath = this.file.getPath(); - return filePath.substring(basedirPath.length() + 1); - } - - @Override - public InputStream openInputStream() throws IOException { - return new FileInputStream(this.file); - } - - @Override - public OutputStream openOutputStream() throws IOException { - throw new IllegalStateException("Only expected to be used for input"); - } - - @Override - public Reader openReader(boolean ignoreEncodingErrors) throws IOException { - // It is bytecode - throw new UnsupportedOperationException( - "openReader() not supported on class file: " + getName()); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { - // It is bytecode - throw new UnsupportedOperationException( - "getCharContent() not supported on class file: " + getName()); - } - - @Override - public Writer openWriter() throws IOException { - throw new IllegalStateException("only expected to be used for input"); - } - - @Override - public long getLastModified() { - return this.file.lastModified(); - } - - @Override - public boolean delete() { - return false; // This object is for read only access to a class - } - - @Override - public Kind getKind() { - return Kind.CLASS; - } - - @Override - public boolean isNameCompatible(String simpleName, Kind kind) { - if (kind != Kind.CLASS) { - return false; - } - String name = getName(); - int lastSlash = name.lastIndexOf('/'); - return name.substring(lastSlash + 1).equals(simpleName + ".class"); - } - - @Override - public NestingKind getNestingKind() { - return null; - } - - @Override - public Modifier getAccessLevel() { - return null; - } - - @Override - public int hashCode() { - return this.file.getName().hashCode() * 37 + this.basedir.getName().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof DirEntryJavaFileObject)) { - return false; - } - DirEntryJavaFileObject that = (DirEntryJavaFileObject) obj; - return (this.basedir.getName().equals(that.basedir.getName())) - && (this.file.getName().equals(that.file.getName())); - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/DirEnumeration.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/DirEnumeration.java deleted file mode 100644 index 48017ea84..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/DirEnumeration.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.io.File; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; -import java.util.NoSuchElementException; - -/** - * Walks a directory hierarchy from some base directory discovering files. - * - * @author Andy Clement - */ -public class DirEnumeration implements Enumeration { - - // The starting point - private File basedir; - - // Candidates collected so far - private List filesToReturn; - - // Places still to explore for candidates - private List directoriesToExplore; - - public DirEnumeration(File basedir) { - this.basedir = basedir; - } - - private void computeValue() { - if (this.filesToReturn == null) { // Indicates we haven't started yet - this.filesToReturn = new ArrayList<>(); - this.directoriesToExplore = new ArrayList<>(); - visitDirectory(this.basedir); - } - if (this.filesToReturn.size() == 0) { - while (this.filesToReturn.size() == 0 - && this.directoriesToExplore.size() != 0) { - File nextDir = this.directoriesToExplore.get(0); - this.directoriesToExplore.remove(0); - visitDirectory(nextDir); - } - } - } - - @Override - public boolean hasMoreElements() { - computeValue(); - return this.filesToReturn.size() != 0; - } - - @Override - public File nextElement() { - computeValue(); - if (this.filesToReturn.size() == 0) { - throw new NoSuchElementException(); - } - File toReturn = this.filesToReturn.get(0); - this.filesToReturn.remove(0); - return toReturn; - } - - private void visitDirectory(File dir) { - File[] files = dir.listFiles(); - if (files != null) { - for (File file : files) { - if (file.isDirectory()) { - this.directoriesToExplore.add(file); - } - else { - this.filesToReturn.add(file); - } - } - } - } - - public File getDirectory() { - return this.basedir; - } - - /** - * Return the relative path of this file to the base directory that the directory - * enumeration was started for. - * @param file a file discovered returned by this enumeration - * @return the relative path of the file (for example: a/b/c/D.class) - */ - public String getName(File file) { - String basedirPath = this.basedir.getPath(); - String filePath = file.getPath(); - if (!filePath.startsWith(basedirPath)) { - throw new IllegalStateException("The file '" + filePath - + "' is not nested below the base directory '" + basedirPath + "'"); - } - return filePath.substring(basedirPath.length() + 1); - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/InMemoryJavaFileObject.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/InMemoryJavaFileObject.java deleted file mode 100644 index 5203fb374..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/InMemoryJavaFileObject.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.CharArrayWriter; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.Reader; -import java.io.Writer; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.Charset; - -import javax.lang.model.element.Modifier; -import javax.lang.model.element.NestingKind; -import javax.tools.FileObject; -import javax.tools.JavaFileManager.Location; -import javax.tools.JavaFileObject; -import javax.tools.StandardLocation; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * A JavaFileObject that represents a source artifact created for compilation or an output - * artifact producing during compilation (a .class file or some other thing if an - * annotation processor has run). In order to be clear what it is being used for there are - * static factory methods that ask for specific types of file. - * - * @author Andy Clement - */ -public final class InMemoryJavaFileObject implements JavaFileObject { - - private final static Logger logger = LoggerFactory - .getLogger(InMemoryJavaFileObject.class); - - private Location location; - - private String packageName; - - private String relativeName; - - private FileObject sibling; - - private String className; - - private Kind kind; - - private byte[] content = null; - - private long lastModifiedTime = 0; - - private URI uri = null; - - private InMemoryJavaFileObject() { - } - - public static InMemoryJavaFileObject getFileObject(Location location, - String packageName, String relativeName, FileObject sibling) { - InMemoryJavaFileObject retval = new InMemoryJavaFileObject(); - retval.kind = Kind.OTHER; - retval.location = location; - retval.packageName = packageName; - retval.relativeName = relativeName; - retval.sibling = sibling; - return retval; - } - - public static InMemoryJavaFileObject getJavaFileObject(Location location, - String className, Kind kind, FileObject sibling) { - InMemoryJavaFileObject retval = new InMemoryJavaFileObject(); - retval.location = location; - retval.className = className; - retval.kind = kind; - retval.sibling = sibling; - return retval; - } - - public static InMemoryJavaFileObject getSourceJavaFileObject(String className, - String content) { - InMemoryJavaFileObject retval = new InMemoryJavaFileObject(); - retval.location = StandardLocation.SOURCE_PATH; - retval.className = className; - retval.kind = Kind.SOURCE; - retval.content = content.getBytes(); - return retval; - } - - public byte[] getBytes() { - return this.content; - } - - public String toString() { - return "OutputJavaFileObject: Location=" + this.location + ",className=" - + this.className + ",kind=" + this.kind + ",relativeName=" - + this.relativeName + ",sibling=" + this.sibling + ",packageName=" - + this.packageName; - } - - @Override - public URI toUri() { - // These memory based output files 'pretend' to be relative to the file system - // root - if (this.uri == null) { - String name = null; - if (this.className != null) { - name = this.className.replace('.', '/'); - } - else if (this.packageName != null && this.packageName.length() != 0) { - name = this.packageName.replace('.', '/') + '/' + this.relativeName; - } - else { - name = this.relativeName; - } - - String uriString = null; - try { - uriString = "file:/" + name + this.kind.extension; - this.uri = new URI(uriString); - } - catch (URISyntaxException e) { - throw new IllegalStateException( - "Unexpected URISyntaxException for string '" + uriString + "'", - e); - } - } - return this.uri; - } - - @Override - public String getName() { - return toUri().getPath(); - } - - @Override - public InputStream openInputStream() throws IOException { - if (this.content == null) { - throw new FileNotFoundException(); - } - logger.debug("opening input stream for {}", getName()); - return new ByteArrayInputStream(this.content); - } - - @Override - public OutputStream openOutputStream() throws IOException { - logger.debug("opening output stream for {}", getName()); - return new ByteArrayOutputStream() { - @Override - public void close() throws IOException { - super.close(); - InMemoryJavaFileObject.this.lastModifiedTime = System.currentTimeMillis(); - InMemoryJavaFileObject.this.content = this.toByteArray(); - } - }; - } - - @Override - public Reader openReader(boolean ignoreEncodingErrors) throws IOException { - return new InputStreamReader(openInputStream(), Charset.defaultCharset()); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { - if (this.kind != Kind.SOURCE) { - throw new UnsupportedOperationException( - "getCharContent() not supported on file object: " + getName()); - } - // Not yet supporting encodings - return (this.content == null ? null : new String(this.content)); - } - - @Override - public Writer openWriter() throws IOException { - // Let's not enforce this restriction right now - // if (kind == Kind.CLASS) { - // throw new UnsupportedOperationException("openWriter() not supported on file - // object: " + getName()); - // } - return new CharArrayWriter() { - @Override - public void close() { - InMemoryJavaFileObject.this.lastModifiedTime = System.currentTimeMillis(); - InMemoryJavaFileObject.this.content = new String(toCharArray()) - .getBytes(); // Ignoring encoding... - } - }; - } - - @Override - public long getLastModified() { - return this.lastModifiedTime; - } - - @Override - public boolean delete() { - return false; - } - - @Override - public Kind getKind() { - return this.kind; - } - - public boolean isNameCompatible(String simpleName, Kind kind) { - String baseName = simpleName + kind.extension; - return kind.equals(getKind()) && (baseName.equals(toUri().getPath()) - || toUri().getPath().endsWith("/" + baseName)); - } - - @Override - public NestingKind getNestingKind() { - return null; - } - - @Override - public Modifier getAccessLevel() { - return null; - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/IterableClasspath.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/IterableClasspath.java deleted file mode 100644 index b10e7e0fa..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/IterableClasspath.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Stack; -import java.util.StringTokenizer; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipInputStream; - -import javax.tools.JavaFileObject; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.cloud.function.compiler.java.MemoryBasedJavaFileManager.CompilationInfoCache; -import org.springframework.cloud.function.compiler.java.MemoryBasedJavaFileManager.CompilationInfoCache.ArchiveInfo; - -/** - * Iterable that will produce an iterator that returns classes found 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 spring boot uberjar. - * - * @author Andy Clement - */ -public class IterableClasspath extends CloseableFilterableJavaFileObjectIterable { - - private static Logger logger = LoggerFactory.getLogger(IterableClasspath.class); - - private List classpathEntries = new ArrayList<>(); - - private List openArchives = new ArrayList<>(); - - /** - * @param compilationInfoCache cache of info that may help accelerate compilation - * @param classpath a classpath of jars/directories - * @param packageNameFilter an optional package name if choosing to filter (e.g. - * com.example) - * @param includeSubpackages if true, include results in subpackages of the specified - * package filter - */ - IterableClasspath(CompilationInfoCache compilationInfoCache, String classpath, - String packageNameFilter, boolean includeSubpackages) { - super(compilationInfoCache, packageNameFilter, includeSubpackages); - StringTokenizer tokenizer = new StringTokenizer(classpath, File.pathSeparator); - while (tokenizer.hasMoreElements()) { - String nextEntry = tokenizer.nextToken(); - File f = new File(nextEntry); - if (f.exists()) { - // Skip iterating over archives that cannot possibly match the filter - if (this.packageNameFilter != null - && this.packageNameFilter.length() > 0) { - ArchiveInfo archiveInfo = compilationInfoCache.getArchiveInfoFor(f); - if (archiveInfo != null - && !archiveInfo.containsPackage(this.packageNameFilter, - this.includeSubpackages)) { - continue; - } - } - this.classpathEntries.add(f); - } - else { - logger.debug("path element does not exist {}", f); - } - } - } - - public void close() { - for (ZipFile openArchive : this.openArchives) { - try { - openArchive.close(); - } - catch (IOException ioe) { - logger.debug("Unexpected error closing archive {}", openArchive, ioe); - } - } - this.openArchives.clear(); - } - - public Iterator iterator() { - return new ClasspathEntriesIterator(); - } - - public void reset() { - close(); - } - - static class ZipEnumerator implements Enumeration { - - private ZipInputStream zis; - - private ZipEntry nextEntry = null; - - ZipEnumerator(ZipInputStream zis) { - this.zis = zis; - } - - @Override - public boolean hasMoreElements() { - try { - this.nextEntry = this.zis.getNextEntry(); - } - catch (IOException ioe) { - this.nextEntry = null; - } - return this.nextEntry != null; - } - - @Override - public ZipEntry nextElement() { - ZipEntry retval = this.nextEntry; - this.nextEntry = null; - return retval; - } - - } - - class ClasspathEntriesIterator implements Iterator { - - private int currentClasspathEntriesIndex = 0; - - // Walking one of three possible things: directory tree, zip, or Java runtime - // packaged in JDK9+ form - private File openDirectory = null; - - private DirEnumeration openDirectoryEnumeration = null; - - private ZipFile openArchive = null; - - private File openFile = null; - - private ZipEntry nestedZip = null; - - private Stack> openArchiveEnumeration = null; - - private File openJrt; - - private JrtFsEnumeration openJrtEnumeration = null; - - private JavaFileObject nextEntry = null; - - private void findNext() { - if (this.nextEntry == null) { - try { - while (this.openArchive != null || this.openDirectory != null - || this.openJrt != null - || this.currentClasspathEntriesIndex < IterableClasspath.this.classpathEntries - .size()) { - if (this.openArchive == null && this.openDirectory == null - && this.openJrt == null) { - // Open the next item - File nextFile = IterableClasspath.this.classpathEntries - .get(this.currentClasspathEntriesIndex); - if (nextFile.isDirectory()) { - this.openDirectory = nextFile; - this.openDirectoryEnumeration = new DirEnumeration( - nextFile); - } - else if (nextFile.getName().endsWith("jrt-fs.jar")) { - this.openJrt = nextFile; - this.openJrtEnumeration = new JrtFsEnumeration(nextFile, - null); - } - else { - this.openFile = nextFile; - this.openArchive = new ZipFile(nextFile); - IterableClasspath.this.openArchives.add(this.openArchive); - this.openArchiveEnumeration = new Stack>(); - this.openArchiveEnumeration - .push(this.openArchive.entries()); - } - this.currentClasspathEntriesIndex++; - } - if (this.openArchiveEnumeration != null) { - while (!this.openArchiveEnumeration.isEmpty()) { - while (this.openArchiveEnumeration.peek() - .hasMoreElements()) { - ZipEntry entry = this.openArchiveEnumeration.peek() - .nextElement(); - String entryName = entry.getName(); - if (accept(entryName)) { - if (this.nestedZip != null) { - this.nextEntry = new NestedZipEntryJavaFileObject( - this.openFile, this.openArchive, - this.nestedZip, entry); - } - else { - this.nextEntry = new ZipEntryJavaFileObject( - this.openFile, this.openArchive, - entry); - } - return; - } - else if (this.nestedZip == null - && entryName.startsWith( - MemoryBasedJavaFileManager.BOOT_PACKAGING_PREFIX_FOR_LIBRARIES) - && entryName.endsWith(".jar")) { - // nested jar in uber jar - logger.debug("opening nested archive {}", - entry.getName()); - ZipInputStream zis = new ZipInputStream( - this.openArchive.getInputStream(entry)); - Enumeration nestedZipEnumerator = new ZipEnumerator( - zis); - this.nestedZip = entry; - this.openArchiveEnumeration - .push(nestedZipEnumerator); - } - } - this.openArchiveEnumeration.pop(); - if (this.nestedZip == null) { - this.openArchive = null; - this.openFile = null; - } - else { - this.nestedZip = null; - } - } - this.openArchiveEnumeration = null; - this.openArchive = null; - this.openFile = null; - } - else if (this.openDirectoryEnumeration != null) { - while (this.openDirectoryEnumeration.hasMoreElements()) { - File entry = this.openDirectoryEnumeration.nextElement(); - String name = this.openDirectoryEnumeration - .getName(entry); - if (accept(name)) { - this.nextEntry = new DirEntryJavaFileObject( - this.openDirectoryEnumeration.getDirectory(), - entry); - return; - } - } - this.openDirectoryEnumeration = null; - this.openDirectory = null; - } - else if (this.openJrtEnumeration != null) { - while (this.openJrtEnumeration.hasMoreElements()) { - JrtEntryJavaFileObject jrtEntry = this.openJrtEnumeration - .nextElement(); - String name = this.openJrtEnumeration.getName(jrtEntry); - if (accept(name)) { - this.nextEntry = jrtEntry; - return; - } - } - this.openJrtEnumeration = null; - this.openJrt = null; - } - } - } - catch (IOException ioe) { - logger.debug("Unexpected error whilst processing classpath entries", - ioe); - } - } - } - - public boolean hasNext() { - findNext(); - return this.nextEntry != null; - } - - public JavaFileObject next() { - findNext(); - if (this.nextEntry == null) { - throw new NoSuchElementException(); - } - JavaFileObject retval = this.nextEntry; - this.nextEntry = null; - return retval; - } - - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/IterableJrtModule.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/IterableJrtModule.java deleted file mode 100644 index 50d5c9266..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/IterableJrtModule.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.NoSuchElementException; - -import javax.tools.JavaFileObject; - -import org.springframework.cloud.function.compiler.java.MemoryBasedJavaFileManager.CompilationInfoCache; - -/** - * Iterable that will produce an iterator that returns classes found in a specific module - * tree within the Java runtime image that exists in Java 9 and later. - * - * @author Andy Clement - */ -public class IterableJrtModule extends CloseableFilterableJavaFileObjectIterable { - - // private static Logger logger = LoggerFactory.getLogger(IterableJrtModule.class); - - Map walkers = new HashMap<>(); - - private Path moduleRootPath; - - /** - * @param compilationInfoCache cache of info that may help accelerate compilation - * @param moduleRootPath path to the base of the relevant module within the JRT image - * @param packageNameFilter an optional package name if choosing to filter (e.g. - * com.example) - * @param includeSubpackages if true, include results in subpackages of the specified - * package filter - */ - public IterableJrtModule(CompilationInfoCache compilationInfoCache, - Path moduleRootPath, String packageNameFilter, boolean includeSubpackages) { - super(compilationInfoCache, packageNameFilter, includeSubpackages); - this.moduleRootPath = moduleRootPath; - } - - public Iterator iterator() { - JrtFsEnumeration jrtFsWalker = this.walkers.get(this.moduleRootPath.toString()); - if (jrtFsWalker == null) { - jrtFsWalker = new JrtFsEnumeration(null, this.moduleRootPath); - this.walkers.put(this.moduleRootPath.toString(), jrtFsWalker); - } - jrtFsWalker.reset(); - return new IteratorOverJrtFsEnumeration(jrtFsWalker); - } - - public void close() { - } - - public void reset() { - close(); - } - - class IteratorOverJrtFsEnumeration implements Iterator { - - private JavaFileObject nextEntry = null; - - private JrtFsEnumeration jrtEnumeration; - - IteratorOverJrtFsEnumeration(JrtFsEnumeration jrtFsWalker) { - this.jrtEnumeration = jrtFsWalker; - } - - private void findNext() { - if (this.nextEntry == null) { - while (this.jrtEnumeration.hasMoreElements()) { - JrtEntryJavaFileObject jrtEntry = this.jrtEnumeration.nextElement(); - String name = this.jrtEnumeration.getName(jrtEntry); - if (accept(name)) { - this.nextEntry = jrtEntry; - return; - } - } - } - } - - public boolean hasNext() { - findNext(); - return this.nextEntry != null; - } - - public JavaFileObject next() { - findNext(); - if (this.nextEntry == null) { - throw new NoSuchElementException(); - } - JavaFileObject retval = this.nextEntry; - this.nextEntry = null; - return retval; - } - - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/JrtEntryJavaFileObject.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/JrtEntryJavaFileObject.java deleted file mode 100644 index 385d0577d..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/JrtEntryJavaFileObject.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.io.Writer; -import java.net.URI; -import java.nio.file.Files; -import java.nio.file.Path; - -import javax.lang.model.element.Modifier; -import javax.lang.model.element.NestingKind; -import javax.tools.JavaFileObject; - -/** - * A JavaFileObject that represents a class from the Java runtime as packaged in Java 9 - * and later. - * - * @author Andy Clement - */ -public class JrtEntryJavaFileObject implements JavaFileObject { - - private String pathToClassString; - - private Path path; - - /** - * @param path entry in the Java runtime filesystem, for example - * '/modules/java.base/java/lang/Object.class' - */ - public JrtEntryJavaFileObject(Path path) { - this.pathToClassString = path.subpath(2, path.getNameCount()).toString(); // e.g. - // java/lang/Object.class - this.path = path; - } - - @Override - public URI toUri() { - return this.path.toUri(); - } - - /** - * @return the path of the file relative to the base directory, for example: - * a/b/c/D.class - */ - @Override - public String getName() { - return this.pathToClassString; - } - - @Override - public InputStream openInputStream() throws IOException { - byte[] bytes = Files.readAllBytes(this.path); - return new ByteArrayInputStream(bytes); - } - - @Override - public OutputStream openOutputStream() throws IOException { - throw new IllegalStateException("Only expected to be used for input"); - } - - @Override - public Reader openReader(boolean ignoreEncodingErrors) throws IOException { - // It is bytecode - throw new UnsupportedOperationException( - "openReader() not supported on class file: " + getName()); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { - // It is bytecode - throw new UnsupportedOperationException( - "getCharContent() not supported on class file: " + getName()); - } - - @Override - public Writer openWriter() throws IOException { - throw new IllegalStateException("only expected to be used for input"); - } - - @Override - public long getLastModified() { - try { - return Files.getLastModifiedTime(this.path).toMillis(); - } - catch (IOException ioe) { - throw new RuntimeException( - "Unable to determine last modified time of " + this.pathToClassString, - ioe); - } - } - - @Override - public boolean delete() { - return false; // This object is for read only access to a class - } - - @Override - public Kind getKind() { - return Kind.CLASS; - } - - @Override - public boolean isNameCompatible(String simpleName, Kind kind) { - if (kind != Kind.CLASS) { - return false; - } - String name = getName(); - int lastSlash = name.lastIndexOf('/'); - return name.substring(lastSlash + 1).equals(simpleName + ".class"); - } - - @Override - public NestingKind getNestingKind() { - return null; - } - - @Override - public Modifier getAccessLevel() { - return null; - } - - @Override - public int hashCode() { - return getName().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof JrtEntryJavaFileObject)) { - return false; - } - JrtEntryJavaFileObject that = (JrtEntryJavaFileObject) obj; - return (getName().equals(that.getName())); - } - - public String getPathToClassString() { - return this.pathToClassString; - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/JrtFsEnumeration.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/JrtFsEnumeration.java deleted file mode 100644 index ed9b1eb93..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/JrtFsEnumeration.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; -import java.util.NoSuchElementException; - -/** - * Walks a JrtFS treating it like a directory (to avoid overcomplicating the walking logic - * in IterableClasspath). - * - * @author Andy Clement - */ -public class JrtFsEnumeration implements Enumeration { - - // private final static Logger logger = - // LoggerFactory.getLogger(JrtFsEnumeration.class); - - private static URI JRT_URI = URI.create("jrt:/"); //$NON-NLS-1$ - - private final static FileSystem fs = FileSystems.getFileSystem(JRT_URI); - - private Path pathWithinJrt; - - private List jfos = new ArrayList<>(); - - private Integer counter = 0; - - private Boolean initialized = false; - - public JrtFsEnumeration(File jrtFsFile, Path pathWithinJrt) { - this.pathWithinJrt = pathWithinJrt; - ensureInitialized(); - } - - private void ensureInitialized() { - synchronized (this.initialized) { - if (this.initialized) { - return; - } - FileCacheBuilderVisitor visitor = new FileCacheBuilderVisitor(); - if (this.pathWithinJrt != null) { - try { - Files.walkFileTree(this.pathWithinJrt, visitor); - // System.out.println("JrtFs enumeration for '"+pathWithinJrt+"' with - // #"+jfos.size()+" entries"); - } - catch (IOException e) { - throw new RuntimeException(e); - } - } - else { - Iterable roots = fs.getRootDirectories(); - try { - for (java.nio.file.Path path : roots) { - Files.walkFileTree(path, visitor); - } - // System.out.println("JrtFs enumeration initialized with - // #"+jfos.size()+" entries"); - } - catch (IOException e) { - throw new RuntimeException(e); - } - } - this.initialized = true; - } - } - - @Override - public boolean hasMoreElements() { - return this.counter < this.jfos.size(); - } - - @Override - public JrtEntryJavaFileObject nextElement() { - if (this.counter >= this.jfos.size()) { - throw new NoSuchElementException(); - } - JrtEntryJavaFileObject toReturn = this.jfos.get(this.counter++); - return toReturn; - } - - /** - * Return the relative path of this file to the base directory that the directory - * enumeration was started for. - * @param file a file discovered returned by this enumeration - * @return the relative path of the file (for example: a/b/c/D.class) - */ - public String getName(JrtEntryJavaFileObject file) { - return file.getPathToClassString(); - } - - public void reset() { - this.counter = 0; - } - - class FileCacheBuilderVisitor extends SimpleFileVisitor { - - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) - throws IOException { - int fnc = file.getNameCount(); - if (fnc >= 3 && file.toString().endsWith(".class")) { // There is a preceeding - // module name - e.g. - // /modules/java.base/java/lang/Object.class - // file.subpath(2, fnc); // e.g. java/lang/Object.class - JrtFsEnumeration.this.jfos.add(new JrtEntryJavaFileObject(file)); - } - return FileVisitResult.CONTINUE; - } - - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/MavenSettings.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/MavenSettings.java deleted file mode 100644 index da210daf4..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/MavenSettings.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringReader; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import org.apache.maven.model.ActivationFile; -import org.apache.maven.model.ActivationOS; -import org.apache.maven.model.ActivationProperty; -import org.apache.maven.model.building.ModelProblemCollector; -import org.apache.maven.model.building.ModelProblemCollectorRequest; -import org.apache.maven.model.path.DefaultPathTranslator; -import org.apache.maven.model.profile.DefaultProfileSelector; -import org.apache.maven.model.profile.ProfileActivationContext; -import org.apache.maven.model.profile.activation.FileProfileActivator; -import org.apache.maven.model.profile.activation.JdkVersionProfileActivator; -import org.apache.maven.model.profile.activation.OperatingSystemProfileActivator; -import org.apache.maven.model.profile.activation.PropertyProfileActivator; -import org.apache.maven.settings.Activation; -import org.apache.maven.settings.Mirror; -import org.apache.maven.settings.Profile; -import org.apache.maven.settings.Proxy; -import org.apache.maven.settings.Server; -import org.apache.maven.settings.Settings; -import org.apache.maven.settings.crypto.SettingsDecryptionResult; -import org.eclipse.aether.repository.Authentication; -import org.eclipse.aether.repository.AuthenticationSelector; -import org.eclipse.aether.repository.MirrorSelector; -import org.eclipse.aether.repository.ProxySelector; -import org.eclipse.aether.util.repository.AuthenticationBuilder; -import org.eclipse.aether.util.repository.ConservativeAuthenticationSelector; -import org.eclipse.aether.util.repository.DefaultAuthenticationSelector; -import org.eclipse.aether.util.repository.DefaultMirrorSelector; -import org.eclipse.aether.util.repository.DefaultProxySelector; - -/** - * An encapsulation of settings read from a user's Maven settings.xml. - * - * @author Andy Wilkinson - * @see MavenSettingsReader - */ -public class MavenSettings { - - private final boolean offline; - - private final MirrorSelector mirrorSelector; - - private final AuthenticationSelector authenticationSelector; - - private final ProxySelector proxySelector; - - private final String localRepository; - - private final List activeProfiles; - - /** - * Create a new {@link MavenSettings} instance. - * @param settings the source settings - * @param decryptedSettings the decrypted settings - */ - public MavenSettings(Settings settings, SettingsDecryptionResult decryptedSettings) { - this.offline = settings.isOffline(); - this.mirrorSelector = createMirrorSelector(settings); - this.authenticationSelector = createAuthenticationSelector(decryptedSettings); - this.proxySelector = createProxySelector(decryptedSettings); - this.localRepository = settings.getLocalRepository(); - this.activeProfiles = determineActiveProfiles(settings); - } - - private MirrorSelector createMirrorSelector(Settings settings) { - DefaultMirrorSelector selector = new DefaultMirrorSelector(); - for (Mirror mirror : settings.getMirrors()) { - selector.add(mirror.getId(), mirror.getUrl(), mirror.getLayout(), false, - mirror.getMirrorOf(), mirror.getMirrorOfLayouts()); - } - return selector; - } - - private AuthenticationSelector createAuthenticationSelector( - SettingsDecryptionResult decryptedSettings) { - DefaultAuthenticationSelector selector = new DefaultAuthenticationSelector(); - for (Server server : decryptedSettings.getServers()) { - AuthenticationBuilder auth = new AuthenticationBuilder(); - auth.addUsername(server.getUsername()).addPassword(server.getPassword()); - auth.addPrivateKey(server.getPrivateKey(), server.getPassphrase()); - selector.add(server.getId(), auth.build()); - } - return new ConservativeAuthenticationSelector(selector); - } - - private ProxySelector createProxySelector( - SettingsDecryptionResult decryptedSettings) { - DefaultProxySelector selector = new DefaultProxySelector(); - for (Proxy proxy : decryptedSettings.getProxies()) { - Authentication authentication = new AuthenticationBuilder() - .addUsername(proxy.getUsername()).addPassword(proxy.getPassword()) - .build(); - selector.add( - new org.eclipse.aether.repository.Proxy(proxy.getProtocol(), - proxy.getHost(), proxy.getPort(), authentication), - proxy.getNonProxyHosts()); - } - return selector; - } - - private List determineActiveProfiles(Settings settings) { - SpringBootCliModelProblemCollector problemCollector = new SpringBootCliModelProblemCollector(); - List activeModelProfiles = createProfileSelector() - .getActiveProfiles(createModelProfiles(settings.getProfiles()), - new SpringBootCliProfileActivationContext( - settings.getActiveProfiles()), - problemCollector); - if (!problemCollector.getProblems().isEmpty()) { - throw new IllegalStateException(createFailureMessage(problemCollector)); - } - List activeProfiles = new ArrayList(); - Map profiles = settings.getProfilesAsMap(); - for (org.apache.maven.model.Profile modelProfile : activeModelProfiles) { - activeProfiles.add(profiles.get(modelProfile.getId())); - } - return activeProfiles; - } - - private String createFailureMessage( - SpringBootCliModelProblemCollector problemCollector) { - StringWriter message = new StringWriter(); - PrintWriter printer = new PrintWriter(message); - printer.println("Failed to determine active profiles:"); - for (ModelProblemCollectorRequest problem : problemCollector.getProblems()) { - printer.println(" " + problem.getMessage() + (problem.getLocation() != null - ? " at " + problem.getLocation() : "")); - if (problem.getException() != null) { - printer.println(indentStackTrace(problem.getException(), " ")); - } - } - return message.toString(); - } - - private String indentStackTrace(Exception ex, String indent) { - return indentLines(printStackTrace(ex), indent); - } - - private String printStackTrace(Exception ex) { - StringWriter stackTrace = new StringWriter(); - PrintWriter printer = new PrintWriter(stackTrace); - ex.printStackTrace(printer); - return stackTrace.toString(); - } - - private String indentLines(String input, String indent) { - StringWriter indented = new StringWriter(); - PrintWriter writer = new PrintWriter(indented); - String line; - BufferedReader reader = new BufferedReader(new StringReader(input)); - try { - while ((line = reader.readLine()) != null) { - writer.println(indent + line); - } - } - catch (IOException ex) { - return input; - } - return indented.toString(); - } - - private DefaultProfileSelector createProfileSelector() { - DefaultProfileSelector selector = new DefaultProfileSelector(); - - selector.addProfileActivator(new FileProfileActivator() - .setPathTranslator(new DefaultPathTranslator())); - selector.addProfileActivator(new JdkVersionProfileActivator()); - selector.addProfileActivator(new PropertyProfileActivator()); - selector.addProfileActivator(new OperatingSystemProfileActivator()); - return selector; - } - - private List createModelProfiles( - List profiles) { - List modelProfiles = new ArrayList(); - for (Profile profile : profiles) { - org.apache.maven.model.Profile modelProfile = new org.apache.maven.model.Profile(); - modelProfile.setId(profile.getId()); - if (profile.getActivation() != null) { - modelProfile - .setActivation(createModelActivation(profile.getActivation())); - } - modelProfiles.add(modelProfile); - } - return modelProfiles; - } - - private org.apache.maven.model.Activation createModelActivation( - Activation activation) { - org.apache.maven.model.Activation modelActivation = new org.apache.maven.model.Activation(); - modelActivation.setActiveByDefault(activation.isActiveByDefault()); - if (activation.getFile() != null) { - ActivationFile activationFile = new ActivationFile(); - activationFile.setExists(activation.getFile().getExists()); - activationFile.setMissing(activation.getFile().getMissing()); - modelActivation.setFile(activationFile); - } - modelActivation.setJdk(activation.getJdk()); - if (activation.getOs() != null) { - ActivationOS os = new ActivationOS(); - os.setArch(activation.getOs().getArch()); - os.setFamily(activation.getOs().getFamily()); - os.setName(activation.getOs().getName()); - os.setVersion(activation.getOs().getVersion()); - modelActivation.setOs(os); - } - if (activation.getProperty() != null) { - ActivationProperty property = new ActivationProperty(); - property.setName(activation.getProperty().getName()); - property.setValue(activation.getProperty().getValue()); - modelActivation.setProperty(property); - } - return modelActivation; - } - - public boolean getOffline() { - return this.offline; - } - - public MirrorSelector getMirrorSelector() { - return this.mirrorSelector; - } - - public AuthenticationSelector getAuthenticationSelector() { - return this.authenticationSelector; - } - - public ProxySelector getProxySelector() { - return this.proxySelector; - } - - public String getLocalRepository() { - return this.localRepository; - } - - public List getActiveProfiles() { - return this.activeProfiles; - } - - private static final class SpringBootCliProfileActivationContext - implements ProfileActivationContext { - - private final List activeProfiles; - - SpringBootCliProfileActivationContext(List activeProfiles) { - this.activeProfiles = activeProfiles; - } - - @Override - public List getActiveProfileIds() { - return this.activeProfiles; - } - - @Override - public List getInactiveProfileIds() { - return Collections.emptyList(); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Override - public Map getSystemProperties() { - return (Map) System.getProperties(); - } - - @Override - public Map getUserProperties() { - return Collections.emptyMap(); - } - - @Override - public File getProjectDirectory() { - return new File("."); - } - - @Override - public Map getProjectProperties() { - return Collections.emptyMap(); - } - - } - - private static final class SpringBootCliModelProblemCollector - implements ModelProblemCollector { - - private final List problems = new ArrayList(); - - @Override - public void add(ModelProblemCollectorRequest req) { - this.problems.add(req); - } - - List getProblems() { - return this.problems; - } - - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/MavenSettingsReader.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/MavenSettingsReader.java deleted file mode 100644 index a2292f982..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/MavenSettingsReader.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.io.File; -import java.lang.reflect.Field; - -import org.apache.maven.settings.Settings; -import org.apache.maven.settings.building.DefaultSettingsBuilderFactory; -import org.apache.maven.settings.building.DefaultSettingsBuildingRequest; -import org.apache.maven.settings.building.SettingsBuildingException; -import org.apache.maven.settings.building.SettingsBuildingRequest; -import org.apache.maven.settings.crypto.DefaultSettingsDecrypter; -import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest; -import org.apache.maven.settings.crypto.SettingsDecrypter; -import org.apache.maven.settings.crypto.SettingsDecryptionResult; -import org.eclipse.aether.DefaultRepositorySystemSession; -import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory; -import org.eclipse.aether.repository.LocalRepository; -import org.eclipse.aether.repository.NoLocalRepositoryManagerException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonatype.plexus.components.cipher.DefaultPlexusCipher; -import org.sonatype.plexus.components.cipher.PlexusCipherException; -import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher; - -/** - * {@code MavenSettingsReader} reads settings from a user's Maven settings.xml file, - * decrypting them if necessary using settings-security.xml. - * - * @author Andy Wilkinson - */ -public class MavenSettingsReader { - - private static final Logger log = LoggerFactory.getLogger(MavenSettingsReader.class); - - private final String homeDir; - - public MavenSettingsReader() { - this(System.getProperty("user.home")); - } - - public MavenSettingsReader(String homeDir) { - this.homeDir = homeDir; - } - - public static void applySettings(MavenSettings settings, - DefaultRepositorySystemSession session) { - if (settings.getLocalRepository() != null) { - try { - session.setLocalRepositoryManager( - new SimpleLocalRepositoryManagerFactory().newInstance(session, - new LocalRepository(settings.getLocalRepository()))); - } - catch (NoLocalRepositoryManagerException e) { - throw new IllegalStateException( - "Cannot set local repository to " + settings.getLocalRepository(), - e); - } - } - session.setOffline(settings.getOffline()); - session.setMirrorSelector(settings.getMirrorSelector()); - session.setAuthenticationSelector(settings.getAuthenticationSelector()); - session.setProxySelector(settings.getProxySelector()); - } - - public MavenSettings readSettings() { - Settings settings = loadSettings(); - SettingsDecryptionResult decrypted = decryptSettings(settings); - if (!decrypted.getProblems().isEmpty()) { - log.error( - "Maven settings decryption failed. Some Maven repositories may be inaccessible"); - // Continue - the encrypted credentials may not be used - } - return new MavenSettings(settings, decrypted); - } - - private Settings loadSettings() { - File settingsFile = new File(this.homeDir, ".m2/settings.xml"); - if (settingsFile.exists()) { - log.info("Reading settings from: " + settingsFile); - } - else { - log.info("No settings found at: " + settingsFile); - } - SettingsBuildingRequest request = new DefaultSettingsBuildingRequest(); - request.setUserSettingsFile(settingsFile); - request.setSystemProperties(System.getProperties()); - try { - return new DefaultSettingsBuilderFactory().newInstance().build(request) - .getEffectiveSettings(); - } - catch (SettingsBuildingException ex) { - throw new IllegalStateException( - "Failed to build settings from " + settingsFile, ex); - } - } - - private SettingsDecryptionResult decryptSettings(Settings settings) { - DefaultSettingsDecryptionRequest request = new DefaultSettingsDecryptionRequest( - settings); - - return createSettingsDecrypter().decrypt(request); - } - - private SettingsDecrypter createSettingsDecrypter() { - SettingsDecrypter settingsDecrypter = new DefaultSettingsDecrypter(); - setField(DefaultSettingsDecrypter.class, "securityDispatcher", settingsDecrypter, - new SpringBootSecDispatcher()); - return settingsDecrypter; - } - - private void setField(Class sourceClass, String fieldName, Object target, - Object value) { - try { - Field field = sourceClass.getDeclaredField(fieldName); - field.setAccessible(true); - field.set(target, value); - } - catch (Exception ex) { - throw new IllegalStateException( - "Failed to set field '" + fieldName + "' on '" + target + "'", ex); - } - } - - private class SpringBootSecDispatcher extends DefaultSecDispatcher { - - private static final String SECURITY_XML = ".m2/settings-security.xml"; - - SpringBootSecDispatcher() { - File file = new File(MavenSettingsReader.this.homeDir, SECURITY_XML); - this._configurationFile = file.getAbsolutePath(); - try { - this._cipher = new DefaultPlexusCipher(); - } - catch (PlexusCipherException e) { - throw new IllegalStateException(e); - } - } - - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/MemoryBasedJavaFileManager.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/MemoryBasedJavaFileManager.java deleted file mode 100644 index 2b20695cf..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/MemoryBasedJavaFileManager.java +++ /dev/null @@ -1,769 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.net.URL; -import java.net.URLClassLoader; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipInputStream; - -import javax.tools.FileObject; -import javax.tools.JavaFileManager; -import javax.tools.JavaFileObject; -import javax.tools.JavaFileObject.Kind; -import javax.tools.StandardLocation; - -import org.eclipse.aether.artifact.DefaultArtifact; -import org.eclipse.aether.graph.Dependency; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.cloud.function.compiler.java.IterableClasspath.ZipEnumerator; - -/** - * A file manager that serves source code from in memory and ensures output results are - * kept in memory rather than being flushed out to disk. The JavaFileManager is also used - * as a lookup mechanism for resolving types. - * - * @author Andy Clement - * @author Oleg Zhurakousky - */ -public class MemoryBasedJavaFileManager implements JavaFileManager { - - final static String BOOT_PACKAGING_PREFIX_FOR_CLASSES = "BOOT-INF/classes/"; - - final static String BOOT_PACKAGING_PREFIX_FOR_LIBRARIES = "BOOT-INF/lib/"; - - private static Logger logger = LoggerFactory - .getLogger(MemoryBasedJavaFileManager.class); - - private static URI JRT_URI = URI.create("jrt:/"); - - private static FileSystem fs; - - private CompilationOutputCollector outputCollector; - - private Map resolvedAdditionalDependencies = new LinkedHashMap<>(); - - private String platformClasspath; - - private String classpath; - - private CompilationInfoCache compilationInfoCache; - - private Map iterables = new HashMap<>(); - - private String jrtFsFilePath = null; - - private boolean checkedForJrtFsPath = false; - - public MemoryBasedJavaFileManager() { - this.outputCollector = new CompilationOutputCollector(); - this.compilationInfoCache = new CompilationInfoCache(); - } - - private static FileSystem getJrtFs() { - if (fs == null) { - fs = FileSystems.getFileSystem(JRT_URI); - } - return fs; - } - - @Override - public int isSupportedOption(String option) { - logger.debug("isSupportedOption({})", option); - return -1; // Not yet supporting options - } - - @Override - public ClassLoader getClassLoader(Location location) { - // Do not simply return the context classloader as it may get closed and then - // be unusable for loading any further classes - logger.debug("getClassLoader({})", location); - return null; // Do not currently need to load plugins - } - - private String getPlatformClassPath() { - if (this.platformClasspath == null) { - this.platformClasspath = System.getProperty("sun.boot.class.path"); - } - if (this.platformClasspath == null) { - this.platformClasspath = ""; - } - return this.platformClasspath; - } - - @Override - public Iterable list(Location location, String packageName, - Set kinds, boolean recurse) throws IOException { - logger.debug("list({},{},{},{})", location, packageName, kinds, recurse); - String classpath = ""; - Path moduleRootPath = null; - if (location instanceof JDKModuleLocation - && (kinds == null || kinds.contains(Kind.CLASS))) { - // list(org.springframework.cloud.function.compiler.java.MemoryBasedJavaFileManager$JDKModuleLocation@550a1967, - // java.lang,[SOURCE, CLASS, HTML, OTHER],false) - moduleRootPath = ((JDKModuleLocation) location).getModuleRootPath(); - logger.debug("For JDKModuleLocation " + location.toString() + " root path is " - + moduleRootPath); - } - else if (location == StandardLocation.PLATFORM_CLASS_PATH - && (kinds == null || kinds.contains(Kind.CLASS))) { - classpath = getPlatformClassPath(); - // if (classpath.length() == 0) { - // if (hasJrtFsPath()) { - // classpath = getJrtFsPath(); - // } - // } - logger.debug("Creating iterable for boot class path: {}", classpath); - } - else if (location == StandardLocation.CLASS_PATH - && (kinds == null || kinds.contains(Kind.CLASS))) { - String javaClassPath = getClassPath(); - if (!this.resolvedAdditionalDependencies.isEmpty()) { - for (File resolvedAdditionalDependency : this.resolvedAdditionalDependencies - .values()) { - javaClassPath += File.pathSeparatorChar + resolvedAdditionalDependency - .toURI().toString().substring("file:".length()); - } - } - classpath = javaClassPath; - logger.debug("Creating iterable for class path: {}", classpath); - } - Key k = new Key(location, classpath, packageName, kinds, recurse); - CloseableFilterableJavaFileObjectIterable resultIterable = this.iterables.get(k); - if (resultIterable == null) { - if (moduleRootPath != null) { - resultIterable = new IterableJrtModule(this.compilationInfoCache, - moduleRootPath, packageName, recurse); - } - else { - resultIterable = new IterableClasspath(this.compilationInfoCache, - classpath, packageName, recurse); - } - this.iterables.put(k, resultIterable); - } - resultIterable.reset(); - return resultIterable; - } - - private String getClassPath() { - if (this.classpath == null) { - ClassLoader loader = InMemoryJavaFileObject.class.getClassLoader(); - String cp = null; - if (loader instanceof URLClassLoader) { - cp = classPath((URLClassLoader) loader, cp); - } - if (cp == null) { - cp = System.getProperty("java.class.path"); - } - if (hasJrtFsPath()) { - cp = cp + File.pathSeparator + getJrtFsPath(); - } - this.classpath = pathWithPlatformClassPathRemoved(cp); - } - return this.classpath; - } - - private String classPath(URLClassLoader loader, String cp) { - URL[] urls = loader.getURLs(); - if (urls.length > 1) { // heuristic that catches Maven surefire tests - if (!urls[0].toString().startsWith("jar:file:")) { // heuristic for - // Spring Boot fat - // jar - StringBuilder builder = new StringBuilder(); - for (URL url : urls) { - if (builder.length() > 0) { - builder.append(File.pathSeparator); - } - String path = url.toString(); - if (path.startsWith("file:")) { - path = path.substring("file:".length()); - } - builder.append(path); - } - cp = builder.toString(); - } - } - return cp; - } - - // remove the platform classpath entries, they will be search separately (and earlier) - private String pathWithPlatformClassPathRemoved(String classpath) { - Set pcps = toList(getPlatformClassPath()); - Set cps = toList(classpath); - cps.removeAll(pcps); - StringBuilder builder = new StringBuilder(); - for (String cpe : cps) { - if (builder.length() > 0) { - builder.append(File.pathSeparator); - } - builder.append(cpe); - } - return builder.toString(); - } - - private Set toList(String path) { - Set result = new LinkedHashSet<>(); - StringTokenizer tokenizer = new StringTokenizer(path, File.pathSeparator); - while (tokenizer.hasMoreTokens()) { - result.add(tokenizer.nextToken()); - } - return result; - } - - @Override - public boolean hasLocation(Location location) { - logger.debug("hasLocation({})", location); - return (location == StandardLocation.SOURCE_PATH - || location == StandardLocation.CLASS_PATH - || location == StandardLocation.PLATFORM_CLASS_PATH); - } - - @Override - public String inferBinaryName(Location location, JavaFileObject file) { - if (location == StandardLocation.SOURCE_PATH) { - return null; - } - // Kind of ignoring location here... assuming we want basically the FQ type name - // Example value from getName(): javax/validation/bootstrap/GenericBootstrap.class - String classname = file.getName().replace('/', '.').replace('\\', '.'); - return classname.substring(0, classname.lastIndexOf(".class")); - } - - @Override - public boolean isSameFile(FileObject a, FileObject b) { - logger.debug("isSameFile({},{})", a, b); - return a.equals(b); - } - - @Override - public boolean handleOption(String current, Iterator remaining) { - logger.debug("handleOption({},{})", current, remaining); - return false; // This file manager does not manage any options - } - - @Override - public JavaFileObject getJavaFileForInput(Location location, String className, - Kind kind) throws IOException { - logger.debug("getJavaFileForInput({},{},{})", location, className, kind); - // getJavaFileForInput(SOURCE_PATH,module-info,SOURCE) - if (className.equals("module-info")) { - return null; - } - throw new IllegalStateException("Not expected to be used in this context"); - } - - @Override - public JavaFileObject getJavaFileForOutput(Location location, String className, - Kind kind, FileObject sibling) throws IOException { - logger.debug("getJavaFileForOutput({},{},{},{})", location, className, kind, - sibling); - // Example parameters: CLASS_OUTPUT, Foo, CLASS, - // StringBasedJavaSourceFileObject[string:///a/b/c/Foo.java] - return this.outputCollector.getJavaFileForOutput(location, className, kind, - sibling); - } - - @Override - public FileObject getFileForInput(Location location, String packageName, - String relativeName) throws IOException { - logger.debug("getFileForInput({},{},{})", location, packageName, relativeName); - throw new IllegalStateException("Not expected to be used in this context"); - } - - @Override - public FileObject getFileForOutput(Location location, String packageName, - String relativeName, FileObject sibling) throws IOException { - logger.debug("getFileForOutput({},{},{},{})", location, packageName, relativeName, - sibling); - // This can be called when the annotation config processor runs - // Example parameters: CLASS_OUTPUT, , - // META-INF/spring-configuration-metadata.json, null - return this.outputCollector.getFileForOutput(location, packageName, relativeName, - sibling); - } - - @Override - public void flush() throws IOException { - } - - @Override - public void close() throws IOException { - Collection toClose = this.iterables - .values(); - for (CloseableFilterableJavaFileObjectIterable icp : toClose) { - icp.close(); - } - } - - public List getCompiledClasses() { - return this.outputCollector.getCompiledClasses(); - } - - public List addAndResolveDependencies(String[] dependencies) { - List resolutionMessages = new ArrayList<>(); - for (String dependency : dependencies) { - if (dependency.startsWith("maven:")) { - // Resolving an explicit external archive - String coordinates = dependency.replaceFirst("maven:\\/*", ""); - DependencyResolver engine = DependencyResolver.instance(); - try { - File resolved = engine.resolve( - new Dependency(new DefaultArtifact(coordinates), "runtime")); - // Example: - // dependency = - // maven://org.springframework:spring-expression:4.3.9.RELEASE - // resolved.toURI() = - // file:/Users/aclement/.m2/repository/ - // org/springframework/spring-expression/4.3.9.RELEASE/spring-expression-4.3.9.RELEASE.jar - this.resolvedAdditionalDependencies.put(dependency, resolved); - } - catch (RuntimeException re) { - CompilationMessage compilationMessage = new CompilationMessage( - CompilationMessage.Kind.ERROR, re.getMessage(), null, 0, 0); - resolutionMessages.add(compilationMessage); - } - } - else if (dependency.startsWith("file:")) { - this.resolvedAdditionalDependencies.put(dependency, - new File(URI.create(dependency))); - } - else { - resolutionMessages.add(new CompilationMessage( - CompilationMessage.Kind.ERROR, - "Unrecognized dependency: " + dependency - + " (expected something of the form: maven://groupId:artifactId:version)", - null, 0, 0)); - } - } - return resolutionMessages; - } - - public Map getResolvedAdditionalDependencies() { - return this.resolvedAdditionalDependencies; - } - - public String inferModuleName(Location location) throws IOException { - if (location instanceof JDKModuleLocation) { - JDKModuleLocation m = (JDKModuleLocation) location; - return m.getModuleName(); - } - throw new IllegalStateException( - "Asked to inferModuleName from a " + location.getClass().getName()); - } - - private boolean hasJrtFsPath() { - return getJrtFsPath() != null; - } - - private String getJrtFsPath() { - if (!this.checkedForJrtFsPath) { - String javaHome = System.getProperty("java.home"); - String jrtFsFilePath = javaHome + File.separator + "lib" + File.separator - + "jrt-fs.jar"; - File jrtFsFile = new File(jrtFsFilePath); - if (jrtFsFile.exists()) { - this.jrtFsFilePath = jrtFsFilePath; - } - this.checkedForJrtFsPath = true; - } - return this.jrtFsFilePath; - } - - public Iterable> listLocationsForModules(Location location) - throws IOException { - if (getJrtFsPath() != null - && location == StandardLocation.valueOf("SYSTEM_MODULES")) { - Set> ss = new HashSet<>(); - HashSet moduleLocations = new HashSet<>(); - ModuleIdentifierVisitor visitor = new ModuleIdentifierVisitor(); - Iterable roots = getJrtFs().getRootDirectories(); - try { - for (Path path : roots) { - Files.walkFileTree(path, visitor); - } - moduleLocations.addAll(visitor.getModuleLocations()); - } - catch (IOException ioe) { - throw new RuntimeException(ioe); - } - ss.add(moduleLocations); - return ss; - } - else { - return Collections.emptySet(); - } - } - - // Holds information that may help speed up compilation - static class CompilationInfoCache { - - private Map archivePackageCache; - - private boolean packageCacheInitialized = false; - - private Map packageCache = new HashMap(); - - private ArchiveInfo moduleArchiveInfo; - - ArchiveInfo getArchiveInfoFor(File archive) { - if (!archive.isFile() || !(archive.getName().endsWith(".zip") - || archive.getName().endsWith(".jar"))) { - // it is not an archive - return null; - } - if (this.archivePackageCache == null) { - this.archivePackageCache = new HashMap<>(); - } - try { - ArchiveInfo result = this.archivePackageCache.get(archive); - if (result == null) { - result = buildArchiveInfo(archive); - this.archivePackageCache.put(archive, result); - } - return result; - } - catch (Exception e) { - throw new IllegalStateException( - "Unexpected problem caching entries from " + archive.getName(), - e); - } - } - - private synchronized ArchiveInfo buildPackageMap() { - if (!this.packageCacheInitialized) { - this.packageCacheInitialized = true; - Iterable roots = getJrtFs().getRootDirectories(); - PackageCacheBuilderVisitor visitor = new PackageCacheBuilderVisitor(); - try { - for (java.nio.file.Path path : roots) { - Files.walkFileTree(path, visitor); - } - } - catch (IOException e) { - throw new RuntimeException(e); - } - List ls = new ArrayList<>(); - ls.addAll(this.packageCache.keySet()); - Collections.sort(ls); - this.moduleArchiveInfo = new ArchiveInfo(ls, false); - } - return this.moduleArchiveInfo; - } - - /** - * 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 walk those too and include relevant - * packages. - * @param file archive file to discover packages from - * @return an ArchiveInfo encapsulating package info from the archive - */ - private ArchiveInfo buildArchiveInfo(File file) { - if (file.toString().endsWith("jrt-fs.jar")) { - // Special treatment for >=JDK9 - treat this as intention to use modules - return buildPackageMap(); - } - List packageNames = new ArrayList<>(); - boolean isBootJar = false; - try (ZipFile openArchive = new ZipFile(file)) { - Enumeration entries = openArchive.entries(); - while (entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - String name = entry.getName(); - if (name.endsWith(".class")) { - if (name.startsWith(BOOT_PACKAGING_PREFIX_FOR_CLASSES)) { - isBootJar = true; - int idx = name.lastIndexOf('/') + 1; - if (idx != 0) { - if (idx == BOOT_PACKAGING_PREFIX_FOR_CLASSES.length()) { - // default package - packageNames.add("/"); - } - else { - // Normalize to forward slashes - name = name.substring( - BOOT_PACKAGING_PREFIX_FOR_CLASSES.length(), - idx); - name = name.replace('\\', '/'); - packageNames.add(name); - } - } - } - else { - int idx = name.lastIndexOf('/') + 1; - if (idx != 0) { - // Normalize to forward slashes - name = name.replace('\\', '/'); - name = name.substring(0, idx); - packageNames.add(name); - } - else if (idx == 0) { - // default package entries in here - packageNames.add("/"); - } - } - } - else if (name.startsWith(BOOT_PACKAGING_PREFIX_FOR_LIBRARIES) - && name.endsWith(".jar")) { - isBootJar = true; - try (ZipInputStream zis = new ZipInputStream( - openArchive.getInputStream(entry))) { - Enumeration nestedZipEnumerator = new ZipEnumerator( - zis); - while (nestedZipEnumerator.hasMoreElements()) { - ZipEntry innerEntry = nestedZipEnumerator.nextElement(); - String innerEntryName = innerEntry.getName(); - if (innerEntryName.endsWith(".class")) { - int idx = innerEntryName.lastIndexOf('/') + 1; - if (idx != 0) { - // Normalize to forward slashes - innerEntryName = innerEntryName.replace('\\', - '/'); - innerEntryName = innerEntryName.substring(0, idx); - packageNames.add(innerEntryName); - } - else if (idx == 0) { - // default package entries in here - packageNames.add("/"); - } - } - } - } - } - } - } - catch (IOException ioe) { - throw new IllegalStateException( - "Unexpected problem determining packages in " + file, ioe); - } - return new ArchiveInfo(packageNames, isBootJar); - } - - static class ArchiveInfo { - - // The packages identified in a particular archive - private List packageNames; - - private boolean isBootJar = false; - - ArchiveInfo(List packageNames, boolean isBootJar) { - this.packageNames = packageNames; - Collections.sort(this.packageNames); - this.isBootJar = isBootJar; - } - - public List getPackageNames() { - return this.packageNames; - } - - public boolean isBootJar() { - return this.isBootJar; - } - - public boolean containsPackage(String packageName, - boolean subpackageMatchesAllowed) { - if (subpackageMatchesAllowed) { - for (String candidatePackageName : this.packageNames) { - if (candidatePackageName.startsWith(packageName)) { - return true; - } - } - return false; - } - else { - // Must be an exact match, fast binary search: - int pos = Collections.binarySearch(this.packageNames, packageName); - return (pos >= 0); - } - } - - } - - private class PackageCacheBuilderVisitor extends SimpleFileVisitor { - - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) - throws IOException { - if (file.getNameCount() > 3 && file.toString().endsWith(".class")) { - int fnc = file.getNameCount(); - if (fnc > 3) { // There is a package name - e.g. - // /modules/java.base/java/lang/Object.class - Path packagePath = file.subpath(2, fnc - 1); // e.g. java/lang - String packagePathString = packagePath.toString() + "/"; - CompilationInfoCache.this.packageCache.put(packagePathString, - file.subpath(0, fnc - 1)); // java/lang - // -> - // /modules/java.base/java/lang - } - } - return FileVisitResult.CONTINUE; - } - - } - - } - - static class Key { - - private Location location; - - private String classpath; - - private String packageName; - - private Set kinds; - - private boolean recurse; - - Key(Location location, String classpath, String packageName, Set kinds, - boolean recurse) { - this.location = location; - this.classpath = classpath; - this.packageName = packageName; - this.kinds = kinds; - this.recurse = recurse; - } - - @Override - public int hashCode() { - return (((this.location.hashCode() * 37) + this.classpath.hashCode() * 37 - + (this.packageName == null ? 0 : this.packageName.hashCode())) * 37 - + this.kinds.hashCode()) * 37 + (this.recurse ? 1 : 0); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof Key)) { - return false; - } - Key that = (Key) obj; - return this.location.equals(that.location) - && this.classpath.equals(that.classpath) - && this.kinds.equals(that.kinds) && (this.recurse == that.recurse) - && (this.packageName == null ? (that.packageName == null) - : this.packageName.equals(that.packageName)); - } - - } - - static class JDKModuleLocation implements Location { - - private String moduleName; - - private Path moduleRootPath; - - JDKModuleLocation(String moduleName, Path moduleRootPath) { - this.moduleName = moduleName; - this.moduleRootPath = moduleRootPath; - } - - @Override - public String getName() { - return "MODULE"; - } - - @Override - public boolean isOutputLocation() { - return false; - } - - public String getModuleName() { - return this.moduleName; - } - - public Path getModuleRootPath() { - return this.moduleRootPath; - } - - public String toString() { - return "JDKModuleLocation(" + this.moduleName + ")"; - } - - public int hashCode() { - return this.moduleName.hashCode(); - } - - public boolean equals(Object other) { - if (!(other instanceof JDKModuleLocation)) { - return false; - } - return this.hashCode() == ((JDKModuleLocation) other).hashCode(); - } - - } - - static class ModuleIdentifierVisitor extends SimpleFileVisitor { - - private Map modules = new HashMap<>(); - - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) - throws IOException { - if (file.getNameCount() > 2 && file.toString().endsWith(".class")) { - // /modules/jdk.rmic/sun/tools/tree/CaseStatement.class - String moduleName = file.getName(1).toString(); // jdk.rmic - Path moduleRootPath = file.subpath(0, 2); // /modules/jdk.rmic - if (!this.modules.containsKey(moduleName)) { - this.modules.put(moduleName, moduleRootPath); - } - } - return FileVisitResult.CONTINUE; - } - - public Set getModuleLocations() { - if (this.modules.size() == 0) { - return Collections.emptySet(); - } - else { - Set locations = new HashSet<>(); - for (Map.Entry moduleEntry : this.modules.entrySet()) { - locations.add(new JDKModuleLocation(moduleEntry.getKey(), - moduleEntry.getValue())); - } - return locations; - } - } - - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/NestedZipEntryJavaFileObject.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/NestedZipEntryJavaFileObject.java deleted file mode 100644 index b78889dec..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/NestedZipEntryJavaFileObject.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.io.Writer; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipInputStream; - -import javax.lang.model.element.Modifier; -import javax.lang.model.element.NestingKind; -import javax.tools.JavaFileObject; - -/** - * Represents an element inside in zip which is itself inside a zip. These objects are not - * initially created with the content of the file they represent, only enough information - * to find that content because many will typically be created but only few will be - * opened. - * - * @author Andy Clement - */ -public class NestedZipEntryJavaFileObject implements JavaFileObject { - - private File outerFile; - - private ZipFile outerZipFile; - - private ZipEntry innerZipFile; - - private ZipEntry innerZipFileEntry; - - private URI uri; - - public NestedZipEntryJavaFileObject(File outerFile, ZipFile outerZipFile, - ZipEntry innerZipFile, ZipEntry innerZipFileEntry) { - this.outerFile = outerFile; - this.outerZipFile = outerZipFile; - this.innerZipFile = innerZipFile; - this.innerZipFileEntry = innerZipFileEntry; - } - - @Override - public String getName() { - return this.innerZipFileEntry.getName(); // Example: a/b/C.class - } - - @Override - public URI toUri() { - if (this.uri == null) { - String uriString = null; - try { - uriString = "zip:" + this.outerFile.getAbsolutePath() + "!" - + this.innerZipFile.getName() + "!" - + this.innerZipFileEntry.getName(); - this.uri = new URI(uriString); - } - catch (URISyntaxException e) { - throw new IllegalStateException( - "Unexpected URISyntaxException for string '" + uriString + "'", - e); - } - } - return this.uri; - } - - @Override - public InputStream openInputStream() throws IOException { - // Find the inner zip file inside the outer zip file, then - // find the relevant entry, then return the stream. - InputStream innerZipFileInputStream = this.outerZipFile - .getInputStream(this.innerZipFile); - ZipInputStream innerZipInputStream = new ZipInputStream(innerZipFileInputStream); - ZipEntry nextEntry = innerZipInputStream.getNextEntry(); - while (nextEntry != null) { - if (nextEntry.getName().equals(this.innerZipFileEntry.getName())) { - return innerZipInputStream; - } - nextEntry = innerZipInputStream.getNextEntry(); - } - throw new IllegalStateException( - "Unable to locate nested zip entry " + this.innerZipFileEntry.getName() - + " in zip " + this.innerZipFile.getName() + " inside zip " - + this.outerZipFile.getName()); - } - - @Override - public Reader openReader(boolean ignoreEncodingErrors) throws IOException { - // It is bytecode - throw new UnsupportedOperationException( - "getCharContent() not supported on class file: " + getName()); - } - - @Override - public long getLastModified() { - return this.innerZipFileEntry.getTime(); - } - - @Override - public Kind getKind() { - // The filtering before this object was created ensure it is only used for classes - return Kind.CLASS; - } - - @Override - public boolean delete() { - return false; // Cannot delete entries inside nested zips - } - - @Override - public OutputStream openOutputStream() throws IOException { - throw new IllegalStateException("cannot write to nested zip entry: " + toUri()); - } - - @Override - public Writer openWriter() throws IOException { - throw new IllegalStateException("cannot write to nested zip entry: " + toUri()); - } - - @Override - public boolean isNameCompatible(String simpleName, Kind kind) { - if (kind != Kind.CLASS) { - return false; - } - String name = getName(); - int lastSlash = name.lastIndexOf('/'); - return name.substring(lastSlash + 1).equals(simpleName + ".class"); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { - // It is bytecode - throw new UnsupportedOperationException( - "getCharContent() not supported on class file: " + getName()); - } - - @Override - public NestingKind getNestingKind() { - return null; // nesting level not known - } - - @Override - public Modifier getAccessLevel() { - return null; // access level not known - } - - @Override - public int hashCode() { - int hc = this.outerFile.getName().hashCode(); - hc = hc * 37 + this.innerZipFile.getName().hashCode(); - hc = hc * 37 + this.innerZipFileEntry.getName().hashCode(); - return hc; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof NestedZipEntryJavaFileObject)) { - return false; - } - NestedZipEntryJavaFileObject that = (NestedZipEntryJavaFileObject) obj; - return (this.outerFile.getName().equals(that.outerFile.getName())) - && (this.innerZipFile.getName().equals(that.innerZipFile.getName())) - && (this.innerZipFileEntry.getName() - .equals(that.innerZipFileEntry.getName())); - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/RuntimeJavaCompiler.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/RuntimeJavaCompiler.java deleted file mode 100644 index 699dda570..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/RuntimeJavaCompiler.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.tools.Diagnostic; -import javax.tools.Diagnostic.Kind; -import javax.tools.DiagnosticCollector; -import javax.tools.JavaCompiler; -import javax.tools.JavaCompiler.CompilationTask; -import javax.tools.JavaFileObject; -import javax.tools.ToolProvider; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Compile Java source at runtime and load it. - * - * @author Andy Clement - */ -public class RuntimeJavaCompiler { - - private static Logger logger = LoggerFactory.getLogger(RuntimeJavaCompiler.class); - - private JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); - - /** - * 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 classes. - * @param className the name of the class (dotted form, e.g. com.foo.bar.Goo) - * @param classSourceCode the full source code for the class - * @param dependencies optional coordinates for dependencies, maven - * 'maven://groupId:artifactId:version', or 'file:' URIs for local files - * @return a CompilationResult that encapsulates what happened during compilation - * (classes/messages produced) - */ - public CompilationResult compile(String className, String classSourceCode, - String... dependencies) { - logger.info("Compiling source for class {} using compiler {}", className, - this.compiler.getClass().getName()); - - DiagnosticCollector diagnosticCollector = new DiagnosticCollector(); - MemoryBasedJavaFileManager fileManager = new MemoryBasedJavaFileManager(); - List resolutionMessages = fileManager - .addAndResolveDependencies(dependencies); - JavaFileObject sourceFile = InMemoryJavaFileObject - .getSourceJavaFileObject(className, classSourceCode); - - Iterable compilationUnits = Arrays.asList(sourceFile); - List options = new ArrayList<>(); - options.add("-source"); - options.add("1.8"); - CompilationTask task = this.compiler.getTask(null, fileManager, - diagnosticCollector, options, null, compilationUnits); - - boolean success = task.call(); - CompilationResult compilationResult = new CompilationResult(success); - compilationResult.recordCompilationMessages(resolutionMessages); - compilationResult.setResolvedAdditionalDependencies(new ArrayList<>( - fileManager.getResolvedAdditionalDependencies().values())); - - // If successful there may be no errors but there might be info/warnings - for (Diagnostic diagnostic : diagnosticCollector - .getDiagnostics()) { - CompilationMessage.Kind kind = (diagnostic.getKind() == Kind.ERROR - ? CompilationMessage.Kind.ERROR : CompilationMessage.Kind.OTHER); - // String sourceCode = - // ((StringBasedJavaSourceFileObject)diagnostic.getSource()).getSourceCode(); - String sourceCode = null; - try { - sourceCode = (String) diagnostic.getSource().getCharContent(true); - } - catch (IOException ioe) { - // Unexpected, but leave sourceCode null to indicate it was not - // retrievable - } - catch (NullPointerException npe) { - // TODO: should we skip warning diagnostics in the loop altogether? - } - int startPosition = (int) diagnostic.getPosition(); - if (startPosition == Diagnostic.NOPOS) { - startPosition = (int) diagnostic.getStartPosition(); - } - CompilationMessage compilationMessage = new CompilationMessage(kind, - diagnostic.getMessage(null), sourceCode, startPosition, - (int) diagnostic.getEndPosition()); - compilationResult.recordCompilationMessage(compilationMessage); - } - if (success) { - List ccds = fileManager.getCompiledClasses(); - List> classes = new ArrayList<>(); - try (SimpleClassLoader ccl = new SimpleClassLoader( - this.getClass().getClassLoader())) { - for (CompiledClassDefinition ccd : ccds) { - Class clazz = ccl.defineClass(ccd.getClassName(), ccd.getBytes()); - classes.add(clazz); - compilationResult.addClassBytes(ccd.getClassName(), ccd.getBytes()); - } - } - catch (IOException ioe) { - logger.debug("Unexpected exception defining classes", ioe); - } - compilationResult.setCompiledClasses(classes); - } - return compilationResult; - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/SimpleClassLoader.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/SimpleClassLoader.java deleted file mode 100644 index 797e55538..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/SimpleClassLoader.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.io.File; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.List; - -/** - * Very simple classloader that can be used to load the compiled types. - * - * @author Andy Clement - */ -public class SimpleClassLoader extends URLClassLoader { - - private static final URL[] NO_URLS = new URL[0]; - - public SimpleClassLoader(ClassLoader classLoader) { - super(NO_URLS, classLoader); - } - - public SimpleClassLoader(List resolvedAdditionalDependencies, - ClassLoader classLoader) { - super(toUrls(resolvedAdditionalDependencies), classLoader); - } - - private static URL[] toUrls(List resolvedAdditionalDependencies) { - URL[] urls = new URL[resolvedAdditionalDependencies.size()]; - for (int i = 0, max = resolvedAdditionalDependencies.size(); i < max; i++) { - try { - urls[i] = resolvedAdditionalDependencies.get(i).toURI().toURL(); - } - catch (Exception e) { - throw new IllegalStateException(e); - } - } - return urls; - } - - public Class defineClass(String name, byte[] bytes) { - return super.defineClass(name, bytes, 0, bytes.length); - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/ZipEntryJavaFileObject.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/ZipEntryJavaFileObject.java deleted file mode 100644 index 306300aec..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/java/ZipEntryJavaFileObject.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.io.Writer; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -import javax.lang.model.element.Modifier; -import javax.lang.model.element.NestingKind; -import javax.tools.JavaFileObject; - -/** - * A {@link JavaFileObject} that works on a ZIP entry. - * - * @author Mark Fisher - */ -public class ZipEntryJavaFileObject implements JavaFileObject { - - private File containingFile; - - private ZipFile zf; - - private ZipEntry ze; - - private URI uri; - - public ZipEntryJavaFileObject(File containingFile, ZipFile zipFile, ZipEntry entry) { - this.containingFile = containingFile; - this.zf = zipFile; - this.ze = entry; - } - - @Override - public URI toUri() { - if (this.uri == null) { - String uriString = null; - try { - uriString = "zip:" + this.containingFile.getAbsolutePath() + "!" - + this.ze.getName(); - this.uri = new URI(uriString); - } - catch (URISyntaxException e) { - throw new IllegalStateException( - "Unexpected URISyntaxException for string '" + uriString + "'", - e); - } - } - return this.uri; - } - - @Override - public String getName() { - return this.ze.getName(); // a/b/C.class - } - - @Override - public InputStream openInputStream() throws IOException { - return this.zf.getInputStream(this.ze); - } - - @Override - public OutputStream openOutputStream() throws IOException { - throw new IllegalStateException("only expected to be used for input"); - } - - @Override - public Reader openReader(boolean ignoreEncodingErrors) throws IOException { - // It is bytecode - throw new UnsupportedOperationException( - "openReader() not supported on class file: " + getName()); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { - // It is bytecode - throw new UnsupportedOperationException( - "getCharContent() not supported on class file: " + getName()); - } - - @Override - public Writer openWriter() throws IOException { - throw new IllegalStateException("only expected to be used for input"); - } - - @Override - public long getLastModified() { - return this.ze.getTime(); - } - - @Override - public boolean delete() { - return false; // Cannot delete entries inside zips - } - - @Override - public Kind getKind() { - return Kind.CLASS; - } - - @Override - public boolean isNameCompatible(String simpleName, Kind kind) { - if (kind != Kind.CLASS) { - return false; - } - String name = getName(); - int lastSlash = name.lastIndexOf('/'); - return name.substring(lastSlash + 1).equals(simpleName + ".class"); - } - - @Override - public NestingKind getNestingKind() { - return null; - } - - @Override - public Modifier getAccessLevel() { - return null; - } - - @Override - public int hashCode() { - int hc = this.containingFile.getName().hashCode(); - hc = hc * 37 + this.ze.getName().hashCode(); - return hc; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof ZipEntryJavaFileObject)) { - return false; - } - ZipEntryJavaFileObject that = (ZipEntryJavaFileObject) obj; - return (this.containingFile.getName().equals(that.containingFile.getName())) - && (this.ze.getName().equals(that.ze.getName())); - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/AbstractByteCodeLoadingProxy.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/AbstractByteCodeLoadingProxy.java deleted file mode 100644 index 0d1b2f472..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/AbstractByteCodeLoadingProxy.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.proxy; - -import java.lang.reflect.Method; -import java.util.concurrent.atomic.AtomicReference; - -import org.springframework.asm.ClassReader; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.cloud.function.compiler.CompilationResultFactory; -import org.springframework.cloud.function.compiler.java.SimpleClassLoader; -import org.springframework.cloud.function.core.FunctionFactoryMetadata; -import org.springframework.core.io.Resource; -import org.springframework.util.FileCopyUtils; -import org.springframework.util.ReflectionUtils; - -/** - * @author Mark Fisher - * @author Oleg Zhurakousky - */ -abstract class AbstractByteCodeLoadingProxy - implements InitializingBean, FunctionFactoryMetadata { - - private final Resource resource; - - private final SimpleClassLoader classLoader = new SimpleClassLoader( - AbstractByteCodeLoadingProxy.class.getClassLoader()); - - private T target; - - private Method method; - - AbstractByteCodeLoadingProxy(Resource resource) { - this.resource = resource; - } - - @Override - @SuppressWarnings("unchecked") - public void afterPropertiesSet() throws Exception { - byte[] bytes = FileCopyUtils.copyToByteArray(this.resource.getInputStream()); - String className = new ClassReader(bytes).getClassName().replace("/", "."); - Class factoryClass = this.classLoader.defineClass(className, bytes); - try { - this.target = ((CompilationResultFactory) factoryClass.newInstance()) - .getResult(); - this.method = findFactoryMethod(factoryClass); - } - catch (InstantiationException | IllegalAccessException e) { - throw new IllegalArgumentException("failed to load Function byte code", e); - } - } - - @Override - public final T getTarget() { - return this.target; - } - - @Override - public Method getFactoryMethod() { - return this.method; - } - - private Method findFactoryMethod(Class clazz) { - AtomicReference method = new AtomicReference<>(); - ReflectionUtils.doWithLocalMethods(clazz, m -> { - if (m.getName().equals("getResult") - && m.getReturnType().getName().startsWith("java.util.function")) { - method.set(m); - } - }); - return method.get(); - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/AbstractLambdaCompilingProxy.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/AbstractLambdaCompilingProxy.java deleted file mode 100644 index 235501bc9..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/AbstractLambdaCompilingProxy.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.proxy; - -import java.io.InputStreamReader; -import java.lang.reflect.Method; - -import org.springframework.beans.factory.BeanNameAware; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.cloud.function.compiler.AbstractFunctionCompiler; -import org.springframework.cloud.function.compiler.CompiledFunctionFactory; -import org.springframework.cloud.function.core.FunctionFactoryMetadata; -import org.springframework.core.io.Resource; -import org.springframework.util.Assert; -import org.springframework.util.FileCopyUtils; - -/** - * @param target type - * @author Mark Fisher - */ -public class AbstractLambdaCompilingProxy - implements InitializingBean, BeanNameAware, FunctionFactoryMetadata { - - private final Resource resource; - - private final AbstractFunctionCompiler compiler; - - private String beanName; - - private CompiledFunctionFactory factory; - - private String[] typeParameterizations; - - public AbstractLambdaCompilingProxy(Resource resource, - AbstractFunctionCompiler compiler) { - Assert.notNull(resource, "Resource must not be null"); - Assert.notNull(compiler, "Compiler must not be null"); - this.resource = resource; - this.compiler = compiler; - } - - @Override - public void setBeanName(String beanName) { - this.beanName = beanName; - } - - public void setTypeParameterizations(String... typeParameterizations) { - this.typeParameterizations = typeParameterizations; - } - - @Override - public void afterPropertiesSet() throws Exception { - String lambda = FileCopyUtils - .copyToString(new InputStreamReader(this.resource.getInputStream())); - this.factory = this.compiler.compile(this.beanName, lambda, - this.typeParameterizations); - } - - @Override - public final T getTarget() { - return this.factory.getResult(); - } - - @Override - public Method getFactoryMethod() { - return this.factory.getFactoryMethod(); - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/ByteCodeLoadingConsumer.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/ByteCodeLoadingConsumer.java deleted file mode 100644 index da45e2e47..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/ByteCodeLoadingConsumer.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.proxy; - -import java.util.function.Consumer; - -import org.springframework.cloud.function.core.FunctionFactoryMetadata; -import org.springframework.core.io.Resource; - -/** - * @param type - * @author Mark Fisher - * @author Oleg Zhurakousky - */ -public class ByteCodeLoadingConsumer extends AbstractByteCodeLoadingProxy> - implements FunctionFactoryMetadata>, Consumer { - - public ByteCodeLoadingConsumer(Resource resource) { - super(resource); - } - - @Override - public void accept(T t) { - this.getTarget().accept(t); - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/ByteCodeLoadingFunction.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/ByteCodeLoadingFunction.java deleted file mode 100644 index 19e921c8c..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/ByteCodeLoadingFunction.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.proxy; - -import java.util.function.Function; - -import org.springframework.cloud.function.core.FunctionFactoryMetadata; -import org.springframework.core.io.Resource; - -/** - * @param Function input type - * @param Function result type - * @author Mark Fisher - * @author Oleg Zhurakousky - */ -public class ByteCodeLoadingFunction - extends AbstractByteCodeLoadingProxy> - implements FunctionFactoryMetadata>, Function { - - public ByteCodeLoadingFunction(Resource resource) { - super(resource); - } - - @Override - public R apply(T input) { - return this.getTarget().apply(input); - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/ByteCodeLoadingSupplier.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/ByteCodeLoadingSupplier.java deleted file mode 100644 index 257fab96b..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/ByteCodeLoadingSupplier.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.proxy; - -import java.util.function.Supplier; - -import org.springframework.cloud.function.core.FunctionFactoryMetadata; -import org.springframework.core.io.Resource; - -/** - * @param type - * @author Mark Fisher - * @author Oleg Zhurakousky - */ -public class ByteCodeLoadingSupplier extends AbstractByteCodeLoadingProxy> - implements FunctionFactoryMetadata>, Supplier { - - public ByteCodeLoadingSupplier(Resource resource) { - super(resource); - } - - @Override - public T get() { - return this.getTarget().get(); - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/LambdaCompilingConsumer.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/LambdaCompilingConsumer.java deleted file mode 100644 index bd8c5e16b..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/LambdaCompilingConsumer.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.proxy; - -import java.util.function.Consumer; - -import org.springframework.cloud.function.compiler.ConsumerCompiler; -import org.springframework.core.io.Resource; - -/** - * @param input argument type - * @author Mark Fisher - */ -public class LambdaCompilingConsumer extends AbstractLambdaCompilingProxy> - implements Consumer { - - public LambdaCompilingConsumer(Resource resource, ConsumerCompiler compiler) { - super(resource, compiler); - } - - @Override - public void accept(T input) { - this.getTarget().accept(input); - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/LambdaCompilingFunction.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/LambdaCompilingFunction.java deleted file mode 100644 index 92a01d21a..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/LambdaCompilingFunction.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.proxy; - -import java.util.function.Function; - -import org.springframework.cloud.function.compiler.FunctionCompiler; -import org.springframework.cloud.function.core.FunctionFactoryMetadata; -import org.springframework.core.io.Resource; - -/** - * @param input argument type - * @param output argument type - * @author Mark Fisher - */ -public class LambdaCompilingFunction - extends AbstractLambdaCompilingProxy> - implements FunctionFactoryMetadata>, Function { - - public LambdaCompilingFunction(Resource resource, FunctionCompiler compiler) { - super(resource, compiler); - } - - @Override - public R apply(T input) { - return this.getTarget().apply(input); - } - -} diff --git a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/LambdaCompilingSupplier.java b/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/LambdaCompilingSupplier.java deleted file mode 100644 index cb2db39d9..000000000 --- a/spring-cloud-function-compiler/src/main/java/org/springframework/cloud/function/compiler/proxy/LambdaCompilingSupplier.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.proxy; - -import java.util.function.Supplier; - -import org.springframework.cloud.function.compiler.SupplierCompiler; -import org.springframework.cloud.function.core.FunctionFactoryMetadata; -import org.springframework.core.io.Resource; - -/** - * @param target type - * @author Mark Fisher - */ -public class LambdaCompilingSupplier extends AbstractLambdaCompilingProxy> - implements FunctionFactoryMetadata>, Supplier { - - public LambdaCompilingSupplier(Resource resource, SupplierCompiler compiler) { - super(resource, compiler); - } - - @Override - public T get() { - return this.getTarget().get(); - } - -} diff --git a/spring-cloud-function-compiler/src/main/resources/META-INF/spring.factories b/spring-cloud-function-compiler/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 0f7f11139..000000000 --- a/spring-cloud-function-compiler/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.context.ApplicationListener=\ -org.springframework.cloud.function.compiler.config.FunctionProxyApplicationListener diff --git a/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/CompilerDependencyResolutionTests.java b/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/CompilerDependencyResolutionTests.java deleted file mode 100644 index 5480e8a9c..000000000 --- a/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/CompilerDependencyResolutionTests.java +++ /dev/null @@ -1,466 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.jar.JarEntry; -import java.util.jar.JarInputStream; -import java.util.jar.JarOutputStream; -import java.util.zip.ZipEntry; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import org.junit.jupiter.api.Test; -import org.slf4j.LoggerFactory; - -import org.springframework.cloud.function.compiler.java.CompilationResult; -import org.springframework.cloud.function.compiler.java.RuntimeJavaCompiler; -import org.springframework.cloud.function.core.FunctionFactoryUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests that verify dependency resolution. Dependencies can be resolved against simple - * classpath entries or against classes under BOOT-INF/classes or in a nested jar under - * under BOOT-INF/lib. Finding classes in those locations enables compilation against a - * packaged boot jar. - * - * @author Andy Clement - */ -public class CompilerDependencyResolutionTests { - - @Test - public void compilingTestClass() throws Exception { - ClassDescriptor t1 = compile("Test1", - "package com.test;\npublic class Test1 { public static String doit() { return \"T1\";}}\n"); - String result = (String) t1.clazz.getDeclaredMethod("doit").invoke(null); - assertThat(result).isEqualTo("T1"); - } - - @Test - public void packagingClassesIntoJar() { - ClassDescriptor t1 = getTestClass("1"); - ClassDescriptor t2 = getTestClass("2"); - File jar = JarBuilder.create().addEntries(t1, t2).getJar(); - assertJarContents(jar, t1, t2); - } - - /** - * Doesn't actually verify the caching helps but can be useful to run to see current - * numbers. - */ - @Test - public void speedtest() { - LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); - Logger rootLogger = loggerContext - .getLogger("org.springframework.cloud.function.compiler"); - rootLogger.setLevel(Level.ERROR); - - // 10 uses of a single function compiler: - long stime = System.currentTimeMillis(); - FunctionCompiler fc = new FunctionCompiler( - String.class.getName()); - for (int i = 0; i < 5; i++) { - stime = System.currentTimeMillis(); - CompiledFunctionFactory> result = fc.compile("foos", - "flux -> flux.map(v -> v.toUpperCase())", "Flux", - "Flux"); - assertThat(FunctionFactoryUtils.isFluxFunction(result.getFactoryMethod())) - .isTrue(); - System.out.println("Reusing FunctionCompiler: #" + (i + 1) + " = " - + (System.currentTimeMillis() - stime) + "ms"); - } - - // 3 separate FunctionCompilers: - stime = System.currentTimeMillis(); - CompiledFunctionFactory> compiled = new FunctionCompiler( - String.class.getName()).compile("foos", - "flux -> flux.map(v -> v.toUpperCase())", "Flux", - "Flux"); - assertThat(FunctionFactoryUtils.isFluxFunction(compiled.getFactoryMethod())) - .isTrue(); - long etime = System.currentTimeMillis(); - long time1 = (etime - stime); - System.out.println("New FunctionCompiler: " + time1 + "ms"); - - stime = System.currentTimeMillis(); - compiled = new FunctionCompiler(String.class.getName()).compile( - "foos", "flux -> flux.map(v -> v.toUpperCase())", "Flux", - "Flux"); - assertThat(FunctionFactoryUtils.isFluxFunction(compiled.getFactoryMethod())) - .isTrue(); - etime = System.currentTimeMillis(); - long time2 = (etime - stime); - System.out.println("New FunctionCompiler: " + time2 + "ms"); - - stime = System.currentTimeMillis(); - compiled = new FunctionCompiler(String.class.getName()).compile( - "foos", "flux -> flux.map(v -> v.toUpperCase())", "Flux", - "Flux"); - assertThat(FunctionFactoryUtils.isFluxFunction(compiled.getFactoryMethod())) - .isTrue(); - etime = System.currentTimeMillis(); - long time3 = (etime - stime); - System.out.println("New FunctionCompiler: " + time3 + "ms"); - } - - @Test - public void usingJarNoPackageDecl() throws Exception { - ClassDescriptor tx = compile("TestX", - "public class TestX { public static String doit() { return \"TX\";}}\n"); - File jar = JarBuilder.create().addEntry(tx).getJar(); - assertJarContents(jar, tx); - CompilationResult result = new RuntimeJavaCompiler().compile("A", - "public class A {\n" + " public static Object run() {\n" - + " return new TestX();\n" + " }\n" + "}", - jar.toURI().toString()); - assertThat(result.getCompilationMessages().isEmpty()) - .as("Should be no problems: " + result.getCompilationMessages()).isTrue(); - try (URLClassLoader cl = new TestClassLoader(tx, descriptorFromResult(result))) { - Class class1 = cl.loadClass("A"); - Object invoke = class1.getDeclaredMethod("run").invoke(null); - assertThat(invoke.getClass().getName()).isEqualTo(tx.name); - } - } - - // A class with no package declaration is placed under BOOT-INF/classes/ in a jar that - // is then used for resolution - @Test - public void usingJarNoPackageDeclBootInfClasses() throws Exception { - ClassDescriptor t1 = compile("TestX", - "public class TestX { public static String doit() { return \"TX\";}}\n"); - File jar = JarBuilder.create().addEntryWithPrefix("BOOT-INF/classes/", t1) - .getJar(); - assertJarContents(jar, "BOOT-INF/classes/", t1); - CompilationResult result = new RuntimeJavaCompiler().compile("A", - "public class A {\n" + " public static Object run() {\n" - + " return new TestX();\n" + " }\n" + "}", - jar.toURI().toString()); - assertThat(result.getCompilationMessages().isEmpty()) - .as("Should be no problems: " + result.getCompilationMessages()).isTrue(); - try (URLClassLoader cl = new TestClassLoader(t1, descriptorFromResult(result))) { - Class class1 = cl.loadClass("A"); - Object invoke = class1.getDeclaredMethod("run").invoke(null); - assertThat(invoke.getClass().getName()).isEqualTo(t1.name); - } - } - - // A class with no package declaration is placed in a jar which is then placed under - // under BOOT-INF/lib/ in a jar that is then used for resolution - @Test - public void usingJarNoPackageDeclNestedBootInfLib() throws Exception { - ClassDescriptor t1 = compile("TestX", - "public class TestX { public static String doit() { return \"TX\";}}\n"); - File jar = JarBuilder.create().addEntry(t1).getJar(); - assertJarContents(jar, t1); - // Now stick that jar in another jar! - File jar2 = JarBuilder.create().addEntry("BOOT-INF/lib/inner.jar", jar).getJar(); - CompilationResult result = new RuntimeJavaCompiler().compile("A", - "public class A {\n" + " public static Object run() {\n" - + " return new TestX();\n" + " }\n" + "}", - jar2.toURI().toString()); - assertThat(result.getCompilationMessages().isEmpty()) - .as("Should be no problems: " + result.getCompilationMessages()).isTrue(); - try (URLClassLoader cl = new TestClassLoader(t1, descriptorFromResult(result))) { - Class class1 = cl.loadClass("A"); - Object invoke = class1.getDeclaredMethod("run").invoke(null); - assertThat(invoke.getClass().getName()).isEqualTo(t1.name); - } - } - - // Build a jar containing a type with a package declaration and building against it - @Test - public void usingJarWithPackageDecl() throws Exception { - ClassDescriptor t1 = getTestClass("1"); - File jar = JarBuilder.create().addEntry(t1).getJar(); - assertJarContents(jar, t1); - CompilationResult result = new RuntimeJavaCompiler().compile("A", - "import " + t1.name.replace('$', '.') + ";\n" + "public class A {\n" - + " public static Object run() {\n" + " return new Test1();\n" - + " }\n" + "}", - jar.toURI().toString()); - assertThat(result.getCompilationMessages().isEmpty()) - .as("Should be no problems: " + result.getCompilationMessages()).isTrue(); - try (URLClassLoader cl = new TestClassLoader(t1, descriptorFromResult(result))) { - Class class1 = cl.loadClass("A"); - Object invoke = class1.getDeclaredMethod("run").invoke(null); - assertThat(invoke.getClass().getName()).isEqualTo(t1.name); - } - } - - @Test - public void usingJarWithPackageDeclBootInfClasses() throws Exception { - // Here the dependencies are under BOOT-INF/classes in the jar - ClassDescriptor t1 = getTestClass("1"); - File jar = JarBuilder.create().addEntryWithPrefix("BOOT-INF/classes/", t1) - .getJar(); - assertJarContents(jar, "BOOT-INF/classes/", t1); - CompilationResult result = new RuntimeJavaCompiler().compile("A", - "import " + t1.name.replace('$', '.') + ";\n" + "public class A {\n" - + " public static Object run() {\n" + " return new Test1();\n" - + " }\n" + "}", - jar.toURI().toString()); - assertThat(result.getCompilationMessages().isEmpty()) - .as("Should be no problems: " + result.getCompilationMessages()).isTrue(); - try (URLClassLoader cl = new TestClassLoader(t1, descriptorFromResult(result))) { - Class class1 = cl.loadClass("A"); - Object invoke = class1.getDeclaredMethod("run").invoke(null); - assertThat(invoke.getClass().getName()).isEqualTo(t1.name); - } - } - - @Test - public void usingJarWithPackageDeclNestedBootInfLib() throws Exception { - // Here the dependencies are under BOOT-INF/lib/nested.jar - ClassDescriptor t1 = getTestClass("1"); - File jar = JarBuilder.create().addEntry(t1).getJar(); - assertJarContents(jar, t1); - // Now stick that jar in another jar! - File jar2 = JarBuilder.create().addEntry("BOOT-INF/lib/inner.jar", jar).getJar(); - CompilationResult result = new RuntimeJavaCompiler().compile("A", - "import " + t1.name.replace('$', '.') + ";\n" + "public class A {\n" - + " public static Object run() {\n" + " return new Test1();\n" - + " }\n" + "}", - jar2.toURI().toString()); - assertThat(result.getCompilationMessages().isEmpty()) - .as("Should be no problems: " + result.getCompilationMessages()).isTrue(); - try (URLClassLoader cl = new TestClassLoader(t1, descriptorFromResult(result))) { - Class class1 = cl.loadClass("A"); - Object invoke = class1.getDeclaredMethod("run").invoke(null); - assertThat(invoke.getClass().getName()).isEqualTo(t1.name); - } - } - - // --- - - private ClassDescriptor descriptorFromResult(CompilationResult result) { - Class clazz = result.getCompiledClasses().get(0); - return new ClassDescriptor(clazz.getName(), result.getClassBytes(clazz.getName()), - clazz); - } - - private ClassDescriptor compile(String className, String classSourceCode) { - CompilationResult compile = new RuntimeJavaCompiler().compile(className, - classSourceCode); - assertThat(compile.getCompilationMessages().isEmpty()) - .as("Should be empty: \n" + compile.getCompilationMessages()).isTrue(); - Class clazz = compile.getCompiledClasses().get(0); - return new ClassDescriptor(clazz.getName(), - compile.getClassBytes(clazz.getName()), - compile.getCompiledClasses().get(0)); - } - - private ClassDescriptor getTestClass(String suffix) { - try { - return compile("Test" + suffix, - "package com.test;\npublic class Test" + suffix - + " { public static String doit() { return \"T" + suffix - + "\";}}\n"); - } - catch (Exception e) { - throw new IllegalStateException(e); - } - } - - private void assertJarContents(File jar, ClassDescriptor... classdescriptors) { - assertJarContents(jar, "", classdescriptors); - } - - private void assertJarContents(File jar, String prefix, - ClassDescriptor... classDescriptors) { - List clazzes = new ArrayList<>(); - for (ClassDescriptor classDescriptor : classDescriptors) { - clazzes.add(prefix + classDescriptor.name.replace('.', '/') + ".class"); - } - walkJar(jar, (entry) -> clazzes.remove(entry.getName())); - assertThat(clazzes.isEmpty()).as("Should be empty: " + clazzes).isTrue(); - } - - private void walkJar(File jar, Consumer fn) { - try { - JarInputStream jarInputStream = new JarInputStream(new FileInputStream(jar)); - while (true) { - JarEntry nextJarEntry = jarInputStream.getNextJarEntry(); - if (nextJarEntry == null) { - break; - } - fn.accept(nextJarEntry); - } - jarInputStream.close(); - } - catch (IOException ioe) { - ioe.printStackTrace(); - } - } - - @SuppressWarnings("unused") - private void printJar(File jar) { - System.out.println("Contents of jar: " + jar); - walkJar(jar, (entry) -> { - System.out.println("- " + entry.getName()); - }); - } - - // Simple holder for the result of compilation - static class ClassDescriptor { - - final String name; - - final byte[] bytes; - - final Class clazz; - - ClassDescriptor(String name, byte[] bytes, Class clazz) { - this.name = name; - this.bytes = bytes; - this.clazz = clazz; - } - - } - - static final class JarBuilder { - - File jarFile; - - JarOutputStream jos; - - private JarBuilder() { - try { - File newJar = File.createTempFile("test", ".jar"); - this.jarFile = newJar.getAbsoluteFile(); - newJar.delete(); - this.jos = new JarOutputStream(new FileOutputStream(this.jarFile)); - this.jarFile.deleteOnExit(); - } - catch (IOException e) { - throw new IllegalStateException("Unexpected problem creating file", e); - } - } - - public static JarBuilder create() { - return new JarBuilder(); - } - - public JarBuilder addEntry(String entryName, File entryContentFile) { - try { - ZipEntry ze = new ZipEntry(entryName); - this.jos.putNextEntry(ze); - this.jos.write(loadBytes(entryContentFile)); - this.jos.closeEntry(); - return this; - } - catch (IOException e) { - throw new IllegalStateException(e); - } - } - - private byte[] loadBytes(File f) { - try (InputStream is = new FileInputStream(f)) { - byte[] bs = null; - byte[] buf = new byte[10000]; - int readCount; - while ((readCount = is.read(buf)) != -1) { - if (bs == null) { - bs = new byte[readCount]; - System.arraycopy(buf, 0, bs, 0, readCount); - } - else { - byte[] newbs = new byte[bs.length + readCount]; - System.arraycopy(bs, 0, newbs, 0, bs.length); - System.arraycopy(buf, 0, newbs, bs.length, readCount); - bs = newbs; - } - } - return bs; - } - catch (IOException ioe) { - throw new IllegalStateException(ioe); - } - } - - public JarBuilder addEntries(ClassDescriptor... classes) { - for (ClassDescriptor clazz : classes) { - addEntry(clazz); - } - return this; - } - - public JarBuilder addEntry(ClassDescriptor clazz) { - return addEntryWithPrefix("", clazz); - } - - public JarBuilder addEntryWithPrefix(String prefix, ClassDescriptor holder) { - try { - String n = holder.name.replace('.', '/') + ".class"; - ZipEntry ze = new ZipEntry(prefix + n); - this.jos.putNextEntry(ze); - this.jos.write(holder.bytes); - this.jos.closeEntry(); - return this; - } - catch (IOException e) { - throw new IllegalStateException(e); - } - } - - private File getJar() { - try { - this.jos.close(); - } - catch (IOException e) { - throw new IllegalStateException("Unable to close jar", e); - } - return this.jarFile; - } - - } - - // Simple classloader that can load from descriptors - class TestClassLoader extends URLClassLoader { - - ClassDescriptor[] descriptors; - - TestClassLoader(ClassDescriptor... descriptors) { - super(new URL[0], TestClassLoader.class.getClassLoader()); - this.descriptors = descriptors; - } - - @Override - protected Class findClass(String name) throws ClassNotFoundException { - for (ClassDescriptor descriptor : this.descriptors) { - if (descriptor.name.equals(name)) { - return defineClass(descriptor.name, descriptor.bytes, 0, - descriptor.bytes.length); - } - } - return super.findClass(name); - } - - } - -} diff --git a/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/ConsumerCompilerTests.java b/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/ConsumerCompilerTests.java deleted file mode 100644 index 962823b13..000000000 --- a/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/ConsumerCompilerTests.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler; - -import java.util.function.Consumer; - -import org.junit.jupiter.api.Test; - -import org.springframework.cloud.function.core.FunctionFactoryUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * - */ -public class ConsumerCompilerTests { - - @Test - public void consumesFluxString() { - CompiledFunctionFactory> compiled = new ConsumerCompiler( - String.class.getName()).compile("foos", - "flux -> flux.subscribe(System.out::println)", "Flux"); - assertThat(FunctionFactoryUtils.isFluxConsumer(compiled.getFactoryMethod())) - .isTrue(); - } - - @Test - public void consumesString() { - CompiledFunctionFactory> compiled = new ConsumerCompiler( - String.class.getName()).compile("foos", "System.out::println", "String"); - assertThat(FunctionFactoryUtils.isFluxConsumer(compiled.getFactoryMethod())) - .isFalse(); - } - -} diff --git a/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/FunctionCompilerTests.java b/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/FunctionCompilerTests.java deleted file mode 100644 index 0a00deffc..000000000 --- a/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/FunctionCompilerTests.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler; - -import java.util.function.Function; - -import org.junit.jupiter.api.Test; - -import org.springframework.cloud.function.core.FunctionFactoryUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * - */ -public class FunctionCompilerTests { - - @Test - public void transformsFluxString() { - CompiledFunctionFactory> compiled = new FunctionCompiler( - String.class.getName()).compile("foos", - "flux -> flux.map(v -> v.toUpperCase())", "Flux", - "Flux"); - assertThat(FunctionFactoryUtils.isFluxFunction(compiled.getFactoryMethod())) - .isTrue(); - } - - @Test - public void transformsString() { - CompiledFunctionFactory> compiled = new FunctionCompiler( - String.class.getName()).compile("foos", "v -> v.toUpperCase()", "String", - "String"); - assertThat(FunctionFactoryUtils.isFluxFunction(compiled.getFactoryMethod())) - .isFalse(); - assertThat(compiled.getResult().apply("hello")).isEqualTo("HELLO"); - } - -} diff --git a/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/SupplierCompilerTests.java b/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/SupplierCompilerTests.java deleted file mode 100644 index fa2a0a225..000000000 --- a/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/SupplierCompilerTests.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler; - -import java.util.function.Supplier; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import org.springframework.cloud.function.core.FunctionFactoryUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * - */ -public class SupplierCompilerTests { - - @Test - public void supppliesFluxString() { - CompiledFunctionFactory> compiled = new SupplierCompiler( - String.class.getName()).compile("foos", - "() -> Flux.just(\"foo\", \"bar\")", "Flux"); - assertThat(FunctionFactoryUtils.isFluxSupplier(compiled.getFactoryMethod())) - .isTrue(); - } - - @Test - public void supppliesString() { - CompiledFunctionFactory> compiled = new SupplierCompiler( - String.class.getName()).compile("foos", "() -> \"foo\"", "String"); - assertThat(FunctionFactoryUtils.isFluxSupplier(compiled.getFactoryMethod())) - .isFalse(); - assertThat(compiled.getResult().get()).isEqualTo("foo"); - } - - @Test - public void supppliesFluxStreamString() { - CompiledFunctionFactory>> compiled = new SupplierCompiler>( - String.class.getName()).compile("foos", - "() -> Flux.interval(Duration.ofMillis(1000)).map(Object::toString)", - "Flux"); - assertThat(FunctionFactoryUtils.isFluxSupplier(compiled.getFactoryMethod())) - .isTrue(); - assertThat(compiled.getResult().get().blockFirst()).isEqualTo("0"); - } - -} diff --git a/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/java/RuntimeJavaCompilerTests.java b/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/java/RuntimeJavaCompilerTests.java deleted file mode 100644 index 10ec123eb..000000000 --- a/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/java/RuntimeJavaCompilerTests.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.java; - -import java.io.File; -import java.util.List; -import java.util.Locale; -import java.util.function.Supplier; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Andy Clement - */ -@SuppressWarnings("unchecked") -public class RuntimeJavaCompilerTests { - - @Test - public void basicCompilation() { - RuntimeJavaCompiler rjc = new RuntimeJavaCompiler(); - CompilationResult cr = rjc.compile("A", "public class A {}"); - List compilationMessages = cr.getCompilationMessages(); - assertThat(compilationMessages.isEmpty()).isTrue(); - } - - @Test - public void missingType() throws Exception { - Locale.setDefault(Locale.ENGLISH); - RuntimeJavaCompiler rjc = new RuntimeJavaCompiler(); - CompilationResult cr = rjc.compile("A", - "public class A implements java.util.function.Supplier { " - + " public String get() {\n" - + " ExpressionParser parser = new SpelExpressionParser();\n" - + " Expression exp = parser.parseExpression(\"'Hello World'\");\n" - + " String message = (String) exp.getValue();" - + " return message;\n" + " }\n" + "}"); - List compilationMessages = cr.getCompilationMessages(); - assertThat(compilationMessages.size()).isEqualTo(3); - assertThat(compilationMessages.get(0).getMessage().contains("cannot find symbol")) - .isTrue(); - assertThat(compilationMessages.get(0).getMessage() - .contains("class ExpressionParser")).isTrue(); - assertThat(compilationMessages.get(1).getMessage().contains("cannot find symbol")) - .isTrue(); - assertThat(compilationMessages.get(1).getMessage() - .contains("class SpelExpressionParser")).isTrue(); - assertThat(compilationMessages.get(2).getMessage().contains("cannot find symbol")) - .isTrue(); - assertThat(compilationMessages.get(2).getMessage().contains("class Expression")) - .isTrue(); - } - - @Test - public void okWithImportedDependencies() throws Exception { - RuntimeJavaCompiler rjc = new RuntimeJavaCompiler(); - CompilationResult cr = rjc.compile("A", - "import org.springframework.expression.*;\n" - + "import org.springframework.expression.spel.standard.*;\n" - + "public class A implements java.util.function.Supplier {\n" - + " public String get() {\n" - + " ExpressionParser parser = new SpelExpressionParser();\n" - + " Expression exp = parser.parseExpression(\"'Hello World'\");\n" - + " String message = (String) exp.getValue();\n" - + " return message;\n" + " }\n" + "}", - "maven://org.springframework:spring-expression:4.3.9.RELEASE"); - List compilationMessages = cr.getCompilationMessages(); - assertThat(compilationMessages.isEmpty()).isTrue(); - try (SimpleClassLoader cl = new SimpleClassLoader( - this.getClass().getClassLoader())) { - Class clazz = cl.defineClass("A", cr.getClassBytes("A")); - Supplier supplier = (Supplier) clazz.newInstance(); - assertThat(supplier.get()).isEqualTo("Hello World"); - } - } - - @Test - public void okWithImportedDependencies2() throws Exception { - RuntimeJavaCompiler rjc = new RuntimeJavaCompiler(); - String source = "import org.joda.time.*;\n" - + "public class A implements java.util.function.Supplier {\n" - + " public String get() {\n" + " DateTime dt = new DateTime();\n" - + " int month = dt.getMonthOfYear();\n" - + " return String.valueOf(month>0);\n" + " }\n" + "}"; - CompilationResult cr = rjc.compile("A", source, - "maven://joda-time:joda-time:2.9.9"); - List compilationMessages = cr.getCompilationMessages(); - assertThat(compilationMessages.isEmpty()).isTrue(); - List resolvedAdditionalDependencies = cr - .getResolvedAdditionalDependencies(); - try (SimpleClassLoader cl = new SimpleClassLoader(resolvedAdditionalDependencies, - this.getClass().getClassLoader())) { - Class clazz = cl.defineClass("A", cr.getClassBytes("A")); - Supplier supplier = (Supplier) clazz.newInstance(); - assertThat(supplier.get()).isEqualTo("true"); - } - - cr = rjc.compile("A", source, - "maven://org.springframework:spring-expression:4.3.9.RELEASE", - "maven://joda-time:joda-time:2.9.9"); - compilationMessages = cr.getCompilationMessages(); - assertThat(compilationMessages.isEmpty()).isTrue(); - resolvedAdditionalDependencies = cr.getResolvedAdditionalDependencies(); - try (SimpleClassLoader cl = new SimpleClassLoader(resolvedAdditionalDependencies, - this.getClass().getClassLoader())) { - Class clazz = cl.defineClass("A", cr.getClassBytes("A")); - Supplier supplier = (Supplier) clazz.newInstance(); - assertThat(supplier.get()).isEqualTo("true"); - } - } - - @Test - public void dependencyResolution() throws Exception { - // Failure: - RuntimeJavaCompiler rjc = new RuntimeJavaCompiler(); - CompilationResult cr = rjc.compile("A", "public class A {}", - "maven://org.springframework:spring-expression2:4.3.9.RELEASE"); // extra - // '2' - // in - // there - List compilationMessages = cr.getCompilationMessages(); - assertThat(compilationMessages.size()).isEqualTo(1); - // ERROR:org.eclipse.aether.resolution.ArtifactResolutionException: Could not find - // artifact org.springframework:spring-expression2:jar:4.3.9.RELEASE in - // spring-snapshots (https://repo.spring.io/libs-snapshot) - assertThat(compilationMessages.get(0).getMessage().contains( - "Could not find artifact org.springframework:spring-expression2:jar:4.3.9.RELEASE")) - .isTrue(); - - // Failure: - rjc = new RuntimeJavaCompiler(); - cr = rjc.compile("A", "public class A {}", - "trouble://org.springframework:spring-expression:4.3.9.RELEASE"); // rogue - // prefix - // (should - // be - // "maven:") - compilationMessages = cr.getCompilationMessages(); - assertThat(compilationMessages.size()).isEqualTo(1); - assertThat(compilationMessages.get(0).getMessage() - .contains("Unrecognized dependency: ")) - .as(compilationMessages.get(0).toString()).isTrue(); - - // Success - rjc = new RuntimeJavaCompiler(); - cr = rjc.compile("A", "public class A {}", "maven://joda-time:joda-time:2.9.9"); - compilationMessages = cr.getCompilationMessages(); - assertThat(compilationMessages.size()).isEqualTo(0); - List resolvedAdditionalDependencies = cr - .getResolvedAdditionalDependencies(); - assertThat(resolvedAdditionalDependencies.size()).isEqualTo(1); - assertThat(resolvedAdditionalDependencies.get(0).toString() - .endsWith("joda-time-2.9.9.jar")) - .as("Expected this to end with 'joda-time-2.9.9.jar': " - + resolvedAdditionalDependencies.get(0).toString()) - .isTrue(); - } - -} diff --git a/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/proxy/ByteCodeLoadingFunctionTests.java b/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/proxy/ByteCodeLoadingFunctionTests.java deleted file mode 100644 index 47d86b89f..000000000 --- a/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/compiler/proxy/ByteCodeLoadingFunctionTests.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.compiler.proxy; - -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; - -import org.springframework.cloud.function.compiler.CompiledFunctionFactory; -import org.springframework.cloud.function.compiler.ConsumerCompiler; -import org.springframework.cloud.function.compiler.FunctionCompiler; -import org.springframework.cloud.function.compiler.SupplierCompiler; -import org.springframework.cloud.function.core.FunctionFactoryMetadata; -import org.springframework.cloud.function.core.FunctionFactoryUtils; -import org.springframework.core.io.ByteArrayResource; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - */ -public class ByteCodeLoadingFunctionTests { - - @Test - public void compileConsumer() throws Exception { - CompiledFunctionFactory> compiled = new ConsumerCompiler( - String.class.getName()).compile("foos", "System.out::println", "String"); - ByteArrayResource resource = new ByteArrayResource( - compiled.getGeneratedClassBytes(), "foos"); - ByteCodeLoadingConsumer consumer = new ByteCodeLoadingConsumer<>( - resource); - consumer.afterPropertiesSet(); - assertThat(consumer instanceof FunctionFactoryMetadata); - assertThat(FunctionFactoryUtils.isFluxConsumer(consumer.getFactoryMethod())) - .isFalse(); - consumer.accept("foo"); - } - - @Test - public void compileSupplier() throws Exception { - CompiledFunctionFactory> compiled = new SupplierCompiler( - String.class.getName()).compile("foos", "() -> \"foo\"", "String"); - ByteArrayResource resource = new ByteArrayResource( - compiled.getGeneratedClassBytes(), "foos"); - ByteCodeLoadingSupplier supplier = new ByteCodeLoadingSupplier<>( - resource); - supplier.afterPropertiesSet(); - assertThat(supplier instanceof FunctionFactoryMetadata); - assertThat(FunctionFactoryUtils.isFluxSupplier(supplier.getFactoryMethod())) - .isFalse(); - assertThat(supplier.get()).isEqualTo("foo"); - } - - @Test - public void compileFunction() throws Exception { - CompiledFunctionFactory> compiled = new FunctionCompiler( - String.class.getName()).compile("foos", "v -> v.toUpperCase()", "String", - "String"); - ByteArrayResource resource = new ByteArrayResource( - compiled.getGeneratedClassBytes(), "foos"); - ByteCodeLoadingFunction function = new ByteCodeLoadingFunction<>( - resource); - function.afterPropertiesSet(); - assertThat(function instanceof FunctionFactoryMetadata); - assertThat(FunctionFactoryUtils.isFluxFunction(function.getFactoryMethod())) - .isFalse(); - assertThat(function.apply("foo")).isEqualTo("FOO"); - } - - @Test - public void compileFluxFunction() throws Exception { - CompiledFunctionFactory, Flux>> compiled = null; - compiled = new FunctionCompiler, Flux>( - String.class.getName()).compile("foos", - "flux -> flux.map(v -> v.toUpperCase())", "Flux", - "Flux"); - ByteArrayResource resource = new ByteArrayResource( - compiled.getGeneratedClassBytes(), "foos"); - ByteCodeLoadingFunction, Flux> function = new ByteCodeLoadingFunction<>( - resource); - function.afterPropertiesSet(); - assertThat(function instanceof FunctionFactoryMetadata); - assertThat(FunctionFactoryUtils.isFluxFunction(function.getFactoryMethod())) - .isTrue(); - assertThat(function.apply(Flux.just("foo")).blockFirst()).isEqualTo("FOO"); - } - -} diff --git a/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/core/FunctionFactoryUtils.java b/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/core/FunctionFactoryUtils.java deleted file mode 100644 index 41465e4a1..000000000 --- a/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/core/FunctionFactoryUtils.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.core; - -import java.lang.invoke.SerializedLambda; -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; - -import org.springframework.util.ObjectUtils; -import org.springframework.util.ReflectionUtils; - -/** - *

- * Miscellaneous utility operations to interrogate functional components (beans) - * configured in BeanFactory. - *

- *

- * It is important to understand that it is not a general purpose utility to interrogate - * "any" functional component. Certain operations may/will not work as expected due to - * java type erasure. While BeanFactory is not the requirement, this utility is targeting - * only the components defined in such way where they could be configured beans within - * BeanFactory. - *

- * It is primarily used internally by the framework. - * - * @author Mark Fisher - * @author Oleg Zhurakousky - */ -public abstract class FunctionFactoryUtils { - - private static final String FLUX_CLASS_NAME = Flux.class.getName(); - - private static final String PUBLISHER_CLASS_NAME = Publisher.class.getName(); - - private FunctionFactoryUtils() { - } - - public static boolean isFluxConsumer(Consumer consumer) { - return consumer instanceof FunctionFactoryMetadata - ? isFluxConsumer( - ((FunctionFactoryMetadata) consumer).getFactoryMethod()) - : isFlux(1, getParameterizedTypeNames(consumer, Consumer.class)); - } - - public static boolean isFluxConsumer(Method method) { - return isFlux(1, getParameterizedTypeNamesForMethod(method, Consumer.class)); - } - - public static boolean isFluxSupplier(Supplier supplier) { - return supplier instanceof FunctionFactoryMetadata - ? isFluxSupplier( - ((FunctionFactoryMetadata) supplier).getFactoryMethod()) - : isFlux(1, getParameterizedTypeNames(supplier, Supplier.class)); - } - - public static boolean isFluxSupplier(Method method) { - return isFlux(1, getParameterizedTypeNamesForMethod(method, Supplier.class)); - } - - public static boolean isFluxFunction(Function function) { - return function instanceof FunctionFactoryMetadata - ? isFluxFunction( - ((FunctionFactoryMetadata) function).getFactoryMethod()) - : isFlux(1, getParameterizedTypeNames(function, Function.class)); - } - - public static boolean isFluxFunction(Method method) { - return isFlux(2, getParameterizedTypeNamesForMethod(method, Function.class)); - } - - private static String[] getParameterizedTypeNamesForMethod(Method method, - Class interfaceClass) { - String[] types = retrieveTypes(method.getGenericReturnType(), interfaceClass); - return types == null ? new String[0] : types; - } - - private static String[] getParameterizedTypeNames(Object source, - Class interfaceClass) { - return Stream.of(source.getClass().getGenericInterfaces()) - .map(gi -> retrieveTypes(gi, interfaceClass)).filter(s -> s != null) - .findFirst().orElse(getSerializedLambdaParameterizedTypeNames(source)); - } - - private static String[] retrieveTypes(Type genericInterface, - Class interfaceClass) { - if ((genericInterface instanceof ParameterizedType) && interfaceClass - .getTypeName().equals(((ParameterizedType) genericInterface).getRawType() - .getTypeName())) { - ParameterizedType type = (ParameterizedType) genericInterface; - Type[] args = type.getActualTypeArguments(); - if (args != null) { - return Stream.of(args).map(arg -> arg.getTypeName()) - .toArray(String[]::new); - } - } - return null; - } - - private static String[] getSerializedLambdaParameterizedTypeNames(Object source) { - Method method = ReflectionUtils.findMethod(source.getClass(), "writeReplace"); - if (method == null) { - return null; - } - ReflectionUtils.makeAccessible(method); - SerializedLambda serializedLambda = (SerializedLambda) ReflectionUtils - .invokeMethod(method, source); - String signature = serializedLambda.getImplMethodSignature().replaceAll("[()]", - ""); - - List typeNames = Stream.of(signature.split(";")) - .map(t -> t.substring(1).replace('/', '.')).collect(Collectors.toList()); - - return typeNames.toArray(new String[typeNames.size()]); - } - - private static boolean isFlux(int length, String... types) { - return !ObjectUtils.isEmpty(types) && types.length == length - && Stream.of(types).allMatch(type -> type.startsWith(FLUX_CLASS_NAME) - || type.startsWith(PUBLISHER_CLASS_NAME)); - } - -} diff --git a/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/core/FunctionFactoryUtilsTests.java b/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/core/FunctionFactoryUtilsTests.java deleted file mode 100644 index 2331285f8..000000000 --- a/spring-cloud-function-compiler/src/test/java/org/springframework/cloud/function/core/FunctionFactoryUtilsTests.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.function.core; - -import java.lang.reflect.Method; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import org.junit.jupiter.api.Test; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; - -import org.springframework.util.ReflectionUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Dave Syer - * - */ -public class FunctionFactoryUtilsTests { - - @Test - public void isFluxConsumer() { - Method method = ReflectionUtils.findMethod(FunctionFactoryUtilsTests.class, - "fluxConsumer"); - assertThat(FunctionFactoryUtils.isFluxConsumer(method)).isTrue(); - assertThat(FunctionFactoryUtils.isFluxSupplier(method)).isFalse(); - assertThat(FunctionFactoryUtils.isFluxFunction(method)).isFalse(); - } - - @Test - public void isFluxSupplier() { - Method method = ReflectionUtils.findMethod(FunctionFactoryUtilsTests.class, - "fluxSupplier"); - assertThat(FunctionFactoryUtils.isFluxSupplier(method)).isTrue(); - assertThat(FunctionFactoryUtils.isFluxConsumer(method)).isFalse(); - assertThat(FunctionFactoryUtils.isFluxFunction(method)).isFalse(); - } - - @Test - public void isFluxFunction() { - Method method = ReflectionUtils.findMethod(FunctionFactoryUtilsTests.class, - "fluxFunction"); - assertThat(FunctionFactoryUtils.isFluxFunction(method)).isTrue(); - assertThat(FunctionFactoryUtils.isFluxSupplier(method)).isFalse(); - assertThat(FunctionFactoryUtils.isFluxConsumer(method)).isFalse(); - } - - @Test - public void isReactiveFunction() { - Method method = ReflectionUtils.findMethod(FunctionFactoryUtilsTests.class, - "reactiveFunction"); - assertThat(FunctionFactoryUtils.isFluxFunction(method)).isTrue(); - assertThat(FunctionFactoryUtils.isFluxSupplier(method)).isFalse(); - assertThat(FunctionFactoryUtils.isFluxConsumer(method)).isFalse(); - } - - public Function, Flux> fluxFunction() { - return foos -> foos.map(foo -> new Foo()); - } - - public Function, Publisher> reactiveFunction() { - return foos -> Flux.from(foos).map(foo -> new Foo()); - } - - public Supplier> fluxSupplier() { - return () -> Flux.just(new Foo()); - } - - public Consumer> fluxConsumer() { - return flux -> flux.subscribe(System.out::println); - } - - class Foo { - - } - -} diff --git a/spring-cloud-function-compiler/src/test/resources/logback.xml b/spring-cloud-function-compiler/src/test/resources/logback.xml deleted file mode 100644 index 7d0a9651e..000000000 --- a/spring-cloud-function-compiler/src/test/resources/logback.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/spring-cloud-function-samples/function-sample-compiler/.jdk8 b/spring-cloud-function-samples/function-sample-compiler/.jdk8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-function-samples/function-sample-compiler/build.gradle b/spring-cloud-function-samples/function-sample-compiler/build.gradle deleted file mode 100644 index ee3becec8..000000000 --- a/spring-cloud-function-samples/function-sample-compiler/build.gradle +++ /dev/null @@ -1,51 +0,0 @@ -buildscript { - ext { - springBootVersion = '1.5.12.RELEASE' - wrapperVersion = '1.0.11.RELEASE' - } - repositories { - mavenLocal() - mavenCentral() - maven { url "https://repo.spring.io/plugins-snapshot" } - maven { url "https://repo.spring.io/plugins-milestone" } - } - dependencies { - classpath("org.springframework.boot.experimental:spring-boot-thin-gradle-plugin:${wrapperVersion}") - classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") - } -} - -apply plugin: 'java' -apply plugin: 'maven' -apply plugin: 'eclipse' -apply plugin: 'spring-boot' -apply plugin: 'org.springframework.boot.experimental.thin-launcher' - -group = 'io.spring.sample' -version = '2.0.0.RELEASE' -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - -repositories { - mavenLocal() - mavenCentral() - maven { url "https://repo.spring.io/snapshot" } - maven { url "https://repo.spring.io/milestone" } -} - -ext { - springCloudFunctionVersion = "2.0.0.BUILD-SNAPSHOT" -} -ext['reactor.version'] = "3.1.7.RELEASE" - -dependencyManagement { - imports { - mavenBom "org.springframework.cloud:spring-cloud-function-dependencies:${springCloudFunctionVersion}" - } -} - -dependencies { - compile('org.springframework.cloud:spring-cloud-starter-function-web') - compile('org.springframework.cloud:spring-cloud-function-compiler') - testCompile('org.springframework.boot:spring-boot-starter-test') -} diff --git a/spring-cloud-function-samples/function-sample-compiler/gradle/wrapper/gradle-wrapper.jar b/spring-cloud-function-samples/function-sample-compiler/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index ca78035ef0501d802d4fc55381ef2d5c3ce0ec6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53556 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�H$uJM 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 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/spring-cloud-function-samples/function-sample-compiler/gradlew.bat b/spring-cloud-function-samples/function-sample-compiler/gradlew.bat deleted file mode 100644 index f6d5974e7..000000000 --- a/spring-cloud-function-samples/function-sample-compiler/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/spring-cloud-function-samples/function-sample-compiler/src/main/java/com/example/SampleApplication.java b/spring-cloud-function-samples/function-sample-compiler/src/main/java/com/example/SampleApplication.java deleted file mode 100644 index d66601624..000000000 --- a/spring-cloud-function-samples/function-sample-compiler/src/main/java/com/example/SampleApplication.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.example; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -// @checkstyle:off -@SpringBootApplication -public class SampleApplication { - - public static void main(String[] args) throws Exception { - SpringApplication.run(SampleApplication.class, args); - } - -} -// @checkstyle:on diff --git a/spring-cloud-function-samples/function-sample-compiler/src/test/java/com/example/SampleCompiledConsumerTests.java b/spring-cloud-function-samples/function-sample-compiler/src/test/java/com/example/SampleCompiledConsumerTests.java deleted file mode 100644 index 7b007aa79..000000000 --- a/spring-cloud-function-samples/function-sample-compiler/src/test/java/com/example/SampleCompiledConsumerTests.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.example; - -import org.junit.jupiter.api.Test; - -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Mark Fisher - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { - "spring.cloud.function.compile.test.lambda=com.example.SampleCompiledConsumerTests.Reference::set", - "spring.cloud.function.compile.test.inputType=String", - "spring.cloud.function.compile.test.type=consumer"}) -public class SampleCompiledConsumerTests { - - @LocalServerPort - private int port; - - @Test - public void print() { - assertThat(new TestRestTemplate().postForObject( - "http://localhost:" + this.port + "/test", "it works", String.class)) - .isNull(); - assertThat(Reference.instance).isEqualTo("it works"); - } - - public static class Reference { - - private static Object instance; - - public static void set(Object o) { - instance = o; - } - - } - -} diff --git a/spring-cloud-function-samples/function-sample-compiler/src/test/java/com/example/SampleCompiledFunctionTests.java b/spring-cloud-function-samples/function-sample-compiler/src/test/java/com/example/SampleCompiledFunctionTests.java deleted file mode 100644 index 9f702be13..000000000 --- a/spring-cloud-function-samples/function-sample-compiler/src/test/java/com/example/SampleCompiledFunctionTests.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.example; - -import org.junit.jupiter.api.Test; - -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Mark Fisher - */ -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { - "spring.cloud.function.compile.test.lambda=f->f.map(s->s+\"!!!\")", - "spring.cloud.function.compile.test.inputType=Flux", - "spring.cloud.function.compile.test.outputType=Flux"}) -public class SampleCompiledFunctionTests { - - @LocalServerPort - private int port; - - @Test - public void lowercase() { - assertThat(new TestRestTemplate().postForObject( - "http://localhost:" + this.port + "/test", "it works", String.class)) - .contains("it works!!!"); - } - -} diff --git a/spring-cloud-function-samples/function-sample-pof/build.gradle b/spring-cloud-function-samples/function-sample-pof/build.gradle index ee3becec8..d62d81852 100644 --- a/spring-cloud-function-samples/function-sample-pof/build.gradle +++ b/spring-cloud-function-samples/function-sample-pof/build.gradle @@ -46,6 +46,5 @@ dependencyManagement { dependencies { compile('org.springframework.cloud:spring-cloud-starter-function-web') - compile('org.springframework.cloud:spring-cloud-function-compiler') testCompile('org.springframework.boot:spring-boot-starter-test') } diff --git a/spring-cloud-function-samples/function-sample-pojo/build.gradle b/spring-cloud-function-samples/function-sample-pojo/build.gradle index 47409b0e9..d033c4a27 100644 --- a/spring-cloud-function-samples/function-sample-pojo/build.gradle +++ b/spring-cloud-function-samples/function-sample-pojo/build.gradle @@ -46,6 +46,5 @@ dependencyManagement { dependencies { compile('org.springframework.cloud:spring-cloud-starter-function-web') - compile('org.springframework.cloud:spring-cloud-function-compiler') testCompile('org.springframework.boot:spring-boot-starter-test') } diff --git a/spring-cloud-function-samples/function-sample-task/build.gradle b/spring-cloud-function-samples/function-sample-task/build.gradle index 639b41f75..91518d022 100644 --- a/spring-cloud-function-samples/function-sample-task/build.gradle +++ b/spring-cloud-function-samples/function-sample-task/build.gradle @@ -46,6 +46,5 @@ dependencyManagement { dependencies { compile('org.springframework.cloud:spring-cloud-function-task') - compile('org.springframework.cloud:spring-cloud-function-compiler') testCompile('org.springframework.boot:spring-boot-starter-test') } diff --git a/spring-cloud-function-samples/function-sample-task/pom.xml b/spring-cloud-function-samples/function-sample-task/pom.xml index bfa512c92..729b722d6 100644 --- a/spring-cloud-function-samples/function-sample-task/pom.xml +++ b/spring-cloud-function-samples/function-sample-task/pom.xml @@ -34,10 +34,6 @@ org.springframework.cloud spring-cloud-starter-function-web
- - org.springframework.cloud - spring-cloud-function-compiler - org.springframework.boot spring-boot-starter-test diff --git a/spring-cloud-function-samples/function-sample/build.gradle b/spring-cloud-function-samples/function-sample/build.gradle index 76eb4efff..f2976cab9 100644 --- a/spring-cloud-function-samples/function-sample/build.gradle +++ b/spring-cloud-function-samples/function-sample/build.gradle @@ -45,6 +45,5 @@ dependencyManagement { dependencies { compile('org.springframework.cloud:spring-cloud-starter-function-web') - compile('org.springframework.cloud:spring-cloud-function-compiler') testCompile('org.springframework.boot:spring-boot-starter-test') }