diff --git a/etc/checkstyle.xml b/etc/checkstyle.xml index d01928570..e7865b41e 100644 --- a/etc/checkstyle.xml +++ b/etc/checkstyle.xml @@ -1,7 +1,7 @@ + + diff --git a/etc/copyright-exclude.txt b/etc/copyright-exclude.txt index 1ad7383ef..a0c7a0f58 100644 --- a/etc/copyright-exclude.txt +++ b/etc/copyright-exclude.txt @@ -42,3 +42,4 @@ expected expected-config .helidon jvm.config +.loader diff --git a/maven-plugins/pom.xml b/maven-plugins/pom.xml index 44c9fb351..04777680c 100644 --- a/maven-plugins/pom.xml +++ b/maven-plugins/pom.xml @@ -42,5 +42,6 @@ sitegen-maven-plugin snakeyaml-codegen-maven-plugin stager-maven-plugin + shade-extensions diff --git a/maven-plugins/shade-extensions/README.md b/maven-plugins/shade-extensions/README.md new file mode 100644 index 000000000..c42745f27 --- /dev/null +++ b/maven-plugins/shade-extensions/README.md @@ -0,0 +1,42 @@ +# Helidon Shade Maven Plugin Extensions + +Allows shading Helidon artefacts with[ Maven Shade plugin](https://maven.apache.org/plugins/maven-shade-plugin/) +by providing transformer for aggregating service registry files. + +Aggregated files: + * `META-INF/helidon/service-registry.json` + * `META-INF/helidon/config-metadata.json` + * `META-INF/helidon/service.loader` + * `META-INF/helidon/serial-config.properties` + * `META-INF/helidon/feature-metadata.properties` + +### General usage + +```xml + + org.apache.maven.plugins + maven-shade-plugin + 3.5.1 + + + package + + shade + + + + + + + + + + + + io.helidon.build-tools + helidon-shade-extensions + 4.0.0-SNAPSHOT + + + +``` \ No newline at end of file diff --git a/maven-plugins/shade-extensions/pom.xml b/maven-plugins/shade-extensions/pom.xml new file mode 100644 index 000000000..e74246739 --- /dev/null +++ b/maven-plugins/shade-extensions/pom.xml @@ -0,0 +1,48 @@ + + + + 4.0.0 + + io.helidon.build-tools + helidon-build-tools-project + 4.0.0-SNAPSHOT + ../../pom.xml + + helidon-shade-extensions + Helidon Shade Maven Plugin Extensions + + + + org.apache.maven.plugins + maven-shade-plugin + + + org.glassfish + javax.json + + + + org.junit.jupiter + junit-jupiter-api + test + + + diff --git a/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/Aggregator.java b/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/Aggregator.java new file mode 100644 index 000000000..9128a3ab8 --- /dev/null +++ b/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/Aggregator.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * 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 + * + * http://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 io.helidon.build.maven.shade; + +import java.io.IOException; +import java.io.InputStream; +import java.util.jar.JarOutputStream; + +interface Aggregator { + String path(); + boolean hasTransformedResource(); + void aggregate(InputStream is) throws IOException; + void writeToJar(JarOutputStream jos) throws IOException; +} diff --git a/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/FeatureMetadataAggregator.java b/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/FeatureMetadataAggregator.java new file mode 100644 index 000000000..c0b1184da --- /dev/null +++ b/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/FeatureMetadataAggregator.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * 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 + * + * http://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 io.helidon.build.maven.shade; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.Properties; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; + +import static java.nio.charset.StandardCharsets.UTF_8; + +/** + * Feature properties can't be effectively aggregated, instead single feature file is created. + * + * Example: + *
{@code
+ * # Features aggregated by HelidonServiceTransformer during shading:
+ * # - CDI
+ * # - Config
+ * # - Object Mapping
+ * # - YAML
+ * # - Observe
+ * # - CORS
+ * # - WebServer
+ * # - Media
+ * # - Encoding
+ * # - Static Content
+ * # - JSONP
+ * # - Config
+ * # - Encryption
+ * # - WebClient
+ * # - HTTP/1.1
+ * n=Helidon Shaded
+ * d=Helidon modules shaded in to the single module.
+ * }
+ */ +class FeatureMetadataAggregator implements Aggregator { + + static final String FEATURE_METADATA_PATH = "META-INF/helidon/feature-metadata.properties"; + private final List features = new LinkedList<>(); + + @Override + public String path() { + return FEATURE_METADATA_PATH; + } + + @Override + public boolean hasTransformedResource() { + return true; + } + + @Override + public void aggregate(InputStream is) throws IOException { + Properties properties = new Properties(); + properties.load(is); + Optional.ofNullable(properties.getProperty("n")).ifPresent(features::add); + } + + @Override + public void writeToJar(JarOutputStream jos) throws IOException { + JarEntry entry = new JarEntry(path()); + entry.setTime(Long.MIN_VALUE); + jos.putNextEntry(entry); + Writer writer = new OutputStreamWriter(jos, UTF_8); + writer.write("# Features aggregated by HelidonServiceTransformer during shading:"); + writer.write("\n# - " + String.join("\n# - ", features)); + writer.write("\nn=Helidon Shaded"); + writer.write("\nd=Helidon modules shaded in to the single module."); + writer.write("\n"); + writer.flush(); + } +} diff --git a/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/HelidonServiceTransformer.java b/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/HelidonServiceTransformer.java new file mode 100644 index 000000000..bb1bb5b80 --- /dev/null +++ b/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/HelidonServiceTransformer.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * 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 + * + * http://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 io.helidon.build.maven.shade; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.jar.JarOutputStream; +import java.util.stream.Stream; + +import org.apache.maven.plugins.shade.relocation.Relocator; +import org.apache.maven.plugins.shade.resource.ReproducibleResourceTransformer; + +import static java.util.stream.Collectors.toMap; + +/** + * Maven Shade plugin custom transformer for merging Helidon service-registry files. + * Usage: + *
{@code
+ * 
+ *    org.apache.maven.plugins
+ *    maven-shade-plugin
+ *    3.5.1
+ *    
+ *        
+ *            package
+ *            
+ *                shade
+ *            
+ *            
+ *                
+ *                    
+ *                    
+ *                
+ *            
+ *        
+ *    
+ *    
+ *        
+ *            io.helidon.build-tools
+ *            helidon-shade-extensions
+ *            4.0.0-SNAPSHOT
+ *        
+ *    
+ * 
+ * }
+ */ +public class HelidonServiceTransformer implements ReproducibleResourceTransformer { + + static final String SERVICE_REGISTRY_PATH = "META-INF/helidon/service-registry.json"; + static final String CONFIG_METADATA_PATH = "META-INF/helidon/config-metadata.json"; + + private final Map aggregators = Stream + .of( + new JsonArrayAggregator(SERVICE_REGISTRY_PATH), + new JsonArrayAggregator(CONFIG_METADATA_PATH), + new ServiceLoaderAggregator(), + new SerialConfigAggregator(), + new FeatureMetadataAggregator() + ) + .collect(toMap(Aggregator::path, Function.identity())); + + @Override + public boolean canTransformResource(String resource) { + return aggregators.containsKey(resource); + } + + @Override + public void processResource(String resource, InputStream is, List relocators) throws IOException { + processResource(resource, is, relocators, 0); + } + + @Override + public boolean hasTransformedResource() { + return aggregators.values().stream().anyMatch(Aggregator::hasTransformedResource); + } + + @Override + public void modifyOutputStream(JarOutputStream jarOutputStream) throws IOException { + for (Aggregator a : aggregators.values()) { + a.writeToJar(jarOutputStream); + } + } + + @Override + public void processResource(String resource, InputStream is, List relocators, long time) throws IOException { + aggregators.get(resource).aggregate(is); + } +} diff --git a/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/JsonArrayAggregator.java b/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/JsonArrayAggregator.java new file mode 100644 index 000000000..e598b40e9 --- /dev/null +++ b/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/JsonArrayAggregator.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * 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 + * + * http://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 io.helidon.build.maven.shade; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; + +import javax.json.Json; +import javax.json.JsonArray; +import javax.json.JsonArrayBuilder; +import javax.json.JsonValue; + +import static java.nio.charset.StandardCharsets.UTF_8; + +class JsonArrayAggregator implements Aggregator { + + private final String path; + private final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder(); + + JsonArrayAggregator(String path) { + this.path = path; + } + + @Override + public String path() { + return path; + } + + @Override + public boolean hasTransformedResource() { + return !arrayBuilder.build().isEmpty(); + } + + @Override + public void aggregate(InputStream is) { + JsonArray array = Json.createReader(is).readArray(); + for (JsonValue value : array) { + arrayBuilder.add(value); + } + } + + @Override + public void writeToJar(JarOutputStream jos) throws IOException { + JsonArray jsonArray = arrayBuilder.build(); + if (jsonArray.isEmpty()) { + return; + } + JarEntry entry = new JarEntry(path); + entry.setTime(Long.MIN_VALUE); + jos.putNextEntry(entry); + Writer writer = new OutputStreamWriter(jos, UTF_8); + Json.createWriter(writer).write(jsonArray); + writer.flush(); + } +} diff --git a/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/SerialConfigAggregator.java b/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/SerialConfigAggregator.java new file mode 100644 index 000000000..9a650604f --- /dev/null +++ b/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/SerialConfigAggregator.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * 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 + * + * http://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 io.helidon.build.maven.shade; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.LinkedHashSet; +import java.util.Properties; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static java.nio.charset.StandardCharsets.UTF_8; + +class SerialConfigAggregator implements Aggregator { + + static final String SERIAL_CONFIG_PATH = "META-INF/helidon/serial-config.properties"; + private static final String REJECT_ALL_PATTERN = "!*"; + private final Set parts = new LinkedHashSet<>(); + + @Override + public String path() { + return SERIAL_CONFIG_PATH; + } + + @Override + public boolean hasTransformedResource() { + return !parts.isEmpty(); + } + + @Override + public void aggregate(InputStream is) throws IOException { + Properties props = new Properties(); + props.load(is); + String pattern = props.getProperty("pattern"); + parts.addAll(Stream.of(pattern.split(";")) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .collect(Collectors.toList())); + } + + @Override + public void writeToJar(JarOutputStream jos) throws IOException { + if (parts.isEmpty()) { + return; + } + + moveRejectAllToEnd(); + + JarEntry entry = new JarEntry(path()); + entry.setTime(Long.MIN_VALUE); + jos.putNextEntry(entry); + Writer writer = new OutputStreamWriter(jos, UTF_8); + writer.write("# Serial configuration aggregated by HelidonServiceTransformer during shading"); + writer.write("\npattern="); + writer.write(String.join(";\\\n ", parts)); + writer.write("\n"); + writer.flush(); + } + + private void moveRejectAllToEnd() { + // When reject all pattern is present, it should be always at the end of aggregation + if (parts.contains(REJECT_ALL_PATTERN)) { + parts.remove(REJECT_ALL_PATTERN); + parts.add(REJECT_ALL_PATTERN); + } + } +} diff --git a/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/ServiceLoaderAggregator.java b/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/ServiceLoaderAggregator.java new file mode 100644 index 000000000..8ea49a6e6 --- /dev/null +++ b/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/ServiceLoaderAggregator.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * 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 + * + * http://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 io.helidon.build.maven.shade; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.LinkedHashSet; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; + +import static java.nio.charset.StandardCharsets.UTF_8; + +class ServiceLoaderAggregator implements Aggregator { + + static final String SERVICE_LOADER_PATH = "META-INF/helidon/service.loader"; + private final LinkedHashSet lines = new LinkedHashSet<>(); + + @Override + public String path() { + return SERVICE_LOADER_PATH; + } + + @Override + public boolean hasTransformedResource() { + return !lines.isEmpty(); + } + + @Override + public void aggregate(InputStream is) throws IOException { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, UTF_8))) { + reader.lines().forEach(lines::add); + } + } + + @Override + public void writeToJar(JarOutputStream jos) throws IOException { + if (lines.isEmpty()) { + return; + } + JarEntry entry = new JarEntry(path()); + entry.setTime(Long.MIN_VALUE); + jos.putNextEntry(entry); + Writer writer = new OutputStreamWriter(jos, UTF_8); + for (String line : lines) { + writer.append(line); + writer.append('\n'); + } + writer.flush(); + } +} diff --git a/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/package-info.java b/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/package-info.java new file mode 100644 index 000000000..515ec7732 --- /dev/null +++ b/maven-plugins/shade-extensions/src/main/java/io/helidon/build/maven/shade/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * 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 + * + * http://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. + */ + +/** + * Maven Shade plugin custom transformer for merging Helidon service-registry, config-metadata and service.loader files. + */ +package io.helidon.build.maven.shade; diff --git a/maven-plugins/shade-extensions/src/test/java/io/helidon/build/maven/shade/HelidonServiceTransformerTest.java b/maven-plugins/shade-extensions/src/test/java/io/helidon/build/maven/shade/HelidonServiceTransformerTest.java new file mode 100644 index 000000000..8e0202bde --- /dev/null +++ b/maven-plugins/shade-extensions/src/test/java/io/helidon/build/maven/shade/HelidonServiceTransformerTest.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * 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 + * + * http://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 io.helidon.build.maven.shade; + +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; +import java.util.jar.JarOutputStream; + +import javax.json.Json; +import javax.json.JsonArray; +import javax.json.JsonObject; +import javax.json.JsonWriterFactory; +import javax.json.stream.JsonGenerator; +import org.junit.jupiter.api.Test; + +import static io.helidon.build.maven.shade.HelidonServiceTransformer.CONFIG_METADATA_PATH; +import static io.helidon.build.maven.shade.HelidonServiceTransformer.SERVICE_REGISTRY_PATH; +import static io.helidon.build.maven.shade.SerialConfigAggregator.SERIAL_CONFIG_PATH; +import static io.helidon.build.maven.shade.ServiceLoaderAggregator.SERVICE_LOADER_PATH; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class HelidonServiceTransformerTest { + + static JsonWriterFactory JSON_WRITER = Json.createWriterFactory(Map.of(JsonGenerator.PRETTY_PRINTING, false)); + + @Test + void testAll() throws IOException { + String jarName = "target/output.jar"; + HelidonServiceTransformer transformer = new HelidonServiceTransformer(); + transformer.processResource(SERVICE_REGISTRY_PATH, + ClassLoader.getSystemResourceAsStream("service-registry-1.json"), + null); + transformer.processResource(SERVICE_REGISTRY_PATH, + ClassLoader.getSystemResourceAsStream("service-registry-2.json"), + null); + transformer.processResource(CONFIG_METADATA_PATH, + ClassLoader.getSystemResourceAsStream("config-metadata-1.json"), + null); + transformer.processResource(CONFIG_METADATA_PATH, + ClassLoader.getSystemResourceAsStream("config-metadata-2.json"), + null); + transformer.processResource(SERVICE_LOADER_PATH, + ClassLoader.getSystemResourceAsStream("service-1.loader"), + null); + transformer.processResource(SERVICE_LOADER_PATH, + ClassLoader.getSystemResourceAsStream("service-2.loader"), + null); + transformer.processResource(SERIAL_CONFIG_PATH, + ClassLoader.getSystemResourceAsStream("serial-config-1.properties"), + null); + transformer.processResource(SERIAL_CONFIG_PATH, + ClassLoader.getSystemResourceAsStream("serial-config-2.properties"), + null); + transformer.processResource(SERIAL_CONFIG_PATH, + ClassLoader.getSystemResourceAsStream("serial-config-3.properties"), + null); + + JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream(jarName)); + transformer.modifyOutputStream(jarOutputStream); + jarOutputStream.close(); + + // Resulting service-registry.json + JsonArray svcRegArray = Json.createReader(new StringReader(readFromJar(jarName, SERVICE_REGISTRY_PATH))).readArray(); + JsonObject svcRegObj1 = svcRegArray.getJsonObject(0); + JsonObject svcRegObj2 = svcRegArray.getJsonObject(1); + + assertEqualJson(Json.createArrayBuilder().add(svcRegObj1).build(), "service-registry-1.json"); + assertEqualJson(Json.createArrayBuilder().add(svcRegObj2).build(), "service-registry-2.json"); + + // Resulting config-metadata.json + JsonArray cfgMetaArray = Json.createReader(new StringReader(readFromJar(jarName, CONFIG_METADATA_PATH))).readArray(); + JsonObject cfgMetaObj1 = cfgMetaArray.getJsonObject(0); + JsonObject cfgMetaObj2 = cfgMetaArray.getJsonObject(1); + + assertEqualJson(Json.createArrayBuilder().add(cfgMetaObj1).build(), "config-metadata-1.json"); + assertEqualJson(Json.createArrayBuilder().add(cfgMetaObj2).build(), "config-metadata-2.json"); + + // Resulting service.loader + String expectedsl = new String(ClassLoader.getSystemResourceAsStream("service-expected.loader").readAllBytes()); + String actualsl = readFromJar(jarName, SERVICE_LOADER_PATH); + assertEquals(expectedsl, actualsl); + + // Resulting serial-config.properties + String expectedsc = new String(ClassLoader.getSystemResourceAsStream("serial-config-expected.properties").readAllBytes()); + String actualsc = readFromJar(jarName, SERIAL_CONFIG_PATH); + assertEquals(expectedsc, actualsc); + } + + @Test + void testSingles() throws IOException { + String jarName = "target/output-singles.jar"; + HelidonServiceTransformer transformer = new HelidonServiceTransformer(); + transformer.processResource(SERVICE_REGISTRY_PATH, + ClassLoader.getSystemResourceAsStream("service-registry-1.json"), + null); + transformer.processResource(CONFIG_METADATA_PATH, + ClassLoader.getSystemResourceAsStream("config-metadata-1.json"), + null); + transformer.processResource(SERVICE_LOADER_PATH, + ClassLoader.getSystemResourceAsStream("service-1.loader"), + null); + + JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream(jarName)); + transformer.modifyOutputStream(jarOutputStream); + jarOutputStream.close(); + + // Resulting service-registry.json + JsonArray svcRegArray = Json.createReader(new StringReader(readFromJar(jarName, SERVICE_REGISTRY_PATH))).readArray(); + + assertEqualJson(svcRegArray, "service-registry-1.json"); + + // Resulting config-metadata.json + JsonArray cfgMetaArray = Json.createReader(new StringReader(readFromJar(jarName, CONFIG_METADATA_PATH))).readArray(); + + assertEqualJson(cfgMetaArray, "config-metadata-1.json"); + + // Resulting service.loader + String expected = new String(ClassLoader.getSystemResourceAsStream("service-1.loader").readAllBytes()); + String actual = readFromJar(jarName, SERVICE_LOADER_PATH); + assertEquals(expected, actual); + } + + private void assertEqualJson(JsonArray actual, String expectedResourceName) throws IOException { + String expected = new String(ClassLoader.getSystemResourceAsStream(expectedResourceName).readAllBytes()); + StringWriter actStringWriter = new StringWriter(); + StringWriter expStringWriter = new StringWriter(); + JSON_WRITER.createWriter(actStringWriter).writeArray(actual); + JSON_WRITER.createWriter(expStringWriter).writeArray(Json.createReader(new StringReader(expected)).readArray()); + assertEquals(expStringWriter.toString(), actStringWriter.toString()); + } + + private String readFromJar(String jarPath, String fileName) throws IOException { + JarInputStream jis = new JarInputStream(new FileInputStream(jarPath)); + JarEntry entry; + while ((entry = jis.getNextJarEntry()) != null) { + if (fileName.equals(entry.getName())) { + break; + } + } + assertNotNull(entry); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int n; + while (-1 != (n = jis.read(buffer))) { + baos.write(buffer, 0, n); + } + return baos.toString(StandardCharsets.UTF_8); + } +} diff --git a/maven-plugins/shade-extensions/src/test/resources/config-metadata-1.json b/maven-plugins/shade-extensions/src/test/resources/config-metadata-1.json new file mode 100644 index 000000000..9044d2a71 --- /dev/null +++ b/maven-plugins/shade-extensions/src/test/resources/config-metadata-1.json @@ -0,0 +1,118 @@ +[ + { + "module": "io.helidon.scheduling", + "types": [ + { + "type": "io.helidon.scheduling.TaskConfig", + "annotatedType": "io.helidon.scheduling.TaskConfig", + "producers": [ + "io.helidon.scheduling.TaskConfig#create(io.helidon.common.config.Config)", + "io.helidon.scheduling.TaskConfig#builder()" + ], + "options": [] + }, + { + "type": "io.helidon.scheduling.Cron", + "annotatedType": "io.helidon.scheduling.CronConfig", + "inherits": [ + "io.helidon.scheduling.TaskConfig" + ], + "producers": [ + "io.helidon.scheduling.CronConfig#create(io.helidon.common.config.Config)", + "io.helidon.scheduling.CronConfig#builder()", + "io.helidon.scheduling.Cron#create(io.helidon.scheduling.CronConfig)" + ], + "options": [ + { + "key": "concurrent", + "type": "java.lang.Boolean", + "description": "Allow concurrent execution if previous task didn't finish before next execution.\n Default value is `true`.\n\nTrue for allow concurrent execution.", + "defaultValue": "true", + "method": "io.helidon.scheduling.CronConfig.Builder#concurrentExecution(boolean)" + }, + { + "key": "expression", + "description": "Cron expression for specifying period of execution.\n

\n Examples:\n

    \n
  • `0/2 * * * * ? *` - Every 2 seconds
  • \n
  • `0 45 9 ? * *` - Every day at 9:45
  • \n
  • `0 15 8 ? * MON-FRI` - Every workday at 8:15
  • \n
\n\nCron expression", + "required": true, + "method": "io.helidon.scheduling.CronConfig.Builder#expression(java.lang.String)" + } + ] + }, + { + "type": "io.helidon.scheduling.FixedRate", + "annotatedType": "io.helidon.scheduling.FixedRateConfig", + "inherits": [ + "io.helidon.scheduling.TaskConfig" + ], + "producers": [ + "io.helidon.scheduling.FixedRateConfig#create(io.helidon.common.config.Config)", + "io.helidon.scheduling.FixedRateConfig#builder()", + "io.helidon.scheduling.FixedRate#create(io.helidon.scheduling.FixedRateConfig)" + ], + "options": [ + { + "key": "delay", + "type": "java.lang.Long", + "description": "Fixed rate delay between each invocation. Time unit is by default java.util.concurrent.TimeUnit.SECONDS,\n can be specified with io.helidon.scheduling.FixedRateConfig.Builder.timeUnit(java.util.concurrent.TimeUnit).\n\nDelay between each invocation", + "required": true, + "method": "io.helidon.scheduling.FixedRateConfig.Builder#delay(long)" + }, + { + "key": "delay-type", + "type": "io.helidon.scheduling.FixedRate.DelayType", + "description": "Configure whether the delay between the invocations should be calculated from the time when previous task started or ended.\n Delay type is by default FixedRate.DelayType.SINCE_PREVIOUS_START.\n\nDelay type", + "defaultValue": "DelayType.SINCE_PREVIOUS_START", + "method": "io.helidon.scheduling.FixedRateConfig.Builder#delayType(io.helidon.scheduling.FixedRate.DelayType)", + "allowedValues": [ + { + "value": "SINCE_PREVIOUS_START", + "description": "Next invocation delay is measured from the previous invocation task start." + }, + { + "value": "SINCE_PREVIOUS_END", + "description": "Next invocation delay is measured from the previous invocation task end." + } + ] + }, + { + "key": "time-unit", + "type": "java.util.concurrent.TimeUnit", + "description": "java.util.concurrent.TimeUnit TimeUnit used for interpretation of values provided with\n io.helidon.scheduling.FixedRateConfig.Builder.delay(long)\n and io.helidon.scheduling.FixedRateConfig.Builder.initialDelay(long).\n\nTime unit for interpreting values\n in io.helidon.scheduling.FixedRateConfig.Builder.delay(long)\n and io.helidon.scheduling.FixedRateConfig.Builder.initialDelay(long)", + "defaultValue": "TimeUnit.TimeUnit.SECONDS", + "method": "io.helidon.scheduling.FixedRateConfig.Builder#timeUnit(java.util.concurrent.TimeUnit)", + "allowedValues": [ + { + "value": "NANOSECONDS" + }, + { + "value": "MICROSECONDS" + }, + { + "value": "MILLISECONDS" + }, + { + "value": "SECONDS" + }, + { + "value": "MINUTES" + }, + { + "value": "HOURS" + }, + { + "value": "DAYS" + } + ] + }, + { + "key": "initial-delay", + "type": "java.lang.Long", + "description": "Initial delay of the first invocation. Time unit is by default java.util.concurrent.TimeUnit.SECONDS,\n can be specified with\n io.helidon.scheduling.FixedRateConfig.Builder.timeUnit(java.util.concurrent.TimeUnit) timeUnit().\n\nInitial delay value", + "defaultValue": "0", + "method": "io.helidon.scheduling.FixedRateConfig.Builder#initialDelay(long)" + } + ] + } + ] + } +] \ No newline at end of file diff --git a/maven-plugins/shade-extensions/src/test/resources/config-metadata-2.json b/maven-plugins/shade-extensions/src/test/resources/config-metadata-2.json new file mode 100644 index 000000000..946ed8d72 --- /dev/null +++ b/maven-plugins/shade-extensions/src/test/resources/config-metadata-2.json @@ -0,0 +1,304 @@ +[ + { + "module": "io.helidon.webclient.api", + "types": [ + { + "type": "io.helidon.webclient.api.WebClient", + "annotatedType": "io.helidon.webclient.api.WebClientConfig", + "standalone": true, + "prefix": "clients", + "inherits": [ + "io.helidon.webclient.api.HttpClientConfig" + ], + "producers": [ + "io.helidon.webclient.api.WebClientConfig#create(io.helidon.common.config.Config)", + "io.helidon.webclient.api.WebClientConfig#builder()", + "io.helidon.webclient.api.WebClient#create(io.helidon.webclient.api.WebClientConfig)" + ], + "options": [ + { + "key": "protocol-configs", + "type": "io.helidon.webclient.spi.ProtocolConfig", + "description": "Configuration of client protocols.\n\nClient protocol configurations", + "kind": "LIST", + "provider": true, + "providerType": "io.helidon.webclient.spi.ProtocolConfigProvider", + "method": "io.helidon.webclient.api.WebClientConfig.Builder#protocolConfigs(java.util.List)" + } + ] + }, + { + "type": "io.helidon.webclient.api.HttpClientConfig", + "annotatedType": "io.helidon.webclient.api.HttpClientConfig", + "inherits": [ + "io.helidon.webclient.api.HttpConfigBase" + ], + "producers": [ + "io.helidon.webclient.api.HttpClientConfig#create(io.helidon.common.config.Config)", + "io.helidon.webclient.api.HttpClientConfig#builder()" + ], + "options": [ + { + "key": "relative-uris", + "type": "java.lang.Boolean", + "description": "Can be set to `true` to force the use of relative URIs in all requests,\n regardless of the presence or absence of proxies or no-proxy lists.\n\nRelative URIs flag", + "defaultValue": "false", + "method": "io.helidon.webclient.api.HttpClientConfig.Builder#relativeUris(boolean)" + }, + { + "key": "default-headers", + "description": "Default headers to be used in every request from configuration.\n\nDefault headers", + "kind": "MAP", + "method": "io.helidon.webclient.api.HttpClientConfig.Builder#defaultHeadersMap(java.util.Map)" + }, + { + "key": "content-encoding", + "type": "io.helidon.http.encoding.ContentEncodingContext", + "description": "Configure the listener specific io.helidon.http.encoding.ContentEncodingContext.\n This method discards all previously registered ContentEncodingContext.\n If no content encoding context is registered, default encoding context is used.\n\nContent encoding context", + "method": "io.helidon.webclient.api.HttpClientConfig.Builder#contentEncoding(io.helidon.http.encoding.ContentEncodingContext)" + }, + { + "key": "connection-cache-size", + "type": "java.lang.Integer", + "description": "Maximal size of the connection cache.\n For most HTTP protocols, we may cache connections to various endpoints for keep alive (or stream reuse in case of HTTP/2).\n This option limits the size. Setting this number lower than the \"usual\" number of target services will cause connections\n to be closed and reopened frequently.", + "defaultValue": "256", + "method": "io.helidon.webclient.api.HttpClientConfig.Builder#connectionCacheSize(int)" + }, + { + "key": "services", + "type": "io.helidon.webclient.spi.WebClientService", + "description": "WebClient services.\n\nServices to use with this web client", + "kind": "LIST", + "provider": true, + "providerType": "io.helidon.webclient.spi.WebClientServiceProvider", + "method": "io.helidon.webclient.api.HttpClientConfig.Builder#services(java.util.List)" + }, + { + "key": "media-context", + "type": "io.helidon.http.media.MediaContext", + "description": "Configure the listener specific io.helidon.http.media.MediaContext.\n This method discards all previously registered MediaContext.\n If no media context is registered, default media context is used.\n\nMedia context", + "defaultValue": "create()", + "method": "io.helidon.webclient.api.HttpClientConfig.Builder#mediaContext(io.helidon.http.media.MediaContext)" + }, + { + "key": "cookie-manager", + "type": "io.helidon.webclient.api.WebClientCookieManager", + "description": "WebClient cookie manager.\n\nCookie manager to use", + "method": "io.helidon.webclient.api.HttpClientConfig.Builder#cookieManager(java.util.Optional)" + }, + { + "key": "max-in-memory-entity", + "type": "java.lang.Integer", + "description": "If the entity is expected to be smaller that this number of bytes, it would be buffered in memory to optimize performance.\n If bigger, streaming will be used.\n

\n Note that for some entity types we cannot use streaming, as they are already fully in memory (String, byte[]), for such\n cases, this option is ignored. Default is 128Kb.\n\nMaximal number of bytes to buffer in memory for supported writers", + "defaultValue": "131072", + "method": "io.helidon.webclient.api.HttpClientConfig.Builder#maxInMemoryEntity(int)" + }, + { + "key": "send-expect-continue", + "type": "java.lang.Boolean", + "description": "Whether Expect-100-Continue header is sent to verify server availability before sending an entity.\n

\n Defaults to `true`.\n

\n\nWhether Expect:100-Continue header should be sent on streamed transfers", + "defaultValue": "true", + "method": "io.helidon.webclient.api.HttpClientConfig.Builder#sendExpectContinue(boolean)" + }, + { + "key": "socket-options", + "type": "io.helidon.common.socket.SocketOptions", + "description": "Socket options for connections opened by this client.\n If there is a value explicitly configured on this type and on the socket options,\n the one configured on this type's builder will win:\n
    \n
  • readTimeout()
  • \n
  • connectTimeout()
  • \n
\n\nSocket options", + "method": "io.helidon.webclient.api.HttpClientConfig.Builder#socketOptions(io.helidon.common.socket.SocketOptions)" + }, + { + "key": "share-connection-cache", + "type": "java.lang.Boolean", + "description": "Whether to share connection cache between all the WebClient instances in JVM.\n\nTrue if connection cache is shared", + "defaultValue": "true", + "method": "io.helidon.webclient.api.HttpClientConfig.Builder#shareConnectionCache(boolean)" + }, + { + "key": "media-type-parser-mode", + "type": "io.helidon.common.media.type.ParserMode", + "description": "Configure media type parsing mode for HTTP `Content-Type` header.\n\nMedia type parsing mode", + "defaultValue": "ParserMode.STRICT", + "method": "io.helidon.webclient.api.HttpClientConfig.Builder#mediaTypeParserMode(io.helidon.common.media.type.ParserMode)", + "allowedValues": [ + { + "value": "STRICT" + }, + { + "value": "RELAXED" + } + ] + }, + { + "key": "base-uri", + "type": "io.helidon.webclient.api.ClientUri", + "description": "Base uri used by the client in all requests.\n\nBase uri of the client requests", + "method": "io.helidon.webclient.api.HttpClientConfig.Builder#baseUri(java.util.Optional)" + }, + { + "key": "read-continue-timeout", + "type": "java.time.Duration", + "description": "Socket 100-Continue read timeout. Default is 1 second.\n This read timeout is used when 100-Continue is sent by the client, before it sends an entity.\n\nRead 100-Continue timeout duration", + "defaultValue": "PT1S", + "method": "io.helidon.webclient.api.HttpClientConfig.Builder#readContinueTimeout(java.time.Duration)" + } + ] + }, + { + "type": "io.helidon.webclient.api.WebClientCookieManager", + "annotatedType": "io.helidon.webclient.api.WebClientCookieManagerConfig", + "producers": [ + "io.helidon.webclient.api.WebClientCookieManagerConfig#create(io.helidon.common.config.Config)", + "io.helidon.webclient.api.WebClientCookieManagerConfig#builder()", + "io.helidon.webclient.api.WebClientCookieManager#create(io.helidon.webclient.api.WebClientCookieManagerConfig)" + ], + "options": [ + { + "key": "automatic-store-enabled", + "type": "java.lang.Boolean", + "description": "Whether automatic cookie store is enabled or not.\n\nStatus of cookie store", + "defaultValue": "false", + "method": "io.helidon.webclient.api.WebClientCookieManagerConfig.Builder#automaticStoreEnabled(boolean)" + }, + { + "key": "cookie-policy", + "type": "java.net.CookiePolicy", + "description": "Current cookie policy for this client.\n\nThe cookie policy", + "defaultValue": "java.net.CookiePolicy.ACCEPT_ORIGINAL_SERVER", + "method": "io.helidon.webclient.api.WebClientCookieManagerConfig.Builder#cookiePolicy(java.net.CookiePolicy)" + }, + { + "key": "default-cookies", + "description": "Map of default cookies to include in all requests if cookies enabled.\n\nMap of default cookies", + "kind": "MAP", + "method": "io.helidon.webclient.api.WebClientCookieManagerConfig.Builder#defaultCookies(java.util.Map)" + } + ] + }, + { + "type": "io.helidon.webclient.api.HttpConfigBase", + "annotatedType": "io.helidon.webclient.api.HttpConfigBase", + "producers": [ + "io.helidon.webclient.api.HttpConfigBase#create(io.helidon.common.config.Config)", + "io.helidon.webclient.api.HttpConfigBase#builder()" + ], + "options": [ + { + "key": "read-timeout", + "type": "java.time.Duration", + "description": "Read timeout.\n\nRead timeout\n See io.helidon.common.socket.SocketOptions.readTimeout()", + "method": "io.helidon.webclient.api.HttpConfigBase.Builder#readTimeout(java.util.Optional)" + }, + { + "key": "keep-alive", + "type": "java.lang.Boolean", + "description": "Determines if connection keep alive is enabled (NOT socket keep alive, but HTTP connection keep alive, to re-use\n the same connection for multiple requests).\n\nKeep alive for this connection\n See io.helidon.common.socket.SocketOptions.socketKeepAlive()", + "defaultValue": "true", + "method": "io.helidon.webclient.api.HttpConfigBase.Builder#keepAlive(boolean)" + }, + { + "key": "proxy", + "type": "io.helidon.webclient.api.Proxy", + "description": "Proxy configuration to be used for requests.\n\nProxy to use, defaults to Proxy.noProxy()", + "method": "io.helidon.webclient.api.HttpConfigBase.Builder#proxy(io.helidon.webclient.api.Proxy)" + }, + { + "key": "follow-redirects", + "type": "java.lang.Boolean", + "description": "Whether to follow redirects.\n\nWhether to follow redirects", + "defaultValue": "true", + "method": "io.helidon.webclient.api.HttpConfigBase.Builder#followRedirects(boolean)" + }, + { + "key": "connect-timeout", + "type": "java.time.Duration", + "description": "Connect timeout.\n\nConnect timeout\n See io.helidon.common.socket.SocketOptions.connectTimeout()", + "method": "io.helidon.webclient.api.HttpConfigBase.Builder#connectTimeout(java.util.Optional)" + }, + { + "key": "max-redirects", + "type": "java.lang.Integer", + "description": "Max number of followed redirects.\n This is ignored if followRedirects() option is `false`.\n\nMax number of followed redirects", + "defaultValue": "10", + "method": "io.helidon.webclient.api.HttpConfigBase.Builder#maxRedirects(int)" + }, + { + "key": "tls", + "type": "io.helidon.common.tls.Tls", + "description": "TLS configuration for any TLS request from this client.\n TLS can also be configured per request.\n TLS is used when the protocol is set to `https`.\n\nTLS configuration to use", + "method": "io.helidon.webclient.api.HttpConfigBase.Builder#tls(io.helidon.common.tls.Tls)" + }, + { + "key": "properties", + "description": "Properties configured for this client. These properties are propagated through client request, to be used by\n services (and possibly for other purposes).\n\nMap of client properties", + "kind": "MAP", + "method": "io.helidon.webclient.api.HttpConfigBase.Builder#properties(java.util.Map)" + } + ] + }, + { + "type": "io.helidon.webclient.api.Proxy", + "annotatedType": "io.helidon.webclient.api.Proxy.Builder", + "producers": [ + "io.helidon.webclient.api.Proxy.Builder#build()", + "io.helidon.webclient.api.Proxy#create(io.helidon.common.config.Config)" + ], + "options": [ + { + "key": "password", + "description": "Sets a new password for the proxy.", + "method": "io.helidon.webclient.api.Proxy.Builder#password(char[])" + }, + { + "key": "port", + "type": "java.lang.Integer", + "description": "Sets a port value.", + "method": "io.helidon.webclient.api.Proxy.Builder#port(int)" + }, + { + "key": "host", + "description": "Sets a new host value.", + "method": "io.helidon.webclient.api.Proxy.Builder#host(java.lang.String)" + }, + { + "key": "force-http-connect", + "type": "java.lang.Boolean", + "description": "Forces HTTP CONNECT with the proxy server.\n Otherwise it will not execute HTTP CONNECT when the request is\n plain HTTP with no authentication.", + "method": "io.helidon.webclient.api.Proxy.Builder#forceHttpConnect(boolean)" + }, + { + "key": "username", + "description": "Sets a new username for the proxy.", + "method": "io.helidon.webclient.api.Proxy.Builder#username(java.lang.String)" + }, + { + "key": "type", + "type": "io.helidon.webclient.api.Proxy.ProxyType", + "description": "Sets a new proxy type.", + "defaultValue": "HTTP", + "method": "io.helidon.webclient.api.Proxy.Builder#type(io.helidon.webclient.api.Proxy.ProxyType)", + "allowedValues": [ + { + "value": "NONE", + "description": "No proxy." + }, + { + "value": "SYSTEM", + "description": "Proxy obtained from system." + }, + { + "value": "HTTP", + "description": "HTTP proxy." + } + ] + }, + { + "key": "no-proxy", + "description": "Configure a host pattern that is not going through a proxy.\n

\n Options are:\n

    \n
  • IP Address, such as `192.168.1.1`
  • \n
  • IP V6 Address, such as `[2001:db8:85a3:8d3:1319:8a2e:370:7348]`
  • \n
  • Hostname, such as `localhost`
  • \n
  • Domain name, such as `helidon.io`
  • \n
  • Domain name and all sub-domains, such as `.helidon.io` (leading dot)
  • \n
  • Combination of all options from above with a port, such as `.helidon.io:80`
  • \n
", + "kind": "LIST", + "method": "io.helidon.webclient.api.Proxy.Builder#addNoProxy(java.lang.String)" + } + ] + } + ] + } +] \ No newline at end of file diff --git a/maven-plugins/shade-extensions/src/test/resources/serial-config-1.properties b/maven-plugins/shade-extensions/src/test/resources/serial-config-1.properties new file mode 100644 index 000000000..3f6ce1ec0 --- /dev/null +++ b/maven-plugins/shade-extensions/src/test/resources/serial-config-1.properties @@ -0,0 +1,18 @@ +# +# Copyright (c) 2024 Oracle and/or its affiliates. +# +# 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 +# +# http://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. +# + +pattern=org.jboss.weld.bean.proxy.util.SerializableClientProxy;org.jboss.weld.bean.StringBeanIdentifier;\ + org.eclipse.microprofile.config.Config$_$$_WeldClientProxy;io.helidon.config.mp.MpConfigBuilder$NullCheckingConverter;!* diff --git a/maven-plugins/shade-extensions/src/test/resources/serial-config-2.properties b/maven-plugins/shade-extensions/src/test/resources/serial-config-2.properties new file mode 100644 index 000000000..b239f24c9 --- /dev/null +++ b/maven-plugins/shade-extensions/src/test/resources/serial-config-2.properties @@ -0,0 +1,17 @@ +# +# Copyright (c) 2024 Oracle and/or its affiliates. +# +# 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 +# +# http://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. +# + +pattern=oracle.i18n.util.builder.*;oracle.sql.converter.*;oracle.i18n.text.*;oracle.i18n.text.converter.*; diff --git a/maven-plugins/shade-extensions/src/test/resources/serial-config-3.properties b/maven-plugins/shade-extensions/src/test/resources/serial-config-3.properties new file mode 100644 index 000000000..4be735172 --- /dev/null +++ b/maven-plugins/shade-extensions/src/test/resources/serial-config-3.properties @@ -0,0 +1,17 @@ +# +# Copyright (c) 2024 Oracle and/or its affiliates. +# +# 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 +# +# http://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. +# + +pattern=weblogic.**;java.util.**;java.lang.**;java.io.**;java.rmi.**;javax.naming.** diff --git a/maven-plugins/shade-extensions/src/test/resources/serial-config-expected.properties b/maven-plugins/shade-extensions/src/test/resources/serial-config-expected.properties new file mode 100644 index 000000000..db6112d16 --- /dev/null +++ b/maven-plugins/shade-extensions/src/test/resources/serial-config-expected.properties @@ -0,0 +1,16 @@ +# Serial configuration aggregated by HelidonServiceTransformer during shading +pattern=org.jboss.weld.bean.proxy.util.SerializableClientProxy;\ + org.jboss.weld.bean.StringBeanIdentifier;\ + org.eclipse.microprofile.config.Config$_$$_WeldClientProxy;\ + io.helidon.config.mp.MpConfigBuilder$NullCheckingConverter;\ + oracle.i18n.util.builder.*;\ + oracle.sql.converter.*;\ + oracle.i18n.text.*;\ + oracle.i18n.text.converter.*;\ + weblogic.**;\ + java.util.**;\ + java.lang.**;\ + java.io.**;\ + java.rmi.**;\ + javax.naming.**;\ + !* diff --git a/maven-plugins/shade-extensions/src/test/resources/service-1.loader b/maven-plugins/shade-extensions/src/test/resources/service-1.loader new file mode 100644 index 000000000..ee833c1c8 --- /dev/null +++ b/maven-plugins/shade-extensions/src/test/resources/service-1.loader @@ -0,0 +1,3 @@ +# List of service contracts we want to support either from service registry, or from service loader +io.helidon.config.spi.ConfigParser +io.helidon.config.spi.ConfigFilter diff --git a/maven-plugins/shade-extensions/src/test/resources/service-2.loader b/maven-plugins/shade-extensions/src/test/resources/service-2.loader new file mode 100644 index 000000000..bb56b208d --- /dev/null +++ b/maven-plugins/shade-extensions/src/test/resources/service-2.loader @@ -0,0 +1,2 @@ +# List of service contracts we want to support either from service registry, or from service loader +io.helidon.config.spi.ConfigMapperProvider \ No newline at end of file diff --git a/maven-plugins/shade-extensions/src/test/resources/service-expected.loader b/maven-plugins/shade-extensions/src/test/resources/service-expected.loader new file mode 100644 index 000000000..d07172ed9 --- /dev/null +++ b/maven-plugins/shade-extensions/src/test/resources/service-expected.loader @@ -0,0 +1,4 @@ +# List of service contracts we want to support either from service registry, or from service loader +io.helidon.config.spi.ConfigParser +io.helidon.config.spi.ConfigFilter +io.helidon.config.spi.ConfigMapperProvider diff --git a/maven-plugins/shade-extensions/src/test/resources/service-registry-1.json b/maven-plugins/shade-extensions/src/test/resources/service-registry-1.json new file mode 100644 index 000000000..f0dbbbf26 --- /dev/null +++ b/maven-plugins/shade-extensions/src/test/resources/service-registry-1.json @@ -0,0 +1,20 @@ +[ + { + "module": "io.helidon.config", + "services": [ + { + "descriptor": "io.helidon.config.ConfigProvider__ServiceDescriptor", + "contracts": [ + "io.helidon.common.config.Config", + "io.helidon.config.ConfigProvider" + ] + }, + { + "descriptor": "io.helidon.config.MetaConfig__ServiceDescriptor", + "contracts": [ + "io.helidon.config.MetaConfig" + ] + } + ] + } +] \ No newline at end of file diff --git a/maven-plugins/shade-extensions/src/test/resources/service-registry-2.json b/maven-plugins/shade-extensions/src/test/resources/service-registry-2.json new file mode 100644 index 000000000..c1b36f696 --- /dev/null +++ b/maven-plugins/shade-extensions/src/test/resources/service-registry-2.json @@ -0,0 +1,25 @@ +[ + { + "module": "io.helidon.integrations.oci.authentication.instance", + "services": [ + { + "weight": 60.0, + "descriptor": "io.helidon.integrations.oci.authentication.instance.AuthenticationMethodInstancePrincipal__ServiceDescriptor", + "contracts": [ + "io.helidon.integrations.oci.authentication.instance.AuthenticationMethodInstancePrincipal", + "io.helidon.integrations.oci.spi.OciAuthenticationMethod" + ] + }, + { + "descriptor": "io.helidon.integrations.oci.authentication.instance.InstancePrincipalBuilderProvider__ServiceDescriptor", + "contracts": [ + "com.oracle.bmc.auth.AbstractFederationClientAuthenticationDetailsProviderBuilder", + "com.oracle.bmc.auth.AbstractRequestingAuthenticationDetailsProvider.Builder", + "com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider.InstancePrincipalsAuthenticationDetailsProviderBuilder", + "io.helidon.integrations.oci.authentication.instance.InstancePrincipalBuilderProvider", + "java.util.function.Supplier" + ] + } + ] + } +] \ No newline at end of file diff --git a/pom.xml b/pom.xml index 358b100f9..07300af05 100644 --- a/pom.xml +++ b/pom.xml @@ -171,6 +171,7 @@ 3.1.12 3.5.3 1.10.0 + 3.5.1