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