001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.camel.model.rest;
018
019import java.util.ArrayList;
020import java.util.HashMap;
021import java.util.List;
022import java.util.Map;
023import javax.xml.bind.annotation.XmlAccessType;
024import javax.xml.bind.annotation.XmlAccessorType;
025import javax.xml.bind.annotation.XmlAttribute;
026import javax.xml.bind.annotation.XmlElement;
027import javax.xml.bind.annotation.XmlRootElement;
028
029import org.apache.camel.CamelContext;
030import org.apache.camel.spi.Metadata;
031import org.apache.camel.spi.RestConfiguration;
032import org.apache.camel.util.CamelContextHelper;
033
034/**
035 * To configure rest
036 */
037@Metadata(label = "rest")
038@XmlRootElement(name = "restConfiguration")
039@XmlAccessorType(XmlAccessType.FIELD)
040public class RestConfigurationDefinition {
041
042    @XmlAttribute
043    private String component;
044
045    @XmlAttribute @Metadata(label = "consumer", defaultValue = "swagger")
046    private String apiComponent;
047
048    @XmlAttribute @Metadata(label = "producer")
049    private String producerComponent;
050
051    @XmlAttribute
052    private String scheme;
053
054    @XmlAttribute
055    private String host;
056
057    @XmlAttribute
058    private String apiHost;
059
060    @XmlAttribute
061    private String port;
062
063    @XmlAttribute @Metadata(label = "producer")
064    private String producerApiDoc;
065
066    @XmlAttribute @Metadata(label = "consumer")
067    private String contextPath;
068
069    @XmlAttribute @Metadata(label = "consumer")
070    private String apiContextPath;
071
072    @XmlAttribute @Metadata(label = "consumer")
073    private String apiContextRouteId;
074
075    @XmlAttribute @Metadata(label = "consumer")
076    private String apiContextIdPattern;
077
078    @XmlAttribute @Metadata(label = "consumer")
079    private Boolean apiContextListing;
080
081    @XmlAttribute @Metadata(label = "consumer")
082    private Boolean apiVendorExtension;
083
084    @XmlAttribute @Metadata(label = "consumer")
085    private RestHostNameResolver hostNameResolver;
086
087    @XmlAttribute @Metadata(defaultValue = "off")
088    private RestBindingMode bindingMode;
089
090    @XmlAttribute
091    private Boolean skipBindingOnErrorCode;
092
093    @XmlAttribute @Metadata(label = "consumer")
094    private Boolean enableCORS;
095
096    @XmlAttribute
097    private String jsonDataFormat;
098
099    @XmlAttribute
100    private String xmlDataFormat;
101
102    @XmlElement(name = "componentProperty")
103    private List<RestPropertyDefinition> componentProperties = new ArrayList<RestPropertyDefinition>();
104
105    @XmlElement(name = "endpointProperty")
106    private List<RestPropertyDefinition> endpointProperties = new ArrayList<RestPropertyDefinition>();
107
108    @XmlElement(name = "consumerProperty") @Metadata(label = "consumer")
109    private List<RestPropertyDefinition> consumerProperties = new ArrayList<RestPropertyDefinition>();
110
111    @XmlElement(name = "dataFormatProperty")
112    private List<RestPropertyDefinition> dataFormatProperties = new ArrayList<RestPropertyDefinition>();
113
114    @XmlElement(name = "apiProperty") @Metadata(label = "consumer")
115    private List<RestPropertyDefinition> apiProperties = new ArrayList<RestPropertyDefinition>();
116
117    @XmlElement(name = "corsHeaders") @Metadata(label = "consumer")
118    private List<RestPropertyDefinition> corsHeaders = new ArrayList<RestPropertyDefinition>();
119
120    public String getComponent() {
121        return component;
122    }
123
124    /**
125     * The Camel Rest component to use for the REST transport (consumer), such as restlet, spark-rest.
126     * If no component has been explicit configured, then Camel will lookup if there is a Camel component
127     * that integrates with the Rest DSL, or if a org.apache.camel.spi.RestConsumerFactory is registered in the registry.
128     * If either one is found, then that is being used.
129     */
130    public void setComponent(String component) {
131        this.component = component;
132    }
133
134    public String getApiComponent() {
135        return apiComponent;
136    }
137
138    /**
139     * The name of the Camel component to use as the REST API (such as swagger)
140     */
141    public void setApiComponent(String apiComponent) {
142        this.apiComponent = apiComponent;
143    }
144
145    public String getProducerComponent() {
146        return producerComponent;
147    }
148
149    /**
150     * Sets the name of the Camel component to use as the REST producer
151     */
152    public void setProducerComponent(String producerComponent) {
153        this.producerComponent = producerComponent;
154    }
155
156    public String getScheme() {
157        return scheme;
158    }
159
160    /**
161     * The scheme to use for exposing the REST service. Usually http or https is supported.
162     * <p/>
163     * The default value is http
164     */
165    public void setScheme(String scheme) {
166        this.scheme = scheme;
167    }
168
169    public String getHost() {
170        return host;
171    }
172
173    /**
174     * The hostname to use for exposing the REST service.
175     */
176    public void setHost(String host) {
177        this.host = host;
178    }
179
180    public String getApiHost() {
181        return apiHost;
182    }
183
184    /**
185     * To use an specific hostname for the API documentation (eg swagger)
186     * <p/>
187     * This can be used to override the generated host with this configured hostname
188     */
189    public void setApiHost(String apiHost) {
190        this.apiHost = apiHost;
191    }
192
193    public String getPort() {
194        return port;
195    }
196
197    /**
198     * The port number to use for exposing the REST service.
199     * Notice if you use servlet component then the port number configured here does not apply,
200     * as the port number in use is the actual port number the servlet component is using.
201     * eg if using Apache Tomcat its the tomcat http port, if using Apache Karaf its the HTTP service in Karaf
202     * that uses port 8181 by default etc. Though in those situations setting the port number here,
203     * allows tooling and JMX to know the port number, so its recommended to set the port number
204     * to the number that the servlet engine uses.
205     */
206    public void setPort(String port) {
207        this.port = port;
208    }
209
210    public String getProducerApiDoc() {
211        return producerApiDoc;
212    }
213
214    /**
215     * Sets the location of the api document (swagger api) the REST producer will use
216     * to validate the REST uri and query parameters are valid accordingly to the api document.
217     * This requires adding camel-swagger-java to the classpath, and any miss configuration
218     * will let Camel fail on startup and report the error(s).
219     * <p/>
220     * The location of the api document is loaded from classpath by default, but you can use
221     * <tt>file:</tt> or <tt>http:</tt> to refer to resources to load from file or http url.
222     */
223    public void setProducerApiDoc(String producerApiDoc) {
224        this.producerApiDoc = producerApiDoc;
225    }
226
227    public String getContextPath() {
228        return contextPath;
229    }
230
231    /**
232     * Sets a leading context-path the REST services will be using.
233     * <p/>
234     * This can be used when using components such as <tt>camel-servlet</tt> where the deployed web application
235     * is deployed using a context-path. Or for components such as <tt>camel-jetty</tt> or <tt>camel-netty4-http</tt>
236     * that includes a HTTP server.
237     */
238    public void setContextPath(String contextPath) {
239        this.contextPath = contextPath;
240    }
241
242    public String getApiContextPath() {
243        return apiContextPath;
244    }
245
246    /**
247     * Sets a leading API context-path the REST API services will be using.
248     * <p/>
249     * This can be used when using components such as <tt>camel-servlet</tt> where the deployed web application
250     * is deployed using a context-path.
251     *
252     * @param contextPath the API context path
253     */
254    public void setApiContextPath(String contextPath) {
255        this.apiContextPath = contextPath;
256    }
257
258    public String getApiContextRouteId() {
259        return apiContextRouteId;
260    }
261
262    /**
263     * Sets the route id to use for the route that services the REST API.
264     * <p/>
265     * The route will by default use an auto assigned route id.
266     *
267     * @param apiContextRouteId  the route id
268     */
269    public void setApiContextRouteId(String apiContextRouteId) {
270        this.apiContextRouteId = apiContextRouteId;
271    }
272
273    public String getApiContextIdPattern() {
274        return apiContextIdPattern;
275    }
276
277    /**
278     * Sets an CamelContext id pattern to only allow Rest APIs from rest services within CamelContext's which name matches the pattern.
279     * <p/>
280     * The pattern <tt>#name#</tt> refers to the CamelContext name, to match on the current CamelContext only.
281     * For any other value, the pattern uses the rules from {@link org.apache.camel.util.EndpointHelper#matchPattern(String, String)}
282     *
283     * @param apiContextIdPattern  the pattern
284     */
285    public void setApiContextIdPattern(String apiContextIdPattern) {
286        this.apiContextIdPattern = apiContextIdPattern;
287    }
288
289    public Boolean getApiContextListing() {
290        return apiContextListing;
291    }
292
293    /**
294     * Sets whether listing of all available CamelContext's with REST services in the JVM is enabled. If enabled it allows to discover
295     * these contexts, if <tt>false</tt> then only the current CamelContext is in use.
296     */
297    public void setApiContextListing(Boolean apiContextListing) {
298        this.apiContextListing = apiContextListing;
299    }
300
301    public Boolean getApiVendorExtension() {
302        return apiVendorExtension;
303    }
304
305    /**
306     * Whether vendor extension is enabled in the Rest APIs. If enabled then Camel will include additional information
307     * as vendor extension (eg keys starting with x-) such as route ids, class names etc.
308     * Not all 3rd party API gateways and tools supports vendor-extensions when importing your API docs.
309     */
310    public void setApiVendorExtension(Boolean apiVendorExtension) {
311        this.apiVendorExtension = apiVendorExtension;
312    }
313
314    public RestHostNameResolver getHostNameResolver() {
315        return hostNameResolver;
316    }
317
318    /**
319     * If no hostname has been explicit configured, then this resolver is used to compute the hostname the REST service will be using.
320     */
321    public void setHostNameResolver(RestHostNameResolver hostNameResolver) {
322        this.hostNameResolver = hostNameResolver;
323    }
324
325    public RestBindingMode getBindingMode() {
326        return bindingMode;
327    }
328
329    /**
330     * Sets the binding mode to use.
331     * <p/>
332     * The default value is off
333     */
334    public void setBindingMode(RestBindingMode bindingMode) {
335        this.bindingMode = bindingMode;
336    }
337
338    public Boolean getSkipBindingOnErrorCode() {
339        return skipBindingOnErrorCode;
340    }
341
342    /**
343     * Whether to skip binding on output if there is a custom HTTP error code header.
344     * This allows to build custom error messages that do not bind to json / xml etc, as success messages otherwise will do.
345     */
346    public void setSkipBindingOnErrorCode(Boolean skipBindingOnErrorCode) {
347        this.skipBindingOnErrorCode = skipBindingOnErrorCode;
348    }
349
350    public Boolean getEnableCORS() {
351        return enableCORS;
352    }
353
354    /**
355     * Whether to enable CORS headers in the HTTP response.
356     * <p/>
357     * The default value is false.
358     */
359    public void setEnableCORS(Boolean enableCORS) {
360        this.enableCORS = enableCORS;
361    }
362
363    public String getJsonDataFormat() {
364        return jsonDataFormat;
365    }
366
367    /**
368     * Name of specific json data format to use.
369     * By default json-jackson will be used.
370     * Important: This option is only for setting a custom name of the data format, not to refer to an existing data format instance.
371     */
372    public void setJsonDataFormat(String jsonDataFormat) {
373        this.jsonDataFormat = jsonDataFormat;
374    }
375
376    public String getXmlDataFormat() {
377        return xmlDataFormat;
378    }
379
380    /**
381     * Name of specific XML data format to use.
382     * By default jaxb will be used.
383     * Important: This option is only for setting a custom name of the data format, not to refer to an existing data format instance.
384     */
385    public void setXmlDataFormat(String xmlDataFormat) {
386        this.xmlDataFormat = xmlDataFormat;
387    }
388
389    public List<RestPropertyDefinition> getComponentProperties() {
390        return componentProperties;
391    }
392
393    /**
394     * Allows to configure as many additional properties for the rest component in use.
395     */
396    public void setComponentProperties(List<RestPropertyDefinition> componentProperties) {
397        this.componentProperties = componentProperties;
398    }
399
400    public List<RestPropertyDefinition> getEndpointProperties() {
401        return endpointProperties;
402    }
403
404    /**
405     * Allows to configure as many additional properties for the rest endpoint in use.
406     */
407    public void setEndpointProperties(List<RestPropertyDefinition> endpointProperties) {
408        this.endpointProperties = endpointProperties;
409    }
410
411    public List<RestPropertyDefinition> getConsumerProperties() {
412        return consumerProperties;
413    }
414
415    /**
416     * Allows to configure as many additional properties for the rest consumer in use.
417     */
418    public void setConsumerProperties(List<RestPropertyDefinition> consumerProperties) {
419        this.consumerProperties = consumerProperties;
420    }
421
422    public List<RestPropertyDefinition> getDataFormatProperties() {
423        return dataFormatProperties;
424    }
425
426    /**
427     * Allows to configure as many additional properties for the data formats in use.
428     * For example set property prettyPrint to true to have json outputted in pretty mode.
429     * The properties can be prefixed to denote the option is only for either JSON or XML and for either the IN or the OUT.
430     * The prefixes are:
431     * <ul>
432     *     <li>json.in.</li>
433     *     <li>json.out.</li>
434     *     <li>xml.in.</li>
435     *     <li>xml.out.</li>
436     * </ul>
437     * For example a key with value "xml.out.mustBeJAXBElement" is only for the XML data format for the outgoing.
438     * A key without a prefix is a common key for all situations.
439     */
440    public void setDataFormatProperties(List<RestPropertyDefinition> dataFormatProperties) {
441        this.dataFormatProperties = dataFormatProperties;
442    }
443
444    public List<RestPropertyDefinition> getApiProperties() {
445        return apiProperties;
446    }
447
448    /**
449     * Allows to configure as many additional properties for the api documentation (swagger).
450     * For example set property api.title to my cool stuff
451     */
452    public void setApiProperties(List<RestPropertyDefinition> apiProperties) {
453        this.apiProperties = apiProperties;
454    }
455
456    public List<RestPropertyDefinition> getCorsHeaders() {
457        return corsHeaders;
458    }
459
460    /**
461     * Allows to configure custom CORS headers.
462     */
463    public void setCorsHeaders(List<RestPropertyDefinition> corsHeaders) {
464        this.corsHeaders = corsHeaders;
465    }
466
467    // Fluent API
468    //-------------------------------------------------------------------------
469
470    /**
471     * To use a specific Camel rest component (consumer)
472     */
473    public RestConfigurationDefinition component(String componentId) {
474        setComponent(componentId);
475        return this;
476    }
477
478    /**
479     * To use a specific Camel rest API component
480     */
481    public RestConfigurationDefinition apiComponent(String componentId) {
482        setApiComponent(componentId);
483        return this;
484    }
485
486    /**
487     * To use a specific Camel rest component (producer)
488     */
489    public RestConfigurationDefinition producerComponent(String componentId) {
490        setProducerComponent(componentId);
491        return this;
492    }
493
494    /**
495     * To use a specific scheme such as http/https
496     */
497    public RestConfigurationDefinition scheme(String scheme) {
498        setScheme(scheme);
499        return this;
500    }
501
502    /**
503     * To define the host to use, such as 0.0.0.0 or localhost
504     */
505    public RestConfigurationDefinition host(String host) {
506        setHost(host);
507        return this;
508    }
509
510    /**
511     * To define a specific host to use for API documentation (eg swagger) instead
512     * of using a generated API hostname that is relative to the REST service host.
513     */
514    public RestConfigurationDefinition apiHost(String host) {
515        setApiHost(host);
516        return this;
517    }
518
519    /**
520     * To specify the port number to use for the REST service
521     */
522    public RestConfigurationDefinition port(int port) {
523        setPort("" + port);
524        return this;
525    }
526
527    /**
528     * To specify the port number to use for the REST service
529     */
530    public RestConfigurationDefinition port(String port) {
531        setPort(port);
532        return this;
533    }
534
535    /**
536     * Sets the location of the api document (swagger api) the REST producer will use
537     * to validate the REST uri and query parameters are valid accordingly to the api document.
538     * This requires adding camel-swagger-java to the classpath, and any miss configuration
539     * will let Camel fail on startup and report the error(s).
540     * <p/>
541     * The location of the api document is loaded from classpath by default, but you can use
542     * <tt>file:</tt> or <tt>http:</tt> to refer to resources to load from file or http url.
543     */
544    public RestConfigurationDefinition producerApiDoc(String apiDoc) {
545        setProducerApiDoc(apiDoc);
546        return this;
547    }
548
549    /**
550     * Sets a leading context-path the REST services will be using.
551     * <p/>
552     * This can be used when using components such as <tt>camel-servlet</tt> where the deployed web application
553     * is deployed using a context-path. Or for components such as <tt>camel-jetty</tt> or <tt>camel-netty4-http</tt>
554     * that includes a HTTP server.
555     */
556    public RestConfigurationDefinition apiContextPath(String contextPath) {
557        setApiContextPath(contextPath);
558        return this;
559    }
560
561    /**
562     * Sets the route id to use for the route that services the REST API.
563     */
564    public RestConfigurationDefinition apiContextRouteId(String routeId) {
565        setApiContextRouteId(routeId);
566        return this;
567    }
568
569    /**
570     * Sets an CamelContext id pattern to only allow Rest APIs from rest services within CamelContext's which name matches the pattern.
571     * <p/>
572     * The pattern uses the rules from {@link org.apache.camel.util.EndpointHelper#matchPattern(String, String)}
573     */
574    public RestConfigurationDefinition apiContextIdPattern(String pattern) {
575        setApiContextIdPattern(pattern);
576        return this;
577    }
578
579    /**
580     * Sets whether listing of all available CamelContext's with REST services in the JVM is enabled. If enabled it allows to discover
581     * these contexts, if <tt>false</tt> then only the current CamelContext is in use.
582     */
583    public RestConfigurationDefinition apiContextListing(boolean listing) {
584        setApiContextListing(listing);
585        return this;
586    }
587
588    /**
589     * Whether vendor extension is enabled in the Rest APIs. If enabled then Camel will include additional information
590     * as vendor extension (eg keys starting with x-) such as route ids, class names etc.
591     * Some API tooling may not support vendor extensions and this option can then be turned off.
592     */
593    public RestConfigurationDefinition apiVendorExtension(boolean vendorExtension) {
594        setApiVendorExtension(vendorExtension);
595        return this;
596    }
597
598    /**
599     * Sets a leading context-path the REST services will be using.
600     * <p/>
601     * This can be used when using components such as <tt>camel-servlet</tt> where the deployed web application
602     * is deployed using a context-path.
603     */
604    public RestConfigurationDefinition contextPath(String contextPath) {
605        setContextPath(contextPath);
606        return this;
607    }
608
609    /**
610     * To specify the hostname resolver
611     */
612    public RestConfigurationDefinition hostNameResolver(RestHostNameResolver hostNameResolver) {
613        setHostNameResolver(hostNameResolver);
614        return this;
615    }
616
617    /**
618     * To specify the binding mode
619     */
620    public RestConfigurationDefinition bindingMode(RestBindingMode bindingMode) {
621        setBindingMode(bindingMode);
622        return this;
623    }
624
625    /**
626     * To specify whether to skip binding output if there is a custom HTTP error code
627     */
628    public RestConfigurationDefinition skipBindingOnErrorCode(boolean skipBindingOnErrorCode) {
629        setSkipBindingOnErrorCode(skipBindingOnErrorCode);
630        return this;
631    }
632
633    /**
634     * To specify whether to enable CORS which means Camel will automatic include CORS in the HTTP headers in the response.
635     */
636    public RestConfigurationDefinition enableCORS(boolean enableCORS) {
637        setEnableCORS(enableCORS);
638        return this;
639    }
640
641    /**
642     * To use a specific json data format
643     * <p/>
644     * <b>Important:</b> This option is only for setting a custom name of the data format, not to refer to an existing data format instance.
645     *
646     * @param name  name of the data format to {@link org.apache.camel.CamelContext#resolveDataFormat(java.lang.String) resolve}
647     */
648    public RestConfigurationDefinition jsonDataFormat(String name) {
649        setJsonDataFormat(name);
650        return this;
651    }
652
653    /**
654     * To use a specific XML data format
655     * <p/>
656     * <b>Important:</b> This option is only for setting a custom name of the data format, not to refer to an existing data format instance.
657     *
658     * @param name  name of the data format to {@link org.apache.camel.CamelContext#resolveDataFormat(java.lang.String) resolve}
659     */
660    public RestConfigurationDefinition xmlDataFormat(String name) {
661        setXmlDataFormat(name);
662        return this;
663    }
664
665    /**
666     * For additional configuration options on component level
667     * <p/>
668     * The value can use <tt>#</tt> to refer to a bean to lookup in the registry.
669     */
670    public RestConfigurationDefinition componentProperty(String key, String value) {
671        RestPropertyDefinition prop = new RestPropertyDefinition();
672        prop.setKey(key);
673        prop.setValue(value);
674        getComponentProperties().add(prop);
675        return this;
676    }
677
678    /**
679     * For additional configuration options on endpoint level
680     * <p/>
681     * The value can use <tt>#</tt> to refer to a bean to lookup in the registry.
682     */
683    public RestConfigurationDefinition endpointProperty(String key, String value) {
684        RestPropertyDefinition prop = new RestPropertyDefinition();
685        prop.setKey(key);
686        prop.setValue(value);
687        getEndpointProperties().add(prop);
688        return this;
689    }
690
691    /**
692     * For additional configuration options on consumer level
693     * <p/>
694     * The value can use <tt>#</tt> to refer to a bean to lookup in the registry.
695     */
696    public RestConfigurationDefinition consumerProperty(String key, String value) {
697        RestPropertyDefinition prop = new RestPropertyDefinition();
698        prop.setKey(key);
699        prop.setValue(value);
700        getConsumerProperties().add(prop);
701        return this;
702    }
703
704    /**
705     * For additional configuration options on data format level
706     * <p/>
707     * The value can use <tt>#</tt> to refer to a bean to lookup in the registry.
708     */
709    public RestConfigurationDefinition dataFormatProperty(String key, String value) {
710        RestPropertyDefinition prop = new RestPropertyDefinition();
711        prop.setKey(key);
712        prop.setValue(value);
713        getDataFormatProperties().add(prop);
714        return this;
715    }
716
717    /**
718     * For configuring an api property, such as <tt>api.title</tt>, or <tt>api.version</tt>.
719     */
720    public RestConfigurationDefinition apiProperty(String key, String value) {
721        RestPropertyDefinition prop = new RestPropertyDefinition();
722        prop.setKey(key);
723        prop.setValue(value);
724        getApiProperties().add(prop);
725        return this;
726    }
727
728    /**
729     * For configuring CORS headers
730     */
731    public RestConfigurationDefinition corsHeaderProperty(String key, String value) {
732        RestPropertyDefinition prop = new RestPropertyDefinition();
733        prop.setKey(key);
734        prop.setValue(value);
735        getCorsHeaders().add(prop);
736        return this;
737    }
738
739    /**
740     * Shortcut for setting the {@code Access-Control-Allow-Credentials} header.
741     */
742    public RestConfigurationDefinition corsAllowCredentials(boolean corsAllowCredentials) {
743        return corsHeaderProperty("Access-Control-Allow-Credentials", String.valueOf(corsAllowCredentials));
744    }
745
746
747    // Implementation
748    //-------------------------------------------------------------------------
749
750    /**
751     * Creates a {@link org.apache.camel.spi.RestConfiguration} instance based on the definition
752     *
753     * @param context     the camel context
754     * @return the configuration
755     * @throws Exception is thrown if error creating the configuration
756     */
757    public RestConfiguration asRestConfiguration(CamelContext context) throws Exception {
758        RestConfiguration answer = new RestConfiguration();
759        if (component != null) {
760            answer.setComponent(CamelContextHelper.parseText(context, component));
761        }
762        if (apiComponent != null) {
763            answer.setApiComponent(CamelContextHelper.parseText(context, apiComponent));
764        }
765        if (producerComponent != null) {
766            answer.setProducerComponent(CamelContextHelper.parseText(context, producerComponent));
767        }
768        if (scheme != null) {
769            answer.setScheme(CamelContextHelper.parseText(context, scheme));
770        }
771        if (host != null) {
772            answer.setHost(CamelContextHelper.parseText(context, host));
773        }
774        if (apiHost != null) {
775            answer.setApiHost(CamelContextHelper.parseText(context, apiHost));
776        }
777        if (port != null) {
778            answer.setPort(CamelContextHelper.parseInteger(context, port));
779        }
780        if (producerApiDoc != null) {
781            answer.setProducerApiDoc(CamelContextHelper.parseText(context, producerApiDoc));
782        }
783        if (apiContextPath != null) {
784            answer.setApiContextPath(CamelContextHelper.parseText(context, apiContextPath));
785        }
786        if (apiContextRouteId != null) {
787            answer.setApiContextRouteId(CamelContextHelper.parseText(context, apiContextRouteId));
788        }
789        if (apiContextIdPattern != null) {
790            // special to allow #name# to refer to itself
791            if ("#name#".equals(apiComponent)) {
792                answer.setApiContextIdPattern(context.getName());
793            } else {
794                answer.setApiContextIdPattern(CamelContextHelper.parseText(context, apiContextIdPattern));
795            }
796        }
797        if (apiContextListing != null) {
798            answer.setApiContextListing(apiContextListing);
799        }
800        if (apiVendorExtension != null) {
801            answer.setApiVendorExtension(apiVendorExtension);
802        }
803        if (contextPath != null) {
804            answer.setContextPath(CamelContextHelper.parseText(context, contextPath));
805        }
806        if (hostNameResolver != null) {
807            answer.setRestHostNameResolver(hostNameResolver.name());
808        }
809        if (bindingMode != null) {
810            answer.setBindingMode(bindingMode.name());
811        }
812        if (skipBindingOnErrorCode != null) {
813            answer.setSkipBindingOnErrorCode(skipBindingOnErrorCode);
814        }
815        if (enableCORS != null) {
816            answer.setEnableCORS(enableCORS);
817        }
818        if (jsonDataFormat != null) {
819            answer.setJsonDataFormat(jsonDataFormat);
820        }
821        if (xmlDataFormat != null) {
822            answer.setXmlDataFormat(xmlDataFormat);
823        }
824        if (!componentProperties.isEmpty()) {
825            Map<String, Object> props = new HashMap<String, Object>();
826            for (RestPropertyDefinition prop : componentProperties) {
827                String key = prop.getKey();
828                String value = CamelContextHelper.parseText(context, prop.getValue());
829                props.put(key, value);
830            }
831            answer.setComponentProperties(props);
832        }
833        if (!endpointProperties.isEmpty()) {
834            Map<String, Object> props = new HashMap<String, Object>();
835            for (RestPropertyDefinition prop : endpointProperties) {
836                String key = prop.getKey();
837                String value = CamelContextHelper.parseText(context, prop.getValue());
838                props.put(key, value);
839            }
840            answer.setEndpointProperties(props);
841        }
842        if (!consumerProperties.isEmpty()) {
843            Map<String, Object> props = new HashMap<String, Object>();
844            for (RestPropertyDefinition prop : consumerProperties) {
845                String key = prop.getKey();
846                String value = CamelContextHelper.parseText(context, prop.getValue());
847                props.put(key, value);
848            }
849            answer.setConsumerProperties(props);
850        }
851        if (!dataFormatProperties.isEmpty()) {
852            Map<String, Object> props = new HashMap<String, Object>();
853            for (RestPropertyDefinition prop : dataFormatProperties) {
854                String key = prop.getKey();
855                String value = CamelContextHelper.parseText(context, prop.getValue());
856                props.put(key, value);
857            }
858            answer.setDataFormatProperties(props);
859        }
860        if (!apiProperties.isEmpty()) {
861            Map<String, Object> props = new HashMap<String, Object>();
862            for (RestPropertyDefinition prop : apiProperties) {
863                String key = prop.getKey();
864                String value = CamelContextHelper.parseText(context, prop.getValue());
865                props.put(key, value);
866            }
867            answer.setApiProperties(props);
868        }
869        if (!corsHeaders.isEmpty()) {
870            Map<String, String> props = new HashMap<String, String>();
871            for (RestPropertyDefinition prop : corsHeaders) {
872                String key = prop.getKey();
873                String value = CamelContextHelper.parseText(context, prop.getValue());
874                props.put(key, value);
875            }
876            answer.setCorsHeaders(props);
877        }
878        return answer;
879    }
880
881}