http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifier.java ---------------------------------------------------------------------- diff --git a/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifier.java b/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifier.java new file mode 100644 index 0000000..aa459cc --- /dev/null +++ b/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifier.java @@ -0,0 +1,211 @@ +/** + * 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.http4; + +import java.net.UnknownHostException; +import java.util.Map; +import java.util.Optional; + +import org.apache.camel.ComponentVerifier; +import org.apache.camel.http.common.HttpHelper; +import org.apache.camel.impl.verifier.DefaultComponentVerifier; +import org.apache.camel.impl.verifier.ResultBuilder; +import org.apache.camel.impl.verifier.ResultErrorBuilder; +import org.apache.camel.impl.verifier.ResultErrorHelper; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; + +final class HttpComponentVerifier extends DefaultComponentVerifier { + private final HttpComponent component; + + HttpComponentVerifier(HttpComponent component) { + super(component.getCamelContext()); + + this.component = component; + } + + // ********************************* + // Parameters validation + // ********************************* + + @Override + protected Result verifyParameters(Map<String, Object> parameters) { + // The default is success + ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS); + + // The httpUri is mandatory + builder.error(ResultErrorHelper.requiresOption("httpUri", parameters)); + + return builder.build(); + } + + // ********************************* + // Connectivity validation + // ********************************* + + @Override + protected Result verifyConnectivity(Map<String, Object> parameters) { + // Default is success + ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY); + + Optional<String> uri = getOption(parameters, "httpUri", String.class); + if (!uri.isPresent()) { + // lack of httpUri is a blocking issue + builder.error(ResultErrorHelper.requiresOption("httpUri", parameters)); + } else { + builder.error(parameters, this::verifyHttpConnectivity); + } + + return builder.build(); + } + + private void verifyHttpConnectivity(ResultBuilder builder, Map<String, Object> parameters) throws Exception { + Optional<String> uri = getOption(parameters, "httpUri", String.class); + + CloseableHttpClient httpclient = createHttpClient(parameters); + HttpUriRequest request = new HttpGet(uri.get()); + + try (CloseableHttpResponse response = httpclient.execute(request)) { + int code = response.getStatusLine().getStatusCode(); + String okCodes = getOption(parameters, "okStatusCodeRange", String.class).orElse("200-299"); + + if (!HttpHelper.isStatusCodeOk(code, okCodes)) { + if (code == 401) { + // Unauthorized, add authUsername and authPassword to the list + // of parameters in error + builder.error( + ResultErrorBuilder.withHttpCode(code) + .description(response.getStatusLine().getReasonPhrase()) + .parameter("authUsername") + .parameter("authPassword") + .build() + ); + } else if (code >= 300 && code < 400) { + // redirect + builder.error( + ResultErrorBuilder.withHttpCode(code) + .description(response.getStatusLine().getReasonPhrase()) + .parameter("httpUri") + .attribute(ComponentVerifier.HTTP_REDIRECT, true) + .attribute(ComponentVerifier.HTTP_REDIRECT_LOCATION, () -> HttpUtil.responseHeaderValue(response, "location")) + .build() + ); + } else if (code >= 400) { + // generic http error + builder.error( + ResultErrorBuilder.withHttpCode(code) + .description(response.getStatusLine().getReasonPhrase()) + .build() + ); + } + } + } catch (UnknownHostException e) { + builder.error( + ResultErrorBuilder.withException(e) + .parameter("httpUri") + .build() + ); + } + } + + // ********************************* + // Helpers + // ********************************* + + private Optional<HttpClientConfigurer> configureAuthentication(Map<String, Object> parameters) { + Optional<String> authUsername = getOption(parameters, "authUsername", String.class); + Optional<String> authPassword = getOption(parameters, "authPassword", String.class); + + if (authUsername.isPresent() && authPassword.isPresent()) { + Optional<String> authDomain = getOption(parameters, "authDomain", String.class); + Optional<String> authHost = getOption(parameters, "authHost", String.class); + + return Optional.of( + new BasicAuthenticationHttpClientConfigurer( + authUsername.get(), + authPassword.get(), + authDomain.orElse(null), + authHost.orElse(null) + ) + ); + } + + return Optional.empty(); + } + + private Optional<HttpClientConfigurer> configureProxy(Map<String, Object> parameters) { + Optional<String> uri = getOption(parameters, "httpUri", String.class); + Optional<String> proxyAuthHost = getOption(parameters, "proxyAuthHost", String.class); + Optional<Integer> proxyAuthPort = getOption(parameters, "proxyAuthPort", Integer.class); + + if (proxyAuthHost.isPresent() && proxyAuthPort.isPresent()) { + Optional<String> proxyAuthScheme = getOption(parameters, "proxyAuthScheme", String.class); + Optional<String> proxyAuthUsername = getOption(parameters, "proxyAuthUsername", String.class); + Optional<String> proxyAuthPassword = getOption(parameters, "proxyAuthPassword", String.class); + Optional<String> proxyAuthDomain = getOption(parameters, "proxyAuthDomain", String.class); + Optional<String> proxyAuthNtHost = getOption(parameters, "proxyAuthNtHost", String.class); + + if (!proxyAuthScheme.isPresent()) { + proxyAuthScheme = Optional.of(HttpHelper.isSecureConnection(uri.get()) ? "https" : "http"); + } + + if (proxyAuthUsername != null && proxyAuthPassword != null) { + return Optional.of( + new ProxyHttpClientConfigurer( + proxyAuthHost.get(), + proxyAuthPort.get(), + proxyAuthScheme.get(), + proxyAuthUsername.orElse(null), + proxyAuthPassword.orElse(null), + proxyAuthDomain.orElse(null), + proxyAuthNtHost.orElse(null)) + ); + } else { + return Optional.of( + new ProxyHttpClientConfigurer( + proxyAuthHost.get(), + proxyAuthPort.get(), + proxyAuthScheme.get()) + ); + } + } + + return Optional.empty(); + } + + private CloseableHttpClient createHttpClient(Map<String, Object> parameters) throws Exception { + CompositeHttpConfigurer configurer = new CompositeHttpConfigurer(); + configureAuthentication(parameters).ifPresent(configurer::addConfigurer); + configureProxy(parameters).ifPresent(configurer::addConfigurer); + + HttpClientBuilder builder = HttpClientBuilder.create(); + configurer.configureHttpClient(builder); + + RequestConfig.Builder requestConfigBuilder = RequestConfig.custom(); + + // Apply custom http client properties like httpClient.redirectsEnabled + setProperties(builder, "httpClient.", parameters); + setProperties(requestConfigBuilder, "httpClient.", parameters); + + return builder.setDefaultRequestConfig(requestConfigBuilder.build()) + .build(); + } +}
http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpUtil.java ---------------------------------------------------------------------- diff --git a/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpUtil.java b/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpUtil.java new file mode 100644 index 0000000..8a6a8e4 --- /dev/null +++ b/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpUtil.java @@ -0,0 +1,36 @@ +/** + * 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.http4; + +import java.util.Optional; + +import org.apache.http.Header; +import org.apache.http.HttpResponse; + + +public final class HttpUtil { + private HttpUtil() { + } + + public static Optional<Header> responseHeader(HttpResponse response, String headerName) { + return Optional.ofNullable(response.getFirstHeader(headerName)); + } + + public static Optional<String> responseHeaderValue(HttpResponse response, String headerName) { + return responseHeader(response, headerName).map(Header::getValue); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-http4/src/main/java/org/apache/camel/component/http4/ProxyHttpClientConfigurer.java ---------------------------------------------------------------------- diff --git a/components/camel-http4/src/main/java/org/apache/camel/component/http4/ProxyHttpClientConfigurer.java b/components/camel-http4/src/main/java/org/apache/camel/component/http4/ProxyHttpClientConfigurer.java index 35d9234..492c21a 100644 --- a/components/camel-http4/src/main/java/org/apache/camel/component/http4/ProxyHttpClientConfigurer.java +++ b/components/camel-http4/src/main/java/org/apache/camel/component/http4/ProxyHttpClientConfigurer.java @@ -66,4 +66,6 @@ public class ProxyHttpClientConfigurer implements HttpClientConfigurer { clientBuilder.setDefaultCredentialsProvider(credentialsProvider); } } + + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierTest.java ---------------------------------------------------------------------- diff --git a/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierTest.java b/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierTest.java new file mode 100644 index 0000000..effca79 --- /dev/null +++ b/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierTest.java @@ -0,0 +1,230 @@ +/** + * 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.http4; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.apache.camel.ComponentVerifier; +import org.apache.camel.component.http4.handler.AuthenticationValidationHandler; +import org.apache.camel.component.http4.handler.BasicValidationHandler; +import org.apache.http.HttpException; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.impl.bootstrap.HttpServer; +import org.apache.http.impl.bootstrap.ServerBootstrap; +import org.apache.http.localserver.RequestBasicAuth; +import org.apache.http.localserver.ResponseBasicUnauthorized; +import org.apache.http.protocol.HttpContext; +import org.apache.http.protocol.HttpProcessor; +import org.apache.http.protocol.HttpRequestHandler; +import org.apache.http.protocol.ImmutableHttpProcessor; +import org.apache.http.protocol.ResponseContent; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class CamelComponentVerifierTest extends BaseHttpTest { + private static final String AUTH_USERNAME = "camel"; + private static final String AUTH_PASSWORD = "password"; + + private HttpServer localServer; + + @Before + @Override + public void setUp() throws Exception { + localServer = ServerBootstrap.bootstrap() + .setHttpProcessor(getHttpProcessor()) + .registerHandler("/basic", new BasicValidationHandler("GET", null, null, getExpectedContent())) + .registerHandler("/auth", new AuthenticationValidationHandler("GET", null, null, getExpectedContent(), AUTH_USERNAME, AUTH_PASSWORD)) + .registerHandler("/redirect", redirectTo(HttpStatus.SC_MOVED_PERMANENTLY, "/redirected")) + .registerHandler("/redirected", new BasicValidationHandler("GET", null, null, getExpectedContent())) + .create(); + + localServer.start(); + + super.setUp(); + } + + @After + @Override + public void tearDown() throws Exception { + super.tearDown(); + + if (localServer != null) { + localServer.stop(); + } + } + + @Override + public boolean isUseRouteBuilder() { + return false; + } + + private HttpProcessor getHttpProcessor() { + return new ImmutableHttpProcessor( + Arrays.asList( + new RequestBasicAuth() + ), + Arrays.asList( + new ResponseContent(), + new ResponseBasicUnauthorized()) + ); + } + + // ************************************************* + // Helpers + // ************************************************* + + protected String getLocalServerUri(String contextPath) { + return new StringBuilder() + .append("http://") + .append(localServer.getInetAddress().getHostName()) + .append(":") + .append(localServer.getLocalPort()) + .append(contextPath != null + ? contextPath.startsWith("/") ? contextPath : "/" + contextPath + : "") + .toString(); + } + + private HttpRequestHandler redirectTo(int code, String path) { + return new HttpRequestHandler() { + @Override + public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { + response.setHeader("location", getLocalServerUri(path)); + response.setStatusCode(code); + } + }; + } + + // ************************************************* + // Tests + // ************************************************* + + @Test + public void testConnectivity() throws Exception { + HttpComponent component = context().getComponent("http4", HttpComponent.class); + HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); + + Map<String, Object> parameters = new HashMap<>(); + parameters.put("httpUri", getLocalServerUri("/basic")); + + ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus()); + } + + @Test + public void testConnectivityWithWrongUri() throws Exception { + HttpComponent component = context().getComponent("http4", HttpComponent.class); + HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); + + Map<String, Object> parameters = new HashMap<>(); + parameters.put("httpUri", "http://www.not-existing-uri.unknown"); + + ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + + ComponentVerifier.Error error = result.getErrors().get(0); + + Assert.assertEquals(ComponentVerifier.CODE_EXCEPTION, error.getCode()); + Assert.assertEquals(ComponentVerifier.ERROR_TYPE_EXCEPTION, error.getAttributes().get(ComponentVerifier.ERROR_TYPE_ATTRIBUTE)); + Assert.assertTrue(error.getParameters().contains("httpUri")); + } + + @Test + public void testConnectivityWithAuthentication() throws Exception { + HttpComponent component = context().getComponent("http4", HttpComponent.class); + HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); + + Map<String, Object> parameters = new HashMap<>(); + parameters.put("httpUri", getLocalServerUri("/auth")); + parameters.put("authUsername", AUTH_USERNAME); + parameters.put("authPassword", AUTH_PASSWORD); + + ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus()); + } + + @Test + public void testConnectivityWithWrongAuthenticationData() throws Exception { + HttpComponent component = context().getComponent("http4", HttpComponent.class); + HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); + + Map<String, Object> parameters = new HashMap<>(); + parameters.put("httpUri", getLocalServerUri("/auth")); + parameters.put("authUsername", "unknown"); + parameters.put("authPassword", AUTH_PASSWORD); + + ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + + ComponentVerifier.Error error = result.getErrors().get(0); + + Assert.assertEquals("401", error.getCode()); + Assert.assertEquals(ComponentVerifier.ERROR_TYPE_HTTP, error.getAttributes().get(ComponentVerifier.ERROR_TYPE_ATTRIBUTE)); + Assert.assertEquals(401, error.getAttributes().get(ComponentVerifier.HTTP_CODE)); + Assert.assertTrue(error.getParameters().contains("authUsername")); + Assert.assertTrue(error.getParameters().contains("authPassword")); + } + + @Test + public void testConnectivityWithRedirect() throws Exception { + HttpComponent component = context().getComponent("http4", HttpComponent.class); + HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); + + Map<String, Object> parameters = new HashMap<>(); + parameters.put("httpUri", getLocalServerUri("/redirect")); + + ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus()); + } + + @Test + public void testConnectivityWithRedirectDisabled() throws Exception { + HttpComponent component = context().getComponent("http4", HttpComponent.class); + HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); + + Map<String, Object> parameters = new HashMap<>(); + parameters.put("httpUri", getLocalServerUri("/redirect")); + parameters.put("httpClient.redirectsEnabled", "false"); + + ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + + ComponentVerifier.Error error = result.getErrors().get(0); + + Assert.assertEquals("301", error.getCode()); + Assert.assertEquals(ComponentVerifier.ERROR_TYPE_HTTP, error.getAttributes().get(ComponentVerifier.ERROR_TYPE_ATTRIBUTE)); + Assert.assertEquals(true, error.getAttributes().get("http.redirect")); + Assert.assertEquals(getLocalServerUri("/redirected"), error.getAttributes().get("http.redirect.location")); + Assert.assertTrue(error.getParameters().contains("httpUri")); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-http4/src/test/java/org/apache/camel/component/http4/HttpRedirectTest.java ---------------------------------------------------------------------- diff --git a/components/camel-http4/src/test/java/org/apache/camel/component/http4/HttpRedirectTest.java b/components/camel-http4/src/test/java/org/apache/camel/component/http4/HttpRedirectTest.java index 6a40340..ed90a1c 100644 --- a/components/camel-http4/src/test/java/org/apache/camel/component/http4/HttpRedirectTest.java +++ b/components/camel-http4/src/test/java/org/apache/camel/component/http4/HttpRedirectTest.java @@ -50,7 +50,6 @@ public class HttpRedirectTest extends BaseHttpTest { setResponseFactory(getHttpResponseFactory()). setExpectationVerifier(getHttpExpectationVerifier()). setSslContext(getSSLContext()). - registerHandler("/test", new RedirectHandler(HttpStatus.SC_MOVED_PERMANENTLY)). registerHandler("/someplaceelse", new BasicValidationHandler("GET", null, null, "Bye World")). registerHandler("/test", new RedirectHandler(HttpStatus.SC_MOVED_PERMANENTLY)). create(); http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java index e95668d..64fce53 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java @@ -30,7 +30,9 @@ import java.util.regex.Pattern; import org.apache.camel.CamelContext; import org.apache.camel.ComponentConfiguration; +import org.apache.camel.ComponentVerifier; import org.apache.camel.Endpoint; +import org.apache.camel.VerifiableComponent; import org.apache.camel.component.salesforce.api.SalesforceException; import org.apache.camel.component.salesforce.api.dto.AbstractQueryRecordsBase; import org.apache.camel.component.salesforce.api.dto.AbstractSObjectBase; @@ -61,13 +63,14 @@ import static org.apache.camel.component.salesforce.SalesforceLoginConfig.DEFAUL /** * Represents the component that manages {@link SalesforceEndpoint}. */ -public class SalesforceComponent extends UriEndpointComponent implements EndpointCompleter { +@Metadata(label = "verifiers", enums = "PARAMETERS,CONNECTIVITY") +public class SalesforceComponent extends UriEndpointComponent implements EndpointCompleter, VerifiableComponent { private static final Logger LOG = LoggerFactory.getLogger(SalesforceComponent.class); - private static final int CONNECTION_TIMEOUT = 60000; - private static final Pattern SOBJECT_NAME_PATTERN = Pattern.compile("^.*[\\?&]sObjectName=([^&,]+).*$"); - private static final String APEX_CALL_PREFIX = OperationName.APEX_CALL.value() + "/"; + static final int CONNECTION_TIMEOUT = 60000; + static final Pattern SOBJECT_NAME_PATTERN = Pattern.compile("^.*[\\?&]sObjectName=([^&,]+).*$"); + static final String APEX_CALL_PREFIX = OperationName.APEX_CALL.value() + "/"; @Metadata(label = "security") private SalesforceLoginConfig loginConfig; @@ -702,4 +705,11 @@ public class SalesforceComponent extends UriEndpointComponent implements Endpoin public Map<String, Class<?>> getClassMap() { return classMap; } + + /** + * TODO: document + */ + public ComponentVerifier getVerifier() { + return new SalesforceComponentVerifier(getCamelContext()); + } } http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java new file mode 100644 index 0000000..11b331c --- /dev/null +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java @@ -0,0 +1,190 @@ +/** + * 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.salesforce; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Map; +import java.util.Optional; + +import org.apache.camel.CamelContext; +import org.apache.camel.ComponentVerifier; +import org.apache.camel.NoSuchOptionException; +import org.apache.camel.component.salesforce.api.SalesforceException; +import org.apache.camel.component.salesforce.api.dto.RestError; +import org.apache.camel.component.salesforce.internal.SalesforceSession; +import org.apache.camel.component.salesforce.internal.client.DefaultRestClient; +import org.apache.camel.impl.verifier.DefaultComponentVerifier; +import org.apache.camel.impl.verifier.ResultBuilder; +import org.apache.camel.impl.verifier.ResultErrorBuilder; +import org.apache.camel.impl.verifier.ResultErrorHelper; +import org.apache.camel.util.jsse.SSLContextParameters; +import org.eclipse.jetty.client.HttpProxy; +import org.eclipse.jetty.client.Origin; +import org.eclipse.jetty.client.Socks4Proxy; +import org.eclipse.jetty.client.util.BasicAuthentication; +import org.eclipse.jetty.client.util.DigestAuthentication; +import org.eclipse.jetty.util.ssl.SslContextFactory; + +public class SalesforceComponentVerifier extends DefaultComponentVerifier { + SalesforceComponentVerifier(CamelContext camelContext) { + super(camelContext); + } + + // ********************************* + // Parameters validation + // ********************************* + + @Override + protected ComponentVerifier.Result verifyParameters(Map<String, Object> parameters) { + return ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.OK, ComponentVerifier.Scope.PARAMETERS) + .error(ResultErrorHelper.requiresOption("clientId", parameters)) + .error(ResultErrorHelper.requiresOption("clientSecret", parameters)) + .error(ResultErrorHelper.requiresOption("userName", parameters)) + .error(ResultErrorHelper.requiresOption("password", parameters)) + .build(); + } + + // ********************************* + // Connectivity validation + // ********************************* + + @Override + protected Result verifyConnectivity(Map<String, Object> parameters) { + // Default is success + ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY); + + try { + SalesforceEndpointConfig configuration = new SalesforceEndpointConfig(); + setProperties(configuration, parameters); + + SalesforceLoginConfig loginConfig = new SalesforceLoginConfig(); + setProperties(loginConfig, parameters); + + // Create a dummy SslContextFactory which is needed by SalesforceHttpClient + // or the underlying jetty client fails with a NPE + SSLContextParameters contextParameters = new SSLContextParameters(); + SslContextFactory sslContextFactory = new SslContextFactory(); + sslContextFactory.setSslContext(contextParameters.createSSLContext(getCamelContext())); + + SalesforceHttpClient httpClient = new SalesforceHttpClient(sslContextFactory); + httpClient.setConnectTimeout(SalesforceComponent.CONNECTION_TIMEOUT); + configureHttpProxy(httpClient, parameters); + + SalesforceSession session = new SalesforceSession(httpClient, httpClient.getTimeout(), loginConfig); + DefaultRestClient client = new DefaultRestClient(httpClient, configuration.getApiVersion(), configuration.getFormat(), session); + + httpClient.setSession(session); + httpClient.start(); + + // For authentication check is is enough to use + session.start(); + + client.start(); + client.getVersions((response, exception) -> processSalesforceException(builder, Optional.ofNullable(exception))); + client.stop(); + + session.stop(); + + httpClient.stop(); + httpClient.destroy(); + } catch(NoSuchOptionException e) { + builder.error( + ResultErrorBuilder.withMissingOption(e.getOptionName()).build() + ); + } catch(SalesforceException e) { + processSalesforceException(builder, Optional.of(e)); + } catch (Exception e) { + builder.error( + ResultErrorBuilder.withException(e).build() + ); + + throw new RuntimeException(e); + } + + return builder.build(); + } + + // ********************************* + // Helpers + // ********************************* + + private void processSalesforceException(ResultBuilder builder, Optional<SalesforceException> exception) { + exception.ifPresent(e -> { + builder.error( + ResultErrorBuilder.withException(e) + .attribute(ComponentVerifier.HTTP_CODE, e.getStatusCode()) + .build() + ); + + for (RestError error : e.getErrors()) { + builder.error( + ResultErrorBuilder.withCode(error.getErrorCode()) + .description(error.getMessage()) + .attribute(ComponentVerifier.ERROR_TYPE_ATTRIBUTE, "salesforce") + .parameters(error.getFields()) + .build() + ); + } + }); + } + + private void configureHttpProxy(SalesforceHttpClient httpClient, Map<String, Object> parameters) throws NoSuchOptionException, URISyntaxException { + Optional<String> httpProxyHost = getOption(parameters, "httpProxyHost", String.class); + Optional<Integer> httpProxyPort = getOption(parameters, "httpProxyPort", Integer.class); + Optional<String> httpProxyUsername = getOption(parameters, "httpProxyUsername", String.class); + Optional<String> httpProxyPassword = getOption(parameters, "httpProxyPassword", String.class); + + if (httpProxyHost.isPresent() && httpProxyPort.isPresent()) { + Origin.Address address = new Origin.Address(httpProxyHost.get(), httpProxyPort.get()); + Boolean isHttpProxySocks4 = getOption(parameters, "isHttpProxySocks4", Boolean.class, () -> false); + Boolean isHttpProxySecure = getOption(parameters, "isHttpProxySecure", Boolean.class, () -> true); + + if (isHttpProxySocks4) { + httpClient.getProxyConfiguration().getProxies().add( + new Socks4Proxy(address, isHttpProxySecure) + ); + } else { + httpClient.getProxyConfiguration().getProxies().add( + new HttpProxy(address, isHttpProxySecure) + ); + } + } + + if (httpProxyUsername.isPresent() && httpProxyPassword.isPresent()) { + Boolean httpProxyUseDigestAuth = getOption(parameters, "httpProxyUseDigestAuth", Boolean.class, () -> false); + String httpProxyAuthUri = getMandatoryOption(parameters, "httpProxyAuthUri", String.class); + String httpProxyRealm = getMandatoryOption(parameters, "httpProxyRealm", String.class); + + if (httpProxyUseDigestAuth) { + httpClient.getAuthenticationStore().addAuthentication(new DigestAuthentication( + new URI(httpProxyAuthUri), + httpProxyRealm, + httpProxyUsername.get(), + httpProxyPassword.get()) + ); + } else { + httpClient.getAuthenticationStore().addAuthentication(new BasicAuthentication( + new URI(httpProxyAuthUri), + httpProxyRealm, + httpProxyUsername.get(), + httpProxyPassword.get()) + ); + } + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierTest.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierTest.java new file mode 100644 index 0000000..542139e --- /dev/null +++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierTest.java @@ -0,0 +1,143 @@ +/** + * 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.salesforce; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.camel.ComponentVerifier; +import org.apache.camel.component.salesforce.api.SalesforceException; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.apache.camel.util.ObjectHelper; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; + +public class SalesforceComponentVerifierTest extends CamelTestSupport { + private static final String clientId = getSystemPropertyOrEnvVar("salesforce.clientid"); + private static final String clientSecret = getSystemPropertyOrEnvVar("salesforce.clientsecret"); + private static final String userName = getSystemPropertyOrEnvVar("salesforce.userName"); + private static final String password = getSystemPropertyOrEnvVar("salesforce.password"); + + @Override + protected void doPreSetup() throws Exception { + Assume.assumeNotNull(clientId); + Assume.assumeNotNull(clientSecret); + Assume.assumeNotNull(userName); + Assume.assumeNotNull(password); + } + + @Override + public boolean isUseRouteBuilder() { + return false; + } + + // ********************************* + // Helpers + // ********************************* + + protected Map<String, Object> getParameters() { + HashMap<String, Object> parameters = new HashMap<>(); + parameters.put("clientId", clientId); + parameters.put("clientSecret", clientSecret); + parameters.put("userName", userName); + parameters.put("password", password); + + return parameters; + } + + public static String getSystemPropertyOrEnvVar(String systemProperty) { + String answer = System.getProperty(systemProperty); + if (ObjectHelper.isEmpty(answer)) { + String envProperty = systemProperty.toUpperCase().replaceAll("[.-]", "_"); + answer = System.getenv(envProperty); + } + + return answer; + } + + protected SalesforceComponentVerifier getVerifier() { + SalesforceComponent component = context().getComponent("salesforce", SalesforceComponent.class); + SalesforceComponentVerifier verifier = (SalesforceComponentVerifier)component.getVerifier(); + + return verifier; + } + + // ********************************* + // Parameters validation + // ********************************* + + + // ********************************* + // Connectivity validation + // ********************************* + + @Test + public void testConnectivity() { + Map<String, Object> parameters = getParameters(); + ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus()); + } + + @Test + public void testConnectivityWithWrongUserName() { + Map<String, Object> parameters = getParameters(); + parameters.put("userName", "not-a-salesforce-user"); + + ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(2, result.getErrors().size()); + + // Exception + Assert.assertEquals(ComponentVerifier.CODE_EXCEPTION, result.getErrors().get(0).getCode()); + Assert.assertNotNull(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE)); + Assert.assertTrue(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE) instanceof SalesforceException); + Assert.assertEquals(400, result.getErrors().get(0).getAttributes().get(ComponentVerifier.HTTP_CODE)); + + // Salesforce Error + Assert.assertEquals("salesforce", result.getErrors().get(1).getAttributes().get(ComponentVerifier.ERROR_TYPE_ATTRIBUTE)); + Assert.assertEquals("authentication failure", result.getErrors().get(1).getDescription()); + } + + @Test + public void testConnectivityWithWrongSecrets() { + Map<String, Object> parameters = getParameters(); + parameters.put("clientId", "wrong-client-id"); + parameters.put("clientSecret", "wrong-client-secret"); + + ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(2, result.getErrors().size()); + + // Exception + Assert.assertEquals(ComponentVerifier.CODE_EXCEPTION, result.getErrors().get(0).getCode()); + Assert.assertNotNull(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE)); + Assert.assertTrue(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE) instanceof SalesforceException); + Assert.assertEquals(400, result.getErrors().get(0).getAttributes().get(ComponentVerifier.HTTP_CODE)); + + // Salesforce Error + Assert.assertEquals("salesforce", result.getErrors().get(1).getAttributes().get(ComponentVerifier.ERROR_TYPE_ATTRIBUTE)); + Assert.assertEquals("client identifier invalid", result.getErrors().get(1).getDescription()); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java index fa33607..465a692 100644 --- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java @@ -24,7 +24,6 @@ import javax.ws.rs.core.Response; import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; import org.apache.camel.CamelContext; -import org.apache.camel.CamelException; import org.apache.camel.Message; import org.apache.camel.component.servicenow.auth.AuthenticationRequestFilter; import org.apache.camel.util.jsse.SSLContextParameters; @@ -44,8 +43,7 @@ public final class ServiceNowClient { configuration.getApiUrl(), Arrays.asList( new AuthenticationRequestFilter(configuration), - new JacksonJsonProvider(configuration.getMapper()), - new ServiceNowExceptionMapper(configuration.getMapper()) + new JacksonJsonProvider(configuration.getMapper()) ), true ); @@ -131,10 +129,17 @@ public final class ServiceNowClient { case 405: case 406: case 415: - throw response.readEntity(ServiceNowException.class); + ServiceNowExceptionModel model = response.readEntity(ServiceNowExceptionModel.class); + throw new ServiceNowException( + code, + model.getStatus(), + model.getError().get("message"), + model.getError().get("detail") + ); default: - throw new CamelException( - String.format("Status (%d): %s", code, response.readEntity(Map.class)) + throw new ServiceNowException( + code, + response.readEntity(Map.class) ); } http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java index ab3f7e0..63c5996 100644 --- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java @@ -19,7 +19,9 @@ package org.apache.camel.component.servicenow; import java.util.Map; import org.apache.camel.CamelContext; +import org.apache.camel.ComponentVerifier; import org.apache.camel.Endpoint; +import org.apache.camel.VerifiableComponent; import org.apache.camel.impl.UriEndpointComponent; import org.apache.camel.spi.Metadata; import org.apache.camel.util.EndpointHelper; @@ -28,7 +30,8 @@ import org.apache.camel.util.IntrospectionSupport; /** * Represents the component that manages {@link ServiceNowEndpoint}. */ -public class ServiceNowComponent extends UriEndpointComponent { +@Metadata(label = "verifiers", enums = "PARAMETERS,CONNECTIVITY") +public class ServiceNowComponent extends UriEndpointComponent implements VerifiableComponent { @Metadata(label = "advanced") private ServiceNowConfiguration configuration; @@ -71,7 +74,7 @@ public class ServiceNowComponent extends UriEndpointComponent { if (!configuration.hasApiUrl()) { configuration.setApiUrl(String.format("https://%s.service-now.com/api", instanceName)); } - if (!configuration.hasOautTokenUrl()) { + if (!configuration.hasOauthTokenUrl()) { configuration.setOauthTokenUrl(String.format("https://%s.service-now.com/oauth_token.do", instanceName)); } @@ -159,4 +162,11 @@ public class ServiceNowComponent extends UriEndpointComponent { public void setOauthTokenUrl(String oauthTokenUrl) { configuration.setOauthTokenUrl(oauthTokenUrl); } + + /** + * TODO: document + */ + public ComponentVerifier getVerifier() { + return new ServiceNowComponentVerifier(this); + } } http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifier.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifier.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifier.java new file mode 100644 index 0000000..f106632 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifier.java @@ -0,0 +1,113 @@ +/** + * 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.servicenow; + +import java.util.Map; +import javax.ws.rs.HttpMethod; +import javax.ws.rs.core.MediaType; + +import org.apache.camel.ComponentVerifier; +import org.apache.camel.NoSuchOptionException; +import org.apache.camel.impl.verifier.DefaultComponentVerifier; +import org.apache.camel.impl.verifier.ResultBuilder; +import org.apache.camel.impl.verifier.ResultErrorBuilder; +import org.apache.camel.impl.verifier.ResultErrorHelper; + +public class ServiceNowComponentVerifier extends DefaultComponentVerifier { + private final ServiceNowComponent component; + + ServiceNowComponentVerifier(ServiceNowComponent component) { + super(component.getCamelContext()); + + this.component = component; + } + + // ********************************* + // Parameters validation + // ********************************* + + @Override + protected Result verifyParameters(Map<String, Object> parameters) { + return ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS) + .error(ResultErrorHelper.requiresOption("instanceName", parameters)) + .error(ResultErrorHelper.requiresOption("userName", parameters)) + .error(ResultErrorHelper.requiresOption("password", parameters)) + .build(); + } + + // ********************************* + // Connectivity validation + // ********************************* + + @Override + protected Result verifyConnectivity(Map<String, Object> parameters) { + // Default is success + ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY); + + try { + // Load ServiceNow Configuration + ServiceNowConfiguration configuration = new ServiceNowConfiguration(); + setProperties(configuration, parameters); + + String instanceName = getMandatoryOption(parameters, "instanceName", String.class); + String tableName = configuration.getTable() != null ? configuration.getTable() : "incident"; + + // Configure Api and OAuthToken ULRs using instanceName + if (!configuration.hasApiUrl()) { + configuration.setApiUrl(String.format("https://%s.service-now.com/api", instanceName)); + } + if (!configuration.hasOauthTokenUrl()) { + configuration.setOauthTokenUrl(String.format("https://%s.service-now.com/oauth_token.do", instanceName)); + } + + new ServiceNowClient(getCamelContext(), configuration) + .types(MediaType.APPLICATION_JSON_TYPE) + .path("now") + .path(configuration.getApiVersion()) + .path("table") + .path(tableName) + .query(ServiceNowParams.SYSPARM_LIMIT.getId(), 1L) + .invoke(HttpMethod.GET); + } catch(NoSuchOptionException e) { + builder.error( + ResultErrorBuilder.withMissingOption(e.getOptionName()).build() + ); + } catch (ServiceNowException e) { + ResultErrorBuilder errorBuilder = ResultErrorBuilder.withException(e) + .attribute(ComponentVerifier.HTTP_CODE, e.getCode()) + .attribute("servicenow.error.message", e.getMessage()) + .attribute("servicenow.error.status", e.getStatus()) + .attribute("servicenow.error.detail", e.getDetail()) + .attribute("servicenow.error.detail", e.getDetail()); + + if (e.getCode() == 401) { + errorBuilder.parameter("userName"); + errorBuilder.parameter("password"); + errorBuilder.parameter("oauthClientId"); + errorBuilder.parameter("oauthClientSecret"); + } + + builder.error(errorBuilder.build()); + } catch (Exception e) { + builder.error( + ResultErrorBuilder.withException(e).build() + ); + } + + return builder.build(); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java index dd23df9..d27d29e 100644 --- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java @@ -194,7 +194,7 @@ public class ServiceNowConfiguration implements Cloneable { return oauthTokenUrl; } - public boolean hasOautTokenUrl() { + public boolean hasOauthTokenUrl() { return oauthTokenUrl != null; } http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowException.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowException.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowException.java index cb1ce8b..42ffbac 100644 --- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowException.java +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowException.java @@ -16,30 +16,35 @@ */ package org.apache.camel.component.servicenow; +import java.util.Collections; import java.util.Map; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.camel.CamelException; -@JsonIgnoreProperties(ignoreUnknown = true) public class ServiceNowException extends CamelException { + private final Integer code; private final String status; private final String detail; + private final Map<Object, Object> attributes; - public ServiceNowException( - @JsonProperty("status") String status, - @JsonProperty("error") Map<String, String> error) { - super(error.get("message")); + public ServiceNowException(Integer code, String status, String message, String detail) { + super(message); + this.code = code; this.status = status; - this.detail = error.get("detail"); + this.detail = detail; + this.attributes = Collections.emptyMap(); } - public ServiceNowException(Throwable cause) { - super(cause); - + public ServiceNowException(Integer code, Map<Object, Object> attributes) { + super(String.format("Status (%d)")); + this.code = code; this.status = null; this.detail = null; + this.attributes = Collections.unmodifiableMap(attributes); + } + + public Integer getCode() { + return code; } public String getStatus() { @@ -50,10 +55,15 @@ public class ServiceNowException extends CamelException { return detail; } + public Map<Object, Object> getAttributes() { + return attributes; + } + @Override public String toString() { return getMessage() != null ? "" + this.status + ": " + getMessage() : super.toString(); } + } http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionMapper.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionMapper.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionMapper.java deleted file mode 100644 index d864246..0000000 --- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionMapper.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * 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.servicenow; - -import java.io.IOException; -import java.io.InputStream; -import javax.annotation.Priority; -import javax.ws.rs.Priorities; -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.Provider; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.cxf.jaxrs.client.ResponseExceptionMapper; - -@Provider -@Priority(Priorities.USER) -public class ServiceNowExceptionMapper implements ResponseExceptionMapper<ServiceNowException> { - private final ObjectMapper mapper; - - public ServiceNowExceptionMapper(ObjectMapper mapper) { - this.mapper = mapper; - } - - @Override - public ServiceNowException fromResponse(Response r) { - int code = r.getStatus(); - - try { - // Only ServiceNow known error status codes are mapped - // See http://wiki.servicenow.com/index.php?title=REST_API#REST_Response_HTTP_Status_Codes - switch(code) { - case 200: - case 201: - case 204: - // Success - break; - case 400: - case 401: - case 403: - case 404: - case 405: - case 406: - case 415: - return mapper.readValue(r.readEntity(InputStream.class), ServiceNowException.class); - default: - break; - } - } catch (IOException e) { - return new ServiceNowException(e); - } - - return null; - } -} http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionModel.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionModel.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionModel.java new file mode 100644 index 0000000..63c5519 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionModel.java @@ -0,0 +1,27 @@ +package org.apache.camel.component.servicenow; + +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public final class ServiceNowExceptionModel { + private final String status; + private final Map<String, String> error; + + public ServiceNowExceptionModel( + @JsonProperty("status") String status, + @JsonProperty("error") Map<String, String> error) { + this.status = status; + this.error = error; + } + + public String getStatus() { + return status; + } + + public Map<String, String> getError() { + return error; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java new file mode 100644 index 0000000..3cff7bb --- /dev/null +++ b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java @@ -0,0 +1,151 @@ +/** + * 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.servicenow; + +import java.util.Map; + +import javax.ws.rs.ProcessingException; + +import org.apache.camel.ComponentVerifier; +import org.junit.Assert; +import org.junit.Test; + +public class ServiceNowComponentVerifierTest extends ServiceNowTestSupport { + public ServiceNowComponentVerifierTest() { + super(false); + } + + @Override + public boolean isUseRouteBuilder() { + return false; + } + + protected ServiceNowComponentVerifier getVerifier() { + ServiceNowComponent component = context().getComponent("servicenow", ServiceNowComponent.class); + ServiceNowComponentVerifier verifier = (ServiceNowComponentVerifier)component.getVerifier(); + + return verifier; + } + + // ********************************* + // Parameters validation + // ********************************* + + @Test + public void testParameter() { + Map<String, Object> parameters = getParameters(); + ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.PARAMETERS, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus()); + } + + @Test + public void testMissingMandatoryParameter() { + Map<String, Object> parameters = getParameters(); + parameters.remove("instanceName"); + ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.PARAMETERS, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(ComponentVerifier.CODE_MISSING_OPTION, result.getErrors().get(0).getCode()); + Assert.assertEquals("instanceName", result.getErrors().get(0).getParameters().iterator().next()); + } + + @Test + public void testMissingMandatoryAuthenticationParameter() { + Map<String, Object> parameters = getParameters(); + parameters.remove("userName"); + ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.PARAMETERS, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(ComponentVerifier.CODE_MISSING_OPTION, result.getErrors().get(0).getCode()); + Assert.assertEquals("userName", result.getErrors().get(0).getParameters().iterator().next()); + } + + // ********************************* + // Connectivity validation + // ********************************* + + @Test + public void testConnectivity() { + Map<String, Object> parameters = getParameters(); + ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus()); + } + + @Test + public void testConnectivityOnCustomTable() { + Map<String, Object> parameters = getParameters(); + parameters.put("table", "ticket"); + + ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus()); + } + + @Test + public void testConnectivityWithWrongInstance() { + Map<String, Object> parameters = getParameters(); + parameters.put("instanceName", "unknown-instance"); + + ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(ComponentVerifier.CODE_EXCEPTION, result.getErrors().get(0).getCode()); + Assert.assertNotNull(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE)); + Assert.assertTrue(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE) instanceof ProcessingException); + } + + @Test + public void testConnectivityWithWrongTable() { + Map<String, Object> parameters = getParameters(); + parameters.put("table", "unknown"); + + ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(ComponentVerifier.CODE_EXCEPTION, result.getErrors().get(0).getCode()); + Assert.assertNotNull(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE)); + Assert.assertEquals(400, result.getErrors().get(0).getAttributes().get(ComponentVerifier.HTTP_CODE)); + Assert.assertTrue(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE) instanceof ServiceNowException); + } + + @Test + public void testConnectivityWithWrongAuthentication() { + Map<String, Object> parameters = getParameters(); + parameters.put("userName", "unknown-user"); + parameters.remove("oauthClientId"); + parameters.remove("oauthClientSecret"); + + ComponentVerifier.Result result = getVerifier().verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(ComponentVerifier.CODE_EXCEPTION, result.getErrors().get(0).getCode()); + Assert.assertNotNull(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE)); + Assert.assertEquals(401, result.getErrors().get(0).getAttributes().get(ComponentVerifier.HTTP_CODE)); + Assert.assertTrue(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE) instanceof ServiceNowException); + Assert.assertTrue(result.getErrors().get(0).getParameters().contains("userName")); + Assert.assertTrue(result.getErrors().get(0).getParameters().contains("password")); + Assert.assertTrue(result.getErrors().get(0).getParameters().contains("oauthClientId")); + Assert.assertTrue(result.getErrors().get(0).getParameters().contains("oauthClientSecret")); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTestSupport.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTestSupport.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTestSupport.java index 8ed29b2..d9cdf49 100644 --- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTestSupport.java +++ b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowTestSupport.java @@ -29,12 +29,38 @@ import org.slf4j.LoggerFactory; class ServiceNowTestSupport extends CamelTestSupport { protected static final Logger LOGGER = LoggerFactory.getLogger(ServiceNowTestSupport.class); + private final boolean setUpComponent; + + public ServiceNowTestSupport() { + this(true); + } + + public ServiceNowTestSupport(boolean setUpComponent) { + this.setUpComponent = setUpComponent; + } + @Override protected CamelContext createCamelContext() throws Exception { - return configureServicenowComponent(super.createCamelContext()); + CamelContext context = super.createCamelContext(); + if (setUpComponent) { + configureServicenowComponent(context); + } + + return context; } - protected CamelContext configureServicenowComponent(CamelContext camelContext) throws Exception { + protected Map<String, Object> getParameters() { + HashMap<String, Object> parameters = new HashMap<>(); + parameters.put("instanceName", getSystemPropertyOrEnvVar("servicenow.instance")); + parameters.put("userName", getSystemPropertyOrEnvVar("servicenow.username")); + parameters.put("password", getSystemPropertyOrEnvVar("servicenow.password")); + parameters.put("oauthClientId", getSystemPropertyOrEnvVar("servicenow.oauth2.client.id")); + parameters.put("oauthClientSecret", getSystemPropertyOrEnvVar("servicenow.oauth2.client.secret")); + + return parameters; + } + + public void configureServicenowComponent(CamelContext camelContext) throws Exception { String userName = getSystemPropertyOrEnvVar("servicenow.username"); String password = getSystemPropertyOrEnvVar("servicenow.password"); String oauthClientId = getSystemPropertyOrEnvVar("servicenow.oauth2.client.id"); @@ -52,11 +78,9 @@ class ServiceNowTestSupport extends CamelTestSupport { camelContext.addComponent("servicenow", component); } - - return camelContext; } - protected String getSystemPropertyOrEnvVar(String systemProperty) { + public static String getSystemPropertyOrEnvVar(String systemProperty) { String answer = System.getProperty(systemProperty); if (ObjectHelper.isEmpty(answer)) { String envProperty = systemProperty.toUpperCase().replaceAll("[.-]", "_"); http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponent.java ---------------------------------------------------------------------- diff --git a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponent.java b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponent.java index adc4f28..9e33c2e 100644 --- a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponent.java +++ b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponent.java @@ -18,14 +18,17 @@ package org.apache.camel.component.twitter; import java.util.Map; +import org.apache.camel.ComponentVerifier; import org.apache.camel.Endpoint; +import org.apache.camel.VerifiableComponent; import org.apache.camel.impl.UriEndpointComponent; import org.apache.camel.spi.Metadata; /** * Twitter component */ -public class TwitterComponent extends UriEndpointComponent { +@Metadata(label = "verifiers", enums = "PARAMETERS,CONNECTIVITY") +public class TwitterComponent extends UriEndpointComponent implements VerifiableComponent { @Metadata(label = "security", secret = true) private String consumerKey; @@ -171,4 +174,10 @@ public class TwitterComponent extends UriEndpointComponent { return httpProxyPort; } + /** + * TODO: document + */ + public ComponentVerifier getVerifier() { + return new TwitterComponentVerifier(getCamelContext()); + } } http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponentVerifier.java ---------------------------------------------------------------------- diff --git a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponentVerifier.java b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponentVerifier.java new file mode 100644 index 0000000..062736c --- /dev/null +++ b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponentVerifier.java @@ -0,0 +1,84 @@ +/** + * 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.twitter; + +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.impl.verifier.DefaultComponentVerifier; +import org.apache.camel.impl.verifier.ResultBuilder; +import org.apache.camel.impl.verifier.ResultErrorBuilder; +import org.apache.camel.impl.verifier.ResultErrorHelper; +import twitter4j.Twitter; +import twitter4j.TwitterException; + +final class TwitterComponentVerifier extends DefaultComponentVerifier { + TwitterComponentVerifier(CamelContext camelContext) { + super(camelContext); + } + + // ********************************* + // Parameters validation + // ********************************* + + @Override + protected Result verifyParameters(Map<String, Object> parameters) { + return ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS) + .error(ResultErrorHelper.requiresOption("consumerKey", parameters)) + .error(ResultErrorHelper.requiresOption("consumerSecret", parameters)) + .error(ResultErrorHelper.requiresOption("accessToken", parameters)) + .error(ResultErrorHelper.requiresOption("accessTokenSecret", parameters)) + .build(); + } + + // ********************************* + // Connectivity validation + // ********************************* + + @Override + protected Result verifyConnectivity(Map<String, Object> parameters) { + return ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY) + .error(parameters, this::verifyCredentials) + .build(); + } + + private void verifyCredentials(ResultBuilder builder, Map<String, Object> parameters) throws Exception { + try { + TwitterConfiguration configuration = setProperties(new TwitterConfiguration(), parameters); + Twitter twitter = configuration.getTwitter(); + + twitter.verifyCredentials(); + } catch(TwitterException e) { + // verifyCredentials throws TwitterException when Twitter service or + // network is unavailable or if supplied credential is wrong + ResultErrorBuilder errorBuilder = ResultErrorBuilder.withHttpCodeAndText(e.getStatusCode(), e.getErrorMessage()) + .attribute("twitter.error.code", e.getErrorCode()) + .attribute("twitter.status.code", e.getStatusCode()) + .attribute("twitter.exception.code", e.getExceptionCode()) + .attribute("twitter.exception.message", e.getMessage()) + .attribute("twitter.exception.instance", e); + + // For a complete list of error codes see: + // https://dev.twitter.com/overview/api/response-codes + if (e.getErrorCode() == 89) { + errorBuilder.parameter("accessToken"); + } + + builder.error(errorBuilder.build()); + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterConfiguration.java ---------------------------------------------------------------------- diff --git a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterConfiguration.java b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterConfiguration.java index f2ce700..336fc65 100644 --- a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterConfiguration.java +++ b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterConfiguration.java @@ -21,6 +21,7 @@ import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriParam; import org.apache.camel.spi.UriParams; import org.apache.camel.spi.UriPath; +import org.apache.camel.util.ObjectHelper; import twitter4j.Twitter; import twitter4j.TwitterFactory; import twitter4j.TwitterStream; @@ -96,7 +97,7 @@ public class TwitterConfiguration { */ public void checkComplete() { if (twitter == null && twitterStream == null - && (consumerKey.isEmpty() || consumerSecret.isEmpty() || accessToken.isEmpty() || accessTokenSecret.isEmpty())) { + && (ObjectHelper.isEmpty(consumerKey) || ObjectHelper.isEmpty(consumerSecret) || ObjectHelper.isEmpty(accessToken) || ObjectHelper.isEmpty(accessTokenSecret))) { throw new IllegalArgumentException("twitter or twitterStream or all of consumerKey, consumerSecret, accessToken, and accessTokenSecret must be set!"); } } http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/CamelComponentVerifierTest.java ---------------------------------------------------------------------- diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/CamelComponentVerifierTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/CamelComponentVerifierTest.java new file mode 100644 index 0000000..7fcd3c7 --- /dev/null +++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/CamelComponentVerifierTest.java @@ -0,0 +1,107 @@ +/** + * 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.twitter; + +import java.util.Collections; +import java.util.Map; + +import org.apache.camel.ComponentVerifier; +import org.junit.Assert; +import org.junit.Test; + +public class CamelComponentVerifierTest extends CamelTwitterTestSupport { + @Override + public boolean isUseRouteBuilder() { + return false; + } + + @Test + public void testConnectivity() { + TwitterComponent component = context().getComponent("twitter", TwitterComponent.class); + TwitterComponentVerifier verifier = (TwitterComponentVerifier)component.getVerifier(); + + Map<String, Object> parameters = getParameters(); + ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus()); + } + + @Test + public void testInvalidKeyConfiguration() { + TwitterComponent component = context().getComponent("twitter", TwitterComponent.class); + TwitterComponentVerifier verifier = (TwitterComponentVerifier)component.getVerifier(); + + Map<String, Object> parameters = getParameters(); + parameters.put("consumerKey", "invalid"); + + ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals("401", result.getErrors().get(0).getCode()); + Assert.assertEquals(401, result.getErrors().get(0).getAttributes().get("twitter.status.code")); + Assert.assertEquals(32, result.getErrors().get(0).getAttributes().get("twitter.error.code")); + } + + @Test + public void testInvalidTokenConfiguration() { + TwitterComponent component = context().getComponent("twitter", TwitterComponent.class); + TwitterComponentVerifier verifier = (TwitterComponentVerifier)component.getVerifier(); + + Map<String, Object> parameters = getParameters(); + parameters.put("accessToken", "invalid"); + + ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals("401", result.getErrors().get(0).getCode()); + Assert.assertEquals(401, result.getErrors().get(0).getAttributes().get("twitter.status.code")); + Assert.assertEquals(89, result.getErrors().get(0).getAttributes().get("twitter.error.code")); + Assert.assertEquals(1, result.getErrors().get(0).getParameters().size()); + Assert.assertEquals("accessToken", result.getErrors().get(0).getParameters().iterator().next()); + } + + @Test + public void testEmptyConfiguration() { + TwitterComponent component = context().getComponent("twitter", TwitterComponent.class); + TwitterComponentVerifier verifier = (TwitterComponentVerifier)component.getVerifier(); + + { + // Parameters validation + ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.PARAMETERS, Collections.emptyMap()); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(4, result.getErrors().size()); + Assert.assertTrue(result.getErrors().get(0).getParameters().contains("consumerKey")); + Assert.assertTrue(result.getErrors().get(1).getParameters().contains("consumerSecret")); + Assert.assertTrue(result.getErrors().get(2).getParameters().contains("accessToken")); + Assert.assertTrue(result.getErrors().get(3).getParameters().contains("accessTokenSecret")); + } + + { + // Connectivity validation + ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, Collections.emptyMap()); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(ComponentVerifier.CODE_EXCEPTION, result.getErrors().get(0).getCode()); + Assert.assertNotNull(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE)); + Assert.assertTrue(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE) instanceof IllegalArgumentException); + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/CamelTwitterTestSupport.java ---------------------------------------------------------------------- diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/CamelTwitterTestSupport.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/CamelTwitterTestSupport.java index de189c4..19b4bdd 100644 --- a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/CamelTwitterTestSupport.java +++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/CamelTwitterTestSupport.java @@ -19,6 +19,8 @@ package org.apache.camel.component.twitter; import java.io.IOException; import java.io.InputStream; import java.net.URL; +import java.util.HashMap; +import java.util.Map; import java.util.Properties; import org.apache.camel.test.junit4.CamelTestSupport; @@ -74,6 +76,16 @@ public class CamelTwitterTestSupport extends CamelTestSupport { + "&accessTokenSecret=" + accessTokenSecret; } + protected Map<String, Object> getParameters() { + Map<String, Object> parameters = new HashMap<>(); + parameters.put("consumerKey", this.consumerKey); + parameters.put("consumerSecret", this.consumerSecret); + parameters.put("accessToken", this.accessToken); + parameters.put("accessTokenSecret", this.accessTokenSecret); + + return parameters; + } + protected void addProperty(Properties properties, String name, String envName) { if (!properties.containsKey(name)) { String value = System.getenv(envName);