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