http://git-wip-us.apache.org/repos/asf/camel/blob/21b0fe2c/components/camel-ahc-ws/src/main/docs/ahc-ws-component.adoc ---------------------------------------------------------------------- diff --git a/components/camel-ahc-ws/src/main/docs/ahc-ws-component.adoc b/components/camel-ahc-ws/src/main/docs/ahc-ws-component.adoc index b49ec26..ac40edc 100644 --- a/components/camel-ahc-ws/src/main/docs/ahc-ws-component.adoc +++ b/components/camel-ahc-ws/src/main/docs/ahc-ws-component.adoc @@ -69,7 +69,7 @@ The AHC Websocket component supports 6 options which are listed below. // endpoint options: START -The AHC Websocket component supports 18 endpoint options which are listed below: +The AHC Websocket component supports 17 endpoint options which are listed below: {% raw %} [width="100%",cols="2,1,1m,1m,5",options="header"] @@ -87,7 +87,6 @@ The AHC Websocket component supports 18 endpoint options which are listed below: | exceptionHandler | consumer (advanced) | | ExceptionHandler | To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this options is not in use. By default the consumer will deal with exceptions that will be logged at WARN/ERROR level and ignored. | exchangePattern | consumer (advanced) | | ExchangePattern | Sets the exchange pattern when the consumer creates an exchange. | connectionClose | producer | false | boolean | Define if the Connection Close header has to be added to HTTP Request. This parameter is false by default -| cookieHandler | producer | | CookieHandler | Configure a cookie handler to maintain a HTTP session | useStreaming | producer | false | boolean | To enable streaming to send data as multiple text fragments. | clientConfig | advanced | | AsyncHttpClientConfig | To configure the AsyncHttpClient to use a custom com.ning.http.client.AsyncHttpClientConfig instance. | clientConfigOptions | advanced | | Map | To configure the AsyncHttpClientConfig using the key/values from the Map.
http://git-wip-us.apache.org/repos/asf/camel/blob/21b0fe2c/components/camel-atmosphere-websocket/src/main/docs/atmosphere-websocket-component.adoc ---------------------------------------------------------------------- diff --git a/components/camel-atmosphere-websocket/src/main/docs/atmosphere-websocket-component.adoc b/components/camel-atmosphere-websocket/src/main/docs/atmosphere-websocket-component.adoc index 6bc2297..e43c7f1 100644 --- a/components/camel-atmosphere-websocket/src/main/docs/atmosphere-websocket-component.adoc +++ b/components/camel-atmosphere-websocket/src/main/docs/atmosphere-websocket-component.adoc @@ -48,7 +48,7 @@ The Atmosphere Websocket component supports 7 options which are listed below. | Name | Java Type | Description | servletName | String | Default name of servlet to use. The default name is CamelServlet. | httpRegistry | HttpRegistry | To use a custom org.apache.camel.component.servlet.HttpRegistry. -| attachmentMultipartBinding | boolean | Whether to automatic bind multipart/form-data as attachments on the Camel Exchange. The options attachmentMultipartBinding=true and disableStreamCache=false cannot work together. Remove disableStreamCache to use AttachmentMultipartBinding. This is turn off by default as this may require servlet specific configuration to enable this when using Servlet's. +| attachmentMultipartBinding | boolean | Whether to automatic bind multipart/form-data as attachments on the Camel Exchange. This is turn off by default as this may require servet specific configuration to enable this when using Servlet's. | httpBinding | HttpBinding | To use a custom HttpBinding to control the mapping between Camel message and HttpClient. | httpConfiguration | HttpConfiguration | To use the shared HttpConfiguration as base configuration. | allowJavaSerializedObject | boolean | Whether to allow java serialization when a request uses context-type=application/x-java-serialized-object This is by default turned off. If you enable this then be aware that Java will deserialize the incoming data from the request to Java and that can be a potential security risk. @@ -61,7 +61,7 @@ The Atmosphere Websocket component supports 7 options which are listed below. // endpoint options: START -The Atmosphere Websocket component supports 36 endpoint options which are listed below: +The Atmosphere Websocket component supports 34 endpoint options which are listed below: {% raw %} [width="100%",cols="2,1,1m,1m,5",options="header"] @@ -84,13 +84,11 @@ The Atmosphere Websocket component supports 36 endpoint options which are listed | responseBufferSize | consumer | | Integer | To use a custom buffer size on the javax.servlet.ServletResponse. | servletName | consumer | CamelServlet | String | Name of the servlet to use | traceEnabled | consumer | false | boolean | Specifies whether to enable HTTP TRACE for this Servlet consumer. By default TRACE is turned off. -| attachmentMultipartBinding | consumer (advanced) | false | boolean | Whether to automatic bind multipart/form-data as attachments on the Camel Exchange. The options attachmentMultipartBinding=true and disableStreamCache=false cannot work together. Remove disableStreamCache to use AttachmentMultipartBinding. This is turn off by default as this may require servlet specific configuration to enable this when using Servlet's. | exceptionHandler | consumer (advanced) | | ExceptionHandler | To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this options is not in use. By default the consumer will deal with exceptions that will be logged at WARN/ERROR level and ignored. | exchangePattern | consumer (advanced) | | ExchangePattern | Sets the exchange pattern when the consumer creates an exchange. | authMethodPriority | producer | | String | Authentication method for proxy either as Basic Digest or NTLM. | bridgeEndpoint | producer | false | boolean | If the option is true HttpProducer will ignore the Exchange.HTTP_URI header and use the endpoint's URI for request. You may also set the option throwExceptionOnFailure to be false to let the HttpProducer send all the fault response back. | connectionClose | producer | false | boolean | Specifies whether a Connection Close header must be added to HTTP Request. By default connectionClose is false. -| cookieHandler | producer | | CookieHandler | Configure a cookie handler to maintain a HTTP session | copyHeaders | producer | true | boolean | If this option is true then IN exchange headers will be copied to OUT exchange headers according to copy strategy. Setting this to false allows to only include the headers from the HTTP response (not propagating IN headers). | ignoreResponseBody | producer | false | boolean | If this option is true The http producer won't read response body and cache the input stream | okStatusCodeRange | producer | 200-299 | String | The status codes which is considered a success response. The values are inclusive. The range must be defined as from-to with the dash included. http://git-wip-us.apache.org/repos/asf/camel/blob/21b0fe2c/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/ComponentConfigurationProperties.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/ComponentConfigurationProperties.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/ComponentConfigurationProperties.java new file mode 100644 index 0000000..804dc45 --- /dev/null +++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/ComponentConfigurationProperties.java @@ -0,0 +1,33 @@ +/** + * 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.spring.boot; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "camel.component") +public class ComponentConfigurationProperties { + private boolean enabled = true; + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/21b0fe2c/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/DataFormatConfigurationProperties.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/DataFormatConfigurationProperties.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/DataFormatConfigurationProperties.java new file mode 100644 index 0000000..5c0e3d8 --- /dev/null +++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/DataFormatConfigurationProperties.java @@ -0,0 +1,33 @@ +/** + * 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.spring.boot; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "camel.dataformat") +public class DataFormatConfigurationProperties { + private boolean enabled = true; + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/21b0fe2c/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/LanguageConfigurationProperties.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/LanguageConfigurationProperties.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/LanguageConfigurationProperties.java new file mode 100644 index 0000000..d577a3a --- /dev/null +++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/LanguageConfigurationProperties.java @@ -0,0 +1,33 @@ +/** + * 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.spring.boot; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "camel.language") +public class LanguageConfigurationProperties { + private boolean enabled = true; + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/21b0fe2c/components/readme.adoc ---------------------------------------------------------------------- diff --git a/components/readme.adoc b/components/readme.adoc index dbbc3ff..a13518c 100644 --- a/components/readme.adoc +++ b/components/readme.adoc @@ -372,7 +372,7 @@ Components | link:camel-netty-http/src/main/docs/netty-http-component.adoc[Netty HTTP] (camel-netty-http) + `netty-http:protocol:host:port/path` | *deprecated* Netty HTTP server and client using the Netty 3.x library. -| link:camel-netty4/src/main/docs/netty4-component.adoc[Netty4] (camel-netty4) + +| link:null/src/main/docs/netty4-component.adoc[Netty4] (null) + `netty4:protocol:host:port` | Socket level networking using TCP or UDP with the Netty 4.x library. | link:camel-netty4-http/src/main/docs/netty4-http-component.adoc[Netty4 HTTP] (camel-netty4-http) + @@ -477,7 +477,7 @@ Components | link:camel-spring-batch/src/main/docs/spring-batch-component.adoc[Spring Batch] (camel-spring-batch) + `spring-batch:jobName` | The spring-batch component allows to send messages to Spring Batch for further processing. -| link:camel-spring/src/main/docs/spring-event-component.adoc[Spring Event] (camel-spring) + +| link:null/src/main/docs/spring-event-component.adoc[Spring Event] (null) + `spring-event:name` | The spring-event component allows to listen for Spring Application Events. | link:camel-spring-integration/src/main/docs/spring-integration-component.adoc[Spring Integration] (camel-spring-integration) + http://git-wip-us.apache.org/repos/asf/camel/blob/21b0fe2c/platforms/spring-boot/spring-boot-dm/pom.xml ---------------------------------------------------------------------- diff --git a/platforms/spring-boot/spring-boot-dm/pom.xml b/platforms/spring-boot/spring-boot-dm/pom.xml index 279842f..0eadbd4 100644 --- a/platforms/spring-boot/spring-boot-dm/pom.xml +++ b/platforms/spring-boot/spring-boot-dm/pom.xml @@ -38,7 +38,7 @@ <properties> <!-- Spring-Boot target version --> - <spring-boot-version>1.4.1.RELEASE</spring-boot-version> + <spring-boot-version>1.4.2.RELEASE</spring-boot-version> <!-- The following dependencies should be aligned with the ones in standard camel parent --> <avro-version>1.8.1</avro-version> http://git-wip-us.apache.org/repos/asf/camel/blob/21b0fe2c/tooling/maven/camel-package-maven-plugin/pom.xml ---------------------------------------------------------------------- diff --git a/tooling/maven/camel-package-maven-plugin/pom.xml b/tooling/maven/camel-package-maven-plugin/pom.xml index 0eaa61d..24fc0ff 100644 --- a/tooling/maven/camel-package-maven-plugin/pom.xml +++ b/tooling/maven/camel-package-maven-plugin/pom.xml @@ -92,6 +92,12 @@ <artifactId>commons-io</artifactId> </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>${gson-version}</version> + </dependency> + <!-- roaster to create java source for Spring Boot auto configuration support --> <dependency> <groupId>org.jboss.forge.roaster</groupId> http://git-wip-us.apache.org/repos/asf/camel/blob/21b0fe2c/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/SpringBootAutoConfigurationMojo.java ---------------------------------------------------------------------- diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/SpringBootAutoConfigurationMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/SpringBootAutoConfigurationMojo.java index 8fbc886..1979368 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/SpringBootAutoConfigurationMojo.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/SpringBootAutoConfigurationMojo.java @@ -16,9 +16,11 @@ */ package org.apache.camel.maven.packaging; +import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Modifier; @@ -40,6 +42,8 @@ import java.util.TreeSet; import java.util.regex.Pattern; import java.util.stream.Collectors; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import org.apache.camel.maven.packaging.model.ComponentModel; import org.apache.camel.maven.packaging.model.ComponentOptionModel; import org.apache.camel.maven.packaging.model.DataFormatModel; @@ -65,14 +69,21 @@ import org.jboss.forge.roaster.model.source.MethodSource; import org.jboss.forge.roaster.model.source.PropertySource; import org.jboss.forge.roaster.model.util.Strings; import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionMessage; +import org.springframework.boot.autoconfigure.condition.ConditionOutcome; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.SpringBootCondition; +import org.springframework.boot.bind.RelaxedPropertyResolver; import org.springframework.boot.context.properties.DeprecatedConfigurationProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; +import org.springframework.core.type.AnnotatedTypeMetadata; import static org.apache.camel.maven.packaging.JSonSchemaHelper.getSafeValue; import static org.apache.camel.maven.packaging.PackageHelper.loadText; @@ -207,7 +218,7 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { if (hasOptions) { createComponentConfigurationSource(pkg, model, overrideComponentName); } - createComponentAutoConfigurationSource(pkg, model, aliases, hasOptions); + createComponentAutoConfigurationSource(pkg, model, aliases, hasOptions, overrideComponentName); createComponentSpringFactorySource(pkg, model); } } @@ -248,16 +259,16 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { int pos = model.getJavaType().lastIndexOf("."); String pkg = model.getJavaType().substring(0, pos) + ".springboot"; - String overrideDataformatName = null; + String overrideDataFormatName = null; if (aliases.size() > 1) { // determine component name when there are multiple ones - overrideDataformatName = model.getArtifactId().replace("camel-", ""); + overrideDataFormatName = model.getArtifactId().replace("camel-", ""); } if (hasOptions) { - createDataFormatConfigurationSource(pkg, model, overrideDataformatName); + createDataFormatConfigurationSource(pkg, model, overrideDataFormatName); } - createDataFormatAutoConfigurationSource(pkg, model, aliases, hasOptions); + createDataFormatAutoConfigurationSource(pkg, model, aliases, hasOptions, overrideDataFormatName); createDataFormatSpringFactorySource(pkg, model); } } @@ -308,7 +319,7 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { if (hasOptions) { createLanguageConfigurationSource(pkg, model, overrideLanguageName); } - createLanguageAutoConfigurationSource(pkg, model, aliases, hasOptions); + createLanguageAutoConfigurationSource(pkg, model, aliases, hasOptions, overrideLanguageName); createLanguageSpringFactorySource(pkg, model); } } @@ -765,12 +776,15 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { writeSourceIfChanged(javaClass, fileName); } - private void createComponentAutoConfigurationSource(String packageName, ComponentModel model, List<String> componentAliases, boolean hasOptions) throws MojoFailureException { + private void createComponentAutoConfigurationSource( + String packageName, ComponentModel model, List<String> componentAliases, boolean hasOptions, String overrideComponentName) throws MojoFailureException { + final JavaClassSource javaClass = Roaster.create(JavaClassSource.class); int pos = model.getJavaType().lastIndexOf("."); String name = model.getJavaType().substring(pos + 1); name = name.replace("Component", "ComponentAutoConfiguration"); + javaClass.setPackage(packageName).setName(name); String doc = "Generated by camel-package-maven-plugin - do not edit this file!"; @@ -778,6 +792,7 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { javaClass.addAnnotation(Configuration.class); javaClass.addAnnotation(ConditionalOnBean.class).setStringValue("type", "org.apache.camel.spring.boot.CamelAutoConfiguration"); + javaClass.addAnnotation(Conditional.class).setLiteralValue(name + ".Condition.class"); javaClass.addAnnotation(AutoConfigureAfter.class).setStringValue("name", "org.apache.camel.spring.boot.CamelAutoConfiguration"); String configurationName = name.replace("ComponentAutoConfiguration", "ComponentConfiguration"); @@ -817,19 +832,32 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { method.addAnnotation(ConditionalOnClass.class).setLiteralValue("value", "CamelContext.class"); method.addAnnotation(ConditionalOnMissingBean.class).setLiteralValue("value", model.getShortJavaType() + ".class"); + // Generate Condition + javaClass.addNestedType(createConditionType( + javaClass, + "camel.component", + (overrideComponentName != null ? overrideComponentName : model.getScheme()).toLowerCase(Locale.US) + )); + sortImports(javaClass); String fileName = packageName.replaceAll("\\.", "\\/") + "/" + name + ".java"; - writeSourceIfChanged(javaClass, fileName); + writeAdditionalSpringMetaData( + "camel", + "component", + (overrideComponentName != null ? overrideComponentName : model.getScheme()).toLowerCase(Locale.US)); } - private void createDataFormatAutoConfigurationSource(String packageName, DataFormatModel model, List<String> dataFormatAliases, boolean hasOptions) throws MojoFailureException { + private void createDataFormatAutoConfigurationSource( + String packageName, DataFormatModel model, List<String> dataFormatAliases, boolean hasOptions, String overrideDataFormatName) throws MojoFailureException { + final JavaClassSource javaClass = Roaster.create(JavaClassSource.class); int pos = model.getJavaType().lastIndexOf("."); String name = model.getJavaType().substring(pos + 1); - name = name.replace("DataFormat", "DataFormatAutoConfiguration"); + name = name.replace("DataFormat", "DataFormatAutoConfiguration"); + javaClass.setPackage(packageName).setName(name); String doc = "Generated by camel-package-maven-plugin - do not edit this file!"; @@ -837,6 +865,7 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { javaClass.addAnnotation(Configuration.class); javaClass.addAnnotation(ConditionalOnBean.class).setStringValue("type", "org.apache.camel.spring.boot.CamelAutoConfiguration"); + javaClass.addAnnotation(Conditional.class).setLiteralValue(name + ".Condition.class"); javaClass.addAnnotation(AutoConfigureAfter.class).setStringValue("name", "org.apache.camel.spring.boot.CamelAutoConfiguration"); String configurationName = name.replace("DataFormatAutoConfiguration", "DataFormatConfiguration"); @@ -869,7 +898,6 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { method.addParameter(configurationName, "configuration"); } - // Determine all the aliases // adding the '-dataformat' suffix to prevent collision with component names String[] springBeanAliases = dataFormatAliases.stream().map(alias -> alias + "-dataformat").toArray(size -> new String[size]); @@ -878,19 +906,32 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { method.addAnnotation(ConditionalOnClass.class).setLiteralValue("value", "CamelContext.class"); method.addAnnotation(ConditionalOnMissingBean.class).setLiteralValue("value", model.getShortJavaType() + ".class"); + // Generate Condition + javaClass.addNestedType(createConditionType( + javaClass, + "camel.dataformat", + (overrideDataFormatName != null ? overrideDataFormatName : model.getName()).toLowerCase(Locale.US) + )); + sortImports(javaClass); String fileName = packageName.replaceAll("\\.", "\\/") + "/" + name + ".java"; - writeSourceIfChanged(javaClass, fileName); + writeAdditionalSpringMetaData( + "camel", + "dataformat", + (overrideDataFormatName != null ? overrideDataFormatName : model.getName()).toLowerCase(Locale.US)); } - private void createLanguageAutoConfigurationSource(String packageName, LanguageModel model, List<String> languageAliases, boolean hasOptions) throws MojoFailureException { + private void createLanguageAutoConfigurationSource( + String packageName, LanguageModel model, List<String> languageAliases, boolean hasOptions, String overrideLanguageName) throws MojoFailureException { + final JavaClassSource javaClass = Roaster.create(JavaClassSource.class); int pos = model.getJavaType().lastIndexOf("."); String name = model.getJavaType().substring(pos + 1); name = name.replace("Language", "LanguageAutoConfiguration"); + javaClass.setPackage(packageName).setName(name); String doc = "Generated by camel-package-maven-plugin - do not edit this file!"; @@ -898,6 +939,7 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { javaClass.addAnnotation(Configuration.class); javaClass.addAnnotation(ConditionalOnBean.class).setStringValue("type", "org.apache.camel.spring.boot.CamelAutoConfiguration"); + javaClass.addAnnotation(Conditional.class).setLiteralValue(name + ".Condition.class"); javaClass.addAnnotation(AutoConfigureAfter.class).setStringValue("name", "org.apache.camel.spring.boot.CamelAutoConfiguration"); String configurationName = name.replace("LanguageAutoConfiguration", "LanguageConfiguration"); @@ -927,7 +969,6 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { method.addParameter("CamelContext", "camelContext"); method.addParameter(configurationName, "configuration"); - // Determine all the aliases // adding the '-language' suffix to prevent collision with component names String[] springBeanAliases = languageAliases.stream().map(alias -> alias + "-language").toArray(size -> new String[size]); @@ -936,11 +977,21 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { method.addAnnotation(ConditionalOnClass.class).setLiteralValue("value", "CamelContext.class"); method.addAnnotation(ConditionalOnMissingBean.class).setLiteralValue("value", model.getShortJavaType() + ".class"); + // Generate Condition + javaClass.addNestedType(createConditionType( + javaClass, + "camel.language", + (overrideLanguageName != null ? overrideLanguageName : model.getName()).toLowerCase(Locale.US) + )); + sortImports(javaClass); String fileName = packageName.replaceAll("\\.", "\\/") + "/" + name + ".java"; - writeSourceIfChanged(javaClass, fileName); + writeAdditionalSpringMetaData( + "camel", + "language", + (overrideLanguageName != null ? overrideLanguageName : model.getName()).toLowerCase(Locale.US)); } private void createComponentSpringFactorySource(String packageName, ComponentModel model) throws MojoFailureException { @@ -1442,6 +1493,52 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { } } + private void writeAdditionalSpringMetaData(String prefix, String type, String name) throws MojoFailureException { + String fullQualifiedName = prefix + "." + type + "." + name + "." + "enabled"; + String fileName = "META-INF/additional-spring-configuration-metadata.json"; + File target = new File(SpringBootHelper.starterResourceDir(baseDir, project.getArtifactId()), fileName); + + deleteFileOnMainArtifact(target); + + try { + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + Map<String, Object> map = null; + List<Map<String, Object>> properties = null; + + if (target.exists()) { + BufferedReader br = new BufferedReader(new FileReader(target)); + map = gson.fromJson(br, Map.class); + + properties = (List<Map<String, Object>>)map.get("properties"); + if (properties != null && properties.stream().anyMatch(m -> fullQualifiedName.equals(m.get("name")))) { + getLog().debug("No changes to existing file: " + target); + return; + } + } + + Map<String, Object> meta = new HashMap(); + meta.put("name", fullQualifiedName); + meta.put("type", "java.lang.Boolean"); + meta.put("defaultValue", true); + meta.put("description", "Enable " + name + " " + type); + + if (properties == null) { + properties = new ArrayList<>(1); + } + + if (map == null) { + map = new HashMap(); + } + + properties.add(meta); + map.put("properties", properties); + + FileUtils.write(target, gson.toJson(map)); + } catch (Exception e) { + throw new MojoFailureException("IOError with file " + target, e); + } + } + private void deleteFileOnMainArtifact(File starterFile) { if (!DELETE_FILES_ON_MAIN_ARTIFACTS) { return; @@ -1457,4 +1554,47 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { } } + private JavaClassSource createConditionType(JavaClassSource parentClass, String prefix, String type) { + parentClass.addImport(ConditionMessage.class); + parentClass.addImport(ConditionContext.class); + parentClass.addImport(ConditionOutcome.class); + parentClass.addImport(RelaxedPropertyResolver.class); + parentClass.addImport(AnnotatedTypeMetadata.class); + parentClass.addImport(SpringBootCondition.class); + + JavaClassSource condition = Roaster.create(JavaClassSource.class); + condition.setName("Condition"); + condition.extendSuperType(SpringBootCondition.class); + condition.setPublic(); + condition.setStatic(true); + + String fullQualifiedType = prefix.endsWith(".") ? prefix + type : prefix + "." + type; + + MethodSource<JavaClassSource> isEnabled = condition.addMethod(); + isEnabled.setName("isEnabled"); + isEnabled.setPrivate(); + isEnabled.addParameter(ConditionContext.class, "context"); + isEnabled.addParameter(String.class, "prefix"); + isEnabled.addParameter(boolean.class, "defaultValue"); + isEnabled.setReturnType(boolean.class); + isEnabled.setBody(new StringBuilder() + .append("RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(context.getEnvironment(), prefix);\n") + .append("return resolver.getProperty(\"enabled\", Boolean.class, defaultValue);") + .toString() + ); + + MethodSource<JavaClassSource> matchMethod = condition.getMethod("getMatchOutcome", ConditionContext.class, AnnotatedTypeMetadata.class); + matchMethod.setBody(new StringBuilder() + .append("boolean groupEnabled = isEnabled(conditionContext, \"").append(prefix).append(".\", true);\n") + .append("ConditionMessage.Builder message = ConditionMessage.forCondition(\"").append(fullQualifiedType).append("\");\n") + .append("if (isEnabled(conditionContext, \"").append(fullQualifiedType).append(".\", groupEnabled)) {\n") + .append(" return ConditionOutcome.match(message.because(\"enabled\"));\n") + .append("}\n") + .append("return ConditionOutcome.noMatch(message.because(\"not enabled\"));\n") + .toString() + ); + + return condition; + } + }
