| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.camel.component.rest.openapi; |
| |
| import java.net.URI; |
| import java.util.Map; |
| |
| import org.apache.camel.CamelContext; |
| import org.apache.camel.Endpoint; |
| import org.apache.camel.SSLContextParametersAware; |
| import org.apache.camel.spi.Metadata; |
| import org.apache.camel.spi.RestProducerFactory; |
| import org.apache.camel.spi.annotations.Component; |
| import org.apache.camel.support.DefaultComponent; |
| import org.apache.camel.support.jsse.SSLContextParameters; |
| |
| import static org.apache.camel.component.rest.openapi.RestOpenApiHelper.isHostParam; |
| import static org.apache.camel.component.rest.openapi.RestOpenApiHelper.isMediaRange; |
| import static org.apache.camel.util.ObjectHelper.notNull; |
| import static org.apache.camel.util.StringHelper.notEmpty; |
| |
| /** |
| * An awesome REST component backed by OpenApi specifications. Creates endpoints |
| * that connect to REST APIs defined by OpenApi specification. This component |
| * delegates to other {@link RestProducerFactory} components to act as REST |
| * clients, but it configures them from OpenApi specification. Client needs to |
| * point to operation that it wants to invoke via REST, provide any additional |
| * HTTP headers as headers in the Camel message, and any payload as the body of |
| * the incoming message. |
| * <p> |
| * Example usage using Java DSL: |
| * <p> |
| * |
| * <pre> |
| * from(...).to("rest-openapi:https://petstore3.swagger.io/api/v3/openapi.json#getPetById") |
| * </pre> |
| * |
| * This relies on only one {@link RestProducerFactory} component being available |
| * to Camel, you can use specific, for instance preconfigured component by using |
| * the {@code componentName} endpoint property. For example using Undertow |
| * component in Java DSL: |
| * <p> |
| * |
| * <pre> |
| * Component undertow = new UndertowComponent(); |
| * undertow.setSslContextParameters(...); |
| * //... |
| * camelContext.addComponent("myUndertow", undertow); |
| * |
| * from(...).to("rest-openapi:https://petstore3.swagger.io/api/v3/openapi.json#getPetById?componentName=myUndertow") |
| * </pre> |
| * |
| * The most concise way of using this component would be to define it in the |
| * Camel context under a meaningful name, for example: |
| * |
| * <pre> |
| * Component petstore = new RestOpenApiComponent(); |
| * petstore.setSpecificationUri("https://petstore3.swagger.io/api/v3/openapi.json"); |
| * petstore.setComponentName("undertow"); |
| * //... |
| * camelContext.addComponent("petstore", petstore); |
| * |
| * from(...).to("petstore:getPetById") |
| * </pre> |
| */ |
| @Component("rest-openapi") |
| public final class RestOpenApiComponent extends DefaultComponent implements SSLContextParametersAware { |
| public static final String DEFAULT_BASE_PATH = "/"; |
| |
| static final URI DEFAULT_SPECIFICATION_URI = URI.create(RestOpenApiComponent.DEFAULT_SPECIFICATION_URI_STR); |
| |
| static final String DEFAULT_SPECIFICATION_URI_STR = "openapi.json"; |
| |
| @Metadata( |
| description = "API basePath, for example \"`/v2`\". Default is unset, if set overrides the value present in OpenApi specification.", |
| defaultValue = "", label = "producer") |
| private String basePath = ""; |
| |
| @Metadata(description = "Name of the Camel component that will perform the requests. The component must be present" |
| + " in Camel registry and it must implement RestProducerFactory service provider interface. If not set" |
| + " CLASSPATH is searched for single component that implements RestProducerFactory SPI. Can be overridden in" |
| + " endpoint configuration.", label = "producer", required = false) |
| private String componentName; |
| |
| @Metadata( |
| description = "What payload type this component capable of consuming. Could be one type, like `application/json`" |
| + " or multiple types as `application/json, application/xml; q=0.5` according to the RFC7231. This equates" |
| + " to the value of `Accept` HTTP header. If set overrides any value found in the OpenApi specification." |
| + " Can be overridden in endpoint configuration", |
| label = "producer") |
| private String consumes; |
| |
| @Metadata(description = "Scheme hostname and port to direct the HTTP requests to in the form of" |
| + " `http[s]://hostname[:port]`. Can be configured at the endpoint, component or in the corresponding" |
| + " REST configuration in the Camel Context. If you give this component a name (e.g. `petstore`) that" |
| + " REST configuration is consulted first, `rest-openapi` next, and global configuration last. If set" |
| + " overrides any value found in the OpenApi specification, RestConfiguration. Can be overridden in endpoint" |
| + " configuration.", label = "producer") |
| private String host; |
| |
| @Metadata( |
| description = "What payload type this component is producing. For example `application/json`" |
| + " according to the RFC7231. This equates to the value of `Content-Type` HTTP header. If set overrides" |
| + " any value present in the OpenApi specification. Can be overridden in endpoint configuration.", |
| label = "producer") |
| private String produces; |
| |
| @Metadata(description = "Path to the OpenApi specification file. The scheme, host base path are taken from this" |
| + " specification, but these can be overridden with properties on the component or endpoint level. If not" |
| + " given the component tries to load `openapi.json` resource. Note that the `host` defined on the" |
| + " component and endpoint of this Component should contain the scheme, hostname and optionally the" |
| + " port in the URI syntax (i.e. `https://api.example.com:8080`). Can be overridden in endpoint" |
| + " configuration.", defaultValue = DEFAULT_SPECIFICATION_URI_STR, label = "producer") |
| private URI specificationUri; |
| |
| @Metadata(description = "Customize TLS parameters used by the component. If not set defaults to the TLS parameters" |
| + " set in the Camel context ", label = "security") |
| private SSLContextParameters sslContextParameters; |
| |
| @Metadata(description = "Enable usage of global SSL context parameters.", label = "security", |
| defaultValue = "false") |
| private boolean useGlobalSslContextParameters; |
| |
| public RestOpenApiComponent() { |
| } |
| |
| public RestOpenApiComponent(final CamelContext context) { |
| super(context); |
| } |
| |
| @Override |
| protected Endpoint createEndpoint(final String uri, final String remaining, final Map<String, Object> parameters) throws Exception { |
| Endpoint endpoint = new RestOpenApiEndpoint(uri, remaining, this, parameters); |
| setProperties(endpoint, parameters); |
| return endpoint; |
| } |
| |
| public String getBasePath() { |
| return basePath; |
| } |
| |
| public String getComponentName() { |
| return componentName; |
| } |
| |
| public String getConsumes() { |
| return consumes; |
| } |
| |
| public String getHost() { |
| return host; |
| } |
| |
| public String getProduces() { |
| return produces; |
| } |
| |
| public URI getSpecificationUri() { |
| return specificationUri; |
| } |
| |
| public SSLContextParameters getSslContextParameters() { |
| return sslContextParameters; |
| } |
| |
| @Override |
| public boolean isUseGlobalSslContextParameters() { |
| return useGlobalSslContextParameters; |
| } |
| |
| public void setBasePath(final String basePath) { |
| this.basePath = notEmpty(basePath, "basePath"); |
| } |
| |
| public void setComponentName(final String componentName) { |
| this.componentName = notEmpty(componentName, "componentName"); |
| } |
| |
| public void setConsumes(final String consumes) { |
| this.consumes = isMediaRange(consumes, "consumes"); |
| } |
| |
| public void setHost(final String host) { |
| this.host = isHostParam(host); |
| } |
| |
| public void setProduces(final String produces) { |
| this.produces = isMediaRange(produces, "produces"); |
| } |
| |
| public void setSpecificationUri(final URI specificationUri) { |
| this.specificationUri = notNull(specificationUri, "specificationUri"); |
| } |
| |
| public void setSslContextParameters(final SSLContextParameters sslContextParameters) { |
| this.sslContextParameters = sslContextParameters; |
| } |
| |
| @Override |
| public void setUseGlobalSslContextParameters(final boolean useGlobalSslContextParameters) { |
| this.useGlobalSslContextParameters = useGlobalSslContextParameters; |
| } |
| |
| } |