This is an automated email from the ASF dual-hosted git repository. jamesnetherton pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/master by this push: new 64a485f Add configuration option to ignore unknown arguments 64a485f is described below commit 64a485fa09dee336a3307fbfa8125608c02ae47e Author: James Netherton <jamesnether...@gmail.com> AuthorDate: Tue Mar 16 08:52:38 2021 +0000 Add configuration option to ignore unknown arguments Fixes #2293 --- .../ROOT/pages/reference/extensions/main.adoc | 6 ++ .../main/deployment/CamelMainProcessor.java | 6 +- .../CamelMainUnknownArgumentFailTest.java | 71 ++++++++++++++++++ .../CamelMainUnknownArgumentIgnoreTest.java | 83 ++++++++++++++++++++++ .../CamelMainUnknownArgumentWarnTest.java | 83 ++++++++++++++++++++++ .../org/apache/camel/quarkus/main/CamelMain.java | 40 ++++++++++- .../apache/camel/quarkus/main/CamelMainConfig.java | 21 ++++++ .../camel/quarkus/main/CamelMainRecorder.java | 9 +-- 8 files changed, 312 insertions(+), 7 deletions(-) diff --git a/docs/modules/ROOT/pages/reference/extensions/main.adoc b/docs/modules/ROOT/pages/reference/extensions/main.adoc index 8c2ce7c..f3c6a80 100644 --- a/docs/modules/ROOT/pages/reference/extensions/main.adoc +++ b/docs/modules/ROOT/pages/reference/extensions/main.adoc @@ -39,6 +39,12 @@ Check the xref:user-guide/index.adoc[User guide] for more information about writ A timeout (with millisecond precision) to wait for `CamelMain++#++stop()` to finish | `java.time.Duration` | `PT3S` + +|icon:lock[title=Fixed at build time] [[quarkus.camel.main.arguments.on-unknown]]`link:#quarkus.camel.main.arguments.on-unknown[quarkus.camel.main.arguments.on-unknown]` + +The action to take when `CamelMain` encounters an unknown argument. fail - Prints the `CamelMain` usage statement and throws a `RuntimeException` ignore - Suppresses any warnings and the application startup proceeds as normal warn - Prints the `CamelMain` usage statement but allows the application startup to proceed as normal +| `org.apache.camel.quarkus.core.CamelConfig.FailureRemedy` +| `warn` |=== [.configuration-legend] diff --git a/extensions-core/main/deployment/src/main/java/org/apache/camel/quarkus/main/deployment/CamelMainProcessor.java b/extensions-core/main/deployment/src/main/java/org/apache/camel/quarkus/main/deployment/CamelMainProcessor.java index 12ae8c8..7106972 100644 --- a/extensions-core/main/deployment/src/main/java/org/apache/camel/quarkus/main/deployment/CamelMainProcessor.java +++ b/extensions-core/main/deployment/src/main/java/org/apache/camel/quarkus/main/deployment/CamelMainProcessor.java @@ -105,12 +105,14 @@ public class CamelMainProcessor { CamelContextBuildItem context, CamelRoutesCollectorBuildItem routesCollector, List<CamelRoutesBuilderClassBuildItem> routesBuilderClasses, - List<CamelMainListenerBuildItem> listeners) { + List<CamelMainListenerBuildItem> listeners, + CamelMainConfig config) { RuntimeValue<CamelMain> main = recorder.createCamelMain( context.getCamelContext(), routesCollector.getValue(), - beanContainer.getValue()); + beanContainer.getValue(), + config.arguments.onUnknown); for (CamelRoutesBuilderClassBuildItem item : routesBuilderClasses) { // don't add routes builders that are known by the container diff --git a/extensions-core/main/deployment/src/test/java/org/apache/camel/quarkus/main/deployment/CamelMainUnknownArgumentFailTest.java b/extensions-core/main/deployment/src/test/java/org/apache/camel/quarkus/main/deployment/CamelMainUnknownArgumentFailTest.java new file mode 100644 index 0000000..a48b1cc --- /dev/null +++ b/extensions-core/main/deployment/src/test/java/org/apache/camel/quarkus/main/deployment/CamelMainUnknownArgumentFailTest.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.quarkus.main.deployment; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.util.Properties; + +import javax.inject.Inject; + +import io.quarkus.test.QuarkusUnitTest; +import org.apache.camel.quarkus.main.CamelMain; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.Asset; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class CamelMainUnknownArgumentFailTest { + + @RegisterExtension + static final QuarkusUnitTest CONFIG = new QuarkusUnitTest() + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) + .addAsResource(applicationProperties(), "application.properties")); + + @Inject + CamelMain main; + + @Test + public void unknownArgumentThrowsException() { + Exception exception = Assertions.assertThrows(RuntimeException.class, () -> { + main.parseArguments(new String[] { "-d", "10", "-foo", "bar" }); + }); + assertEquals("CamelMain encountered unknown arguments", exception.getMessage()); + } + + public static Asset applicationProperties() { + Writer writer = new StringWriter(); + + Properties props = new Properties(); + props.setProperty("quarkus.banner.enabled", "false"); + props.setProperty("quarkus.camel.main.arguments.on-unknown", "fail"); + + try { + props.store(writer, ""); + } catch (IOException e) { + throw new RuntimeException(e); + } + + return new StringAsset(writer.toString()); + } +} diff --git a/extensions-core/main/deployment/src/test/java/org/apache/camel/quarkus/main/deployment/CamelMainUnknownArgumentIgnoreTest.java b/extensions-core/main/deployment/src/test/java/org/apache/camel/quarkus/main/deployment/CamelMainUnknownArgumentIgnoreTest.java new file mode 100644 index 0000000..6b17182 --- /dev/null +++ b/extensions-core/main/deployment/src/test/java/org/apache/camel/quarkus/main/deployment/CamelMainUnknownArgumentIgnoreTest.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.quarkus.main.deployment; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.io.StringWriter; +import java.io.Writer; +import java.util.Properties; + +import javax.inject.Inject; + +import io.quarkus.test.QuarkusUnitTest; +import org.apache.camel.quarkus.main.CamelMain; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.Asset; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static io.smallrye.common.constraint.Assert.assertFalse; + +public class CamelMainUnknownArgumentIgnoreTest { + + @RegisterExtension + static final QuarkusUnitTest CONFIG = new QuarkusUnitTest() + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) + .addAsResource(applicationProperties(), "application.properties")); + + @Inject + CamelMain main; + + @Test + public void unknownArgumentIgnored() { + PrintStream oldOut = System.out; + + try (ByteArrayOutputStream sysout = new ByteArrayOutputStream()) { + System.setOut(new PrintStream(sysout)); + + main.parseArguments(new String[] { "-d", "10", "-foo", "bar" }); + + String consoleContent = sysout.toString(); + assertFalse(consoleContent.contains("Unknown option: -foo")); + assertFalse(consoleContent.contains("Apache Camel Runner takes the following options")); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + System.setOut(oldOut); + } + } + + public static Asset applicationProperties() { + Writer writer = new StringWriter(); + + Properties props = new Properties(); + props.setProperty("quarkus.banner.enabled", "false"); + props.setProperty("quarkus.camel.main.arguments.on-unknown", "ignore"); + + try { + props.store(writer, ""); + } catch (IOException e) { + throw new RuntimeException(e); + } + + return new StringAsset(writer.toString()); + } +} diff --git a/extensions-core/main/deployment/src/test/java/org/apache/camel/quarkus/main/deployment/CamelMainUnknownArgumentWarnTest.java b/extensions-core/main/deployment/src/test/java/org/apache/camel/quarkus/main/deployment/CamelMainUnknownArgumentWarnTest.java new file mode 100644 index 0000000..27cb594 --- /dev/null +++ b/extensions-core/main/deployment/src/test/java/org/apache/camel/quarkus/main/deployment/CamelMainUnknownArgumentWarnTest.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.quarkus.main.deployment; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.io.StringWriter; +import java.io.Writer; +import java.util.Properties; + +import javax.inject.Inject; + +import io.quarkus.test.QuarkusUnitTest; +import org.apache.camel.quarkus.main.CamelMain; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.Asset; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class CamelMainUnknownArgumentWarnTest { + + @RegisterExtension + static final QuarkusUnitTest CONFIG = new QuarkusUnitTest() + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) + .addAsResource(applicationProperties(), "application.properties")); + + @Inject + CamelMain main; + + @Test + public void unknownArgumentLogsWarning() { + PrintStream oldOut = System.out; + + try (ByteArrayOutputStream sysout = new ByteArrayOutputStream()) { + System.setOut(new PrintStream(sysout)); + + main.parseArguments(new String[] { "-d", "10", "-foo", "bar" }); + + String consoleContent = sysout.toString(); + assertTrue(consoleContent.contains("Unknown option: -foo")); + assertTrue(consoleContent.contains("Apache Camel Runner takes the following options")); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + System.setOut(oldOut); + } + } + + public static Asset applicationProperties() { + Writer writer = new StringWriter(); + + Properties props = new Properties(); + props.setProperty("quarkus.banner.enabled", "false"); + props.setProperty("quarkus.camel.main.arguments.on-unknown", "warn"); + + try { + props.store(writer, ""); + } catch (IOException e) { + throw new RuntimeException(e); + } + + return new StringAsset(writer.toString()); + } +} diff --git a/extensions-core/main/runtime/src/main/java/org/apache/camel/quarkus/main/CamelMain.java b/extensions-core/main/runtime/src/main/java/org/apache/camel/quarkus/main/CamelMain.java index fbca1cf..965f2b6 100644 --- a/extensions-core/main/runtime/src/main/java/org/apache/camel/quarkus/main/CamelMain.java +++ b/extensions-core/main/runtime/src/main/java/org/apache/camel/quarkus/main/CamelMain.java @@ -16,8 +16,10 @@ */ package org.apache.camel.quarkus.main; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.LinkedList; import java.util.concurrent.atomic.AtomicBoolean; import io.quarkus.runtime.Quarkus; @@ -30,6 +32,7 @@ import org.apache.camel.main.MainListener; import org.apache.camel.main.MainShutdownStrategy; import org.apache.camel.main.RoutesConfigurer; import org.apache.camel.main.SimpleMainShutdownStrategy; +import org.apache.camel.quarkus.core.CamelConfig.FailureRemedy; import org.apache.camel.spi.HasCamelContext; import org.apache.camel.support.service.ServiceHelper; import org.slf4j.Logger; @@ -39,10 +42,12 @@ public final class CamelMain extends MainCommandLineSupport implements HasCamelC private static final Logger LOGGER = LoggerFactory.getLogger(CamelMain.class); private final AtomicBoolean engineStarted; + private final FailureRemedy failureRemedy; - public CamelMain(CamelContext camelContext) { + public CamelMain(CamelContext camelContext, FailureRemedy failureRemedy) { this.camelContext = camelContext; this.engineStarted = new AtomicBoolean(); + this.failureRemedy = failureRemedy; } protected void configureRoutes(CamelContext camelContext) throws Exception { @@ -162,4 +167,37 @@ public final class CamelMain extends MainCommandLineSupport implements HasCamelC runEngine(); return getExitCode(); } + + @Override + public void parseArguments(String[] arguments) { + LinkedList<String> args = new LinkedList<>(Arrays.asList(arguments)); + + boolean valid = true; + while (!args.isEmpty()) { + initOptions(); + String arg = args.removeFirst(); + + boolean handled = false; + for (Option option : options) { + if (option.processOption(arg, args)) { + handled = true; + break; + } + } + if (!handled && !failureRemedy.equals(FailureRemedy.ignore)) { + System.out.println("Unknown option: " + arg); + System.out.println(); + + valid = false; + break; + } + } + if (!valid) { + showOptions(); + completed(); + if (failureRemedy.equals(FailureRemedy.fail)) { + throw new RuntimeException("CamelMain encountered unknown arguments"); + } + } + } } diff --git a/extensions-core/main/runtime/src/main/java/org/apache/camel/quarkus/main/CamelMainConfig.java b/extensions-core/main/runtime/src/main/java/org/apache/camel/quarkus/main/CamelMainConfig.java index ff74c28..e249b93 100644 --- a/extensions-core/main/runtime/src/main/java/org/apache/camel/quarkus/main/CamelMainConfig.java +++ b/extensions-core/main/runtime/src/main/java/org/apache/camel/quarkus/main/CamelMainConfig.java @@ -22,6 +22,7 @@ import io.quarkus.runtime.annotations.ConfigGroup; import io.quarkus.runtime.annotations.ConfigItem; import io.quarkus.runtime.annotations.ConfigPhase; import io.quarkus.runtime.annotations.ConfigRoot; +import org.apache.camel.quarkus.core.CamelConfig.FailureRemedy; @ConfigRoot(name = "camel.main", phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED) public class CamelMainConfig { @@ -32,6 +33,12 @@ public class CamelMainConfig { @ConfigItem public ShutdownConfig shutdown; + /** + * Build time configuration options for {@link CamelMain} arguments + */ + @ConfigItem + public ArgumentConfig arguments; + @ConfigGroup public static class ShutdownConfig { /** @@ -40,4 +47,18 @@ public class CamelMainConfig { @ConfigItem(defaultValue = "PT3S") public Duration timeout; } + + @ConfigGroup + public static class ArgumentConfig { + + /** + * The action to take when {@link CamelMain} encounters an unknown argument. + * + * fail - Prints the {@link CamelMain} usage statement and throws a {@link RuntimeException} + * ignore - Suppresses any warnings and the application startup proceeds as normal + * warn - Prints the {@link CamelMain} usage statement but allows the application startup to proceed as normal + */ + @ConfigItem(defaultValue = "warn") + public FailureRemedy onUnknown; + } } diff --git a/extensions-core/main/runtime/src/main/java/org/apache/camel/quarkus/main/CamelMainRecorder.java b/extensions-core/main/runtime/src/main/java/org/apache/camel/quarkus/main/CamelMainRecorder.java index 37ef711..b8f87d8 100644 --- a/extensions-core/main/runtime/src/main/java/org/apache/camel/quarkus/main/CamelMainRecorder.java +++ b/extensions-core/main/runtime/src/main/java/org/apache/camel/quarkus/main/CamelMainRecorder.java @@ -27,6 +27,7 @@ import org.apache.camel.main.BaseMainSupport; import org.apache.camel.main.MainListener; import org.apache.camel.main.MainListenerSupport; import org.apache.camel.main.RoutesCollector; +import org.apache.camel.quarkus.core.CamelConfig.FailureRemedy; import org.apache.camel.quarkus.core.CamelContextCustomizer; import org.apache.camel.quarkus.core.CamelProducers; import org.apache.camel.quarkus.core.CamelRuntime; @@ -34,11 +35,11 @@ import org.apache.camel.quarkus.core.RegistryRoutesLoader; @Recorder public class CamelMainRecorder { - public RuntimeValue<CamelMain> createCamelMain( - RuntimeValue<CamelContext> runtime, + public RuntimeValue<CamelMain> createCamelMain(RuntimeValue<CamelContext> runtime, RuntimeValue<RoutesCollector> routesCollector, - BeanContainer container) { - CamelMain main = new CamelMain(runtime.getValue()); + BeanContainer container, + FailureRemedy failureRemedy) { + CamelMain main = new CamelMain(runtime.getValue(), failureRemedy); main.setRoutesCollector(routesCollector.getValue()); main.addMainListener(new CamelMainEventBridge());