diff --git a/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/build.xml b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/build.xml index f1a1e85a50..ebf679b8f4 100644 --- a/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/build.xml +++ b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/build.xml @@ -17,25 +17,14 @@ ~ under the License. --> - + - - - - - - - - - - - - - + + @@ -43,45 +32,8 @@ - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/components/analytics/iot-analytics/org.wso2.carbon.iot.geo.dashboard/src/main/resources/carbonapps/WSO2IoT-DeviceInfo-Receiver_1.0.0/WSO2IoT-DeviceInfo-Receiver.xml b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/WSO2IoT-DeviceInfo-Receiver_1.0.0/WSO2IoT-DeviceInfo-Receiver_1.0.0.xml similarity index 77% rename from components/analytics/iot-analytics/org.wso2.carbon.iot.geo.dashboard/src/main/resources/carbonapps/WSO2IoT-DeviceInfo-Receiver_1.0.0/WSO2IoT-DeviceInfo-Receiver.xml rename to components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/WSO2IoT-DeviceInfo-Receiver_1.0.0/WSO2IoT-DeviceInfo-Receiver_1.0.0.xml index 53cb45ec1f..008c07951b 100644 --- a/components/analytics/iot-analytics/org.wso2.carbon.iot.geo.dashboard/src/main/resources/carbonapps/WSO2IoT-DeviceInfo-Receiver_1.0.0/WSO2IoT-DeviceInfo-Receiver.xml +++ b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/WSO2IoT-DeviceInfo-Receiver_1.0.0/WSO2IoT-DeviceInfo-Receiver_1.0.0.xml @@ -1,13 +1,13 @@ - + false diff --git a/components/analytics/iot-analytics/org.wso2.carbon.iot.geo.dashboard/src/main/resources/carbonapps/WSO2IoT-DeviceInfo-Receiver_1.0.0/artifact.xml b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/WSO2IoT-DeviceInfo-Receiver_1.0.0/artifact.xml similarity index 93% rename from components/analytics/iot-analytics/org.wso2.carbon.iot.geo.dashboard/src/main/resources/carbonapps/WSO2IoT-DeviceInfo-Receiver_1.0.0/artifact.xml rename to components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/WSO2IoT-DeviceInfo-Receiver_1.0.0/artifact.xml index 6515e8034b..c64128717b 100644 --- a/components/analytics/iot-analytics/org.wso2.carbon.iot.geo.dashboard/src/main/resources/carbonapps/WSO2IoT-DeviceInfo-Receiver_1.0.0/artifact.xml +++ b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/WSO2IoT-DeviceInfo-Receiver_1.0.0/artifact.xml @@ -17,5 +17,5 @@ --> - WSO2IoT-DeviceInfo-Receiver.xml + WSO2IoT-DeviceInfo-Receiver_1.0.0.xml diff --git a/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/WSO2IoT-DeviceOperation-Publisher_1.0.0/WSO2IoT-DeviceOperation-Publisher_1.0.0.xml b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/WSO2IoT-DeviceOperation-Publisher_1.0.0/WSO2IoT-DeviceOperation-Publisher_1.0.0.xml new file mode 100644 index 0000000000..326925a9b0 --- /dev/null +++ b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/WSO2IoT-DeviceOperation-Publisher_1.0.0/WSO2IoT-DeviceOperation-Publisher_1.0.0.xml @@ -0,0 +1,42 @@ + + + + + + + + { + "deviceIdentifiers": [ + {{meta_deviceIdentifier}} + ], + "operation": { + "code": {{code}}, + "type": {{type}}, + "status": "PENDING", + "isEnabled": {{isEnabled}}, + "payLoad": {{payLoad}} + } + } + + + + HttpPost + https://localhost:9443/api/device-mgt/v1.0/devices/android/operations + + \ No newline at end of file diff --git a/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/accelerometer_sensor/accelerometer_store/artifact.xml b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/WSO2IoT-DeviceOperation-Publisher_1.0.0/artifact.xml similarity index 63% rename from components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/accelerometer_sensor/accelerometer_store/artifact.xml rename to components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/WSO2IoT-DeviceOperation-Publisher_1.0.0/artifact.xml index 4c34dc7aa9..51999398e2 100644 --- a/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/accelerometer_sensor/accelerometer_store/artifact.xml +++ b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/WSO2IoT-DeviceOperation-Publisher_1.0.0/artifact.xml @@ -1,5 +1,4 @@ - - - - org_wso2_iot_devices_accelerometer.xml + + WSO2IoT-DeviceOperation-Publisher_1.0.0.xml diff --git a/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/artifacts.xml b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/artifacts.xml new file mode 100644 index 0000000000..0e03c43307 --- /dev/null +++ b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/artifacts.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + diff --git a/components/analytics/iot-analytics/org.wso2.carbon.iot.geo.dashboard/src/main/resources/carbonapps/org.wso2.iot.DeviceInfoStream_1.0.0/artifact.xml b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/org.wso2.iot.DeviceInfoStream_1.0.0/artifact.xml similarity index 93% rename from components/analytics/iot-analytics/org.wso2.carbon.iot.geo.dashboard/src/main/resources/carbonapps/org.wso2.iot.DeviceInfoStream_1.0.0/artifact.xml rename to components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/org.wso2.iot.DeviceInfoStream_1.0.0/artifact.xml index 7071501ef4..51c7fb1510 100644 --- a/components/analytics/iot-analytics/org.wso2.carbon.iot.geo.dashboard/src/main/resources/carbonapps/org.wso2.iot.DeviceInfoStream_1.0.0/artifact.xml +++ b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/org.wso2.iot.DeviceInfoStream_1.0.0/artifact.xml @@ -17,5 +17,5 @@ --> - org.wso2.iot.DeviceInfoStream-1.0.0.json + org.wso2.iot.DeviceInfoStream_1.0.0.json diff --git a/components/analytics/iot-analytics/org.wso2.carbon.iot.geo.dashboard/src/main/resources/carbonapps/org.wso2.iot.DeviceInfoStream_1.0.0/org.wso2.iot.DeviceInfoStream-1.0.0.json b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/org.wso2.iot.DeviceInfoStream_1.0.0/org.wso2.iot.DeviceInfoStream_1.0.0.json similarity index 100% rename from components/analytics/iot-analytics/org.wso2.carbon.iot.geo.dashboard/src/main/resources/carbonapps/org.wso2.iot.DeviceInfoStream_1.0.0/org.wso2.iot.DeviceInfoStream-1.0.0.json rename to components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/org.wso2.iot.DeviceInfoStream_1.0.0/org.wso2.iot.DeviceInfoStream_1.0.0.json diff --git a/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/org.wso2.iot.operation_1.0.0/artifact.xml b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/org.wso2.iot.operation_1.0.0/artifact.xml new file mode 100644 index 0000000000..7e47330504 --- /dev/null +++ b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/org.wso2.iot.operation_1.0.0/artifact.xml @@ -0,0 +1,21 @@ + + + + org.wso2.iot.operation_1.0.0.json + diff --git a/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/org.wso2.iot.operation_1.0.0/org.wso2.iot.operation_1.0.0.json b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/org.wso2.iot.operation_1.0.0/org.wso2.iot.operation_1.0.0.json new file mode 100755 index 0000000000..44a0b0a453 --- /dev/null +++ b/components/analytics/iot-analytics/org.wso2.carbon.device.mgt.iot.analytics/src/main/resources/carbonapps/device_analytics/org.wso2.iot.operation_1.0.0/org.wso2.iot.operation_1.0.0.json @@ -0,0 +1,30 @@ +{ + "name": "org.wso2.iot.operation", + "version": "1.0.0", + "nickName": "", + "description": "Operation stream for WSO2 IoT Devices", + "metaData": [ + { + "name": "deviceIdentifier", + "type": "STRING" + } + ], + "payloadData": [ + { + "name": "code", + "type": "STRING" + }, + { + "name": "type", + "type": "STRING" + }, + { + "name": "isEnabled", + "type": "BOOL" + }, + { + "name": "payLoad", + "type": "STRING" + } + ] +} \ No newline at end of file diff --git a/components/analytics/iot-analytics/org.wso2.carbon.iot.geo.dashboard/src/main/resources/carbonapps/artifacts.xml b/components/analytics/iot-analytics/org.wso2.carbon.iot.geo.dashboard/src/main/resources/carbonapps/artifacts.xml index 04ee848f63..f0fdfa0660 100644 --- a/components/analytics/iot-analytics/org.wso2.carbon.iot.geo.dashboard/src/main/resources/carbonapps/artifacts.xml +++ b/components/analytics/iot-analytics/org.wso2.carbon.iot.geo.dashboard/src/main/resources/carbonapps/artifacts.xml @@ -21,7 +21,6 @@ - @@ -32,7 +31,6 @@ - diff --git a/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/pom.xml b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/pom.xml new file mode 100644 index 0000000000..fc0392dd48 --- /dev/null +++ b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/pom.xml @@ -0,0 +1,133 @@ + + + + + org.wso2.carbon.devicemgt-plugins + cdmf-transport-adapters + 4.0.88-SNAPSHOT + ../../pom.xml + + 4.0.0 + org.wso2.carbon.device.mgt.output.adapter.http + + bundle + WSO2 Carbon - Device Management Output HTTP adapter Module + + org.wso2.carbon.device.mgt.output.adapter.http provides the back-end functionality of oauth http event adapter + + http://wso2.org + + + + org.wso2.carbon.analytics-common + org.wso2.carbon.event.output.adapter.core + + + org.wso2.carbon + org.wso2.carbon.logging + + + org.apache.httpcomponents.wso2 + httpcore + + + org.wso2.orbit.org.apache.httpcomponents + httpclient + + + org.wso2.carbon.devicemgt + org.wso2.carbon.identity.jwt.client.extension + + + + + + + org.apache.felix + maven-scr-plugin + + + generate-scr-descriptor + + scr + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.apache.felix + maven-bundle-plugin + + true + + + ${project.artifactId} + ${project.artifactId} + + org.wso2.carbon.device.mgt.output.adapter.http.internal, + org.wso2.carbon.device.mgt.output.adapter.http.internal.* + + + !org.wso2.carbon.device.mgt.output.adapter.http.internal, + !org.wso2.carbon.device.mgt.output.adapter.http.internal.*, + org.wso2.carbon.device.mgt.output.adapter.http.* + + + org.wso2.carbon.event.output.adapter.core, + org.wso2.carbon.event.output.adapter.core.*, + javax.net.ssl, + org.apache.commons.logging, + org.apache.http, + org.apache.http.client, + org.apache.http.client.methods, + org.apache.http.conn.socket, + org.apache.http.conn.ssl, + org.apache.http.entity, + org.apache.http.impl.client, + org.apache.http.util, + org.eclipse.paho.client.mqttv3, + org.eclipse.paho.client.mqttv3.persist, + org.json.simple, + org.json.simple.parser, + org.osgi.framework, + org.osgi.service.component, + org.wso2.carbon.context, + org.apache.commons.codec.binary, + org.apache.http.client.entity, + org.apache.http.message, + org.apache.commons.ssl, + org.wso2.carbon.identity.jwt.client.extension.*, + org.wso2.carbon.user.api, + javax.xml.namespace; version=0.0.0 + + * + + + + + + + + + \ No newline at end of file diff --git a/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/HTTPEventAdapter.java b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/HTTPEventAdapter.java new file mode 100644 index 0000000000..0fdd7189f0 --- /dev/null +++ b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/HTTPEventAdapter.java @@ -0,0 +1,428 @@ +/* +* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. 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.wso2.carbon.device.mgt.output.adapter.http; + +import org.apache.commons.httpclient.HostConfiguration; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpConnectionManager; +import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; +import org.apache.commons.httpclient.methods.EntityEnclosingMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.PutMethod; +import org.apache.commons.httpclient.methods.StringRequestEntity; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.HttpHost; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.conn.params.ConnRoutePNames; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.message.BasicHeader; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.output.adapter.http.internal.OutputAdapterServiceDataHolder; +import org.wso2.carbon.device.mgt.output.adapter.http.util.HTTPConnectionConfiguration; +import org.wso2.carbon.device.mgt.output.adapter.http.util.HTTPEventAdapterConstants; +import org.wso2.carbon.device.mgt.output.adapter.http.util.HTTPUtil; +import org.wso2.carbon.device.mgt.output.adapter.http.util.RegistrationProfile; +import org.wso2.carbon.event.output.adapter.core.EventAdapterUtil; +import org.wso2.carbon.event.output.adapter.core.OutputEventAdapter; +import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterConfiguration; +import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException; +import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterRuntimeException; +import org.wso2.carbon.event.output.adapter.core.exception.TestConnectionNotSupportedException; +import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo; +import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException; +import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService; +import org.wso2.carbon.user.api.UserStoreException; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.UnknownHostException; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class HTTPEventAdapter implements OutputEventAdapter { + private static final Log log = LogFactory.getLog(OutputEventAdapter.class); + private static ExecutorService executorService; + private static HttpConnectionManager connectionManager; + private OutputEventAdapterConfiguration eventAdapterConfiguration; + private Map globalProperties; + private String clientMethod; + private int tenantId; + private HTTPConnectionConfiguration httpConnectionConfiguration; + private String contentType; + private HttpClient httpClient = null; + private HostConfiguration hostConfiguration = null; + private String clientId, clientSecret; + + + public HTTPEventAdapter(OutputEventAdapterConfiguration eventAdapterConfiguration, + Map globalProperties) { + this.eventAdapterConfiguration = eventAdapterConfiguration; + this.globalProperties = globalProperties; + this.clientMethod = eventAdapterConfiguration.getStaticProperties() + .get(HTTPEventAdapterConstants.ADAPTER_HTTP_CLIENT_METHOD); + } + + @Override + public void init() throws OutputEventAdapterException { + + tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + + //ExecutorService will be assigned if it is null + if (executorService == null) { + int minThread; + int maxThread; + long defaultKeepAliveTime; + int jobQueSize; + + //If global properties are available those will be assigned else constant values will be assigned + if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME) != null) { + minThread = Integer + .parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME)); + } else { + minThread = HTTPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE; + } + + if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME) != null) { + maxThread = Integer + .parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME)); + } else { + maxThread = HTTPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE; + } + + if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME) != null) { + defaultKeepAliveTime = Integer + .parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME)); + } else { + defaultKeepAliveTime = HTTPEventAdapterConstants.DEFAULT_KEEP_ALIVE_TIME_IN_MILLIS; + } + + if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME) != null) { + jobQueSize = Integer + .parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME)); + } else { + jobQueSize = HTTPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE; + } + executorService = new ThreadPoolExecutor(minThread, maxThread, defaultKeepAliveTime, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue<>(jobQueSize)); + + //configurations for the httpConnectionManager which will be shared by every http adapter + int defaultMaxConnectionsPerHost; + int maxTotalConnections; + + if (globalProperties.get(HTTPEventAdapterConstants.DEFAULT_MAX_CONNECTIONS_PER_HOST) != null) { + defaultMaxConnectionsPerHost = Integer + .parseInt(globalProperties.get(HTTPEventAdapterConstants.DEFAULT_MAX_CONNECTIONS_PER_HOST)); + } else { + defaultMaxConnectionsPerHost = HTTPEventAdapterConstants.DEFAULT_DEFAULT_MAX_CONNECTIONS_PER_HOST; + } + + if (globalProperties.get(HTTPEventAdapterConstants.MAX_TOTAL_CONNECTIONS) != null) { + maxTotalConnections = Integer + .parseInt(globalProperties.get(HTTPEventAdapterConstants.MAX_TOTAL_CONNECTIONS)); + } else { + maxTotalConnections = HTTPEventAdapterConstants.DEFAULT_MAX_TOTAL_CONNECTIONS; + } + + connectionManager = new MultiThreadedHttpConnectionManager(); + connectionManager.getParams().setDefaultMaxConnectionsPerHost(defaultMaxConnectionsPerHost); + connectionManager.getParams().setMaxTotalConnections(maxTotalConnections); + } + } + + @Override + public void testConnect() throws TestConnectionNotSupportedException { + throw new TestConnectionNotSupportedException("Test connection is not available"); + } + + @Override + public void connect() { + this.checkHTTPClientInit(eventAdapterConfiguration.getStaticProperties()); + httpConnectionConfiguration = + new HTTPConnectionConfiguration(eventAdapterConfiguration, globalProperties); + generateToken(); + } + + @Override + public void publish(Object message, Map dynamicProperties) { + //Load dynamic properties + String url = dynamicProperties.get(HTTPEventAdapterConstants.ADAPTER_MESSAGE_URL); + Map headers = this + .extractHeaders(dynamicProperties.get(HTTPEventAdapterConstants.ADAPTER_HEADERS)); + String payload = message.toString(); + + try { + executorService.submit(new HTTPSender(url, payload, headers, httpClient)); + } catch (RejectedExecutionException e) { + EventAdapterUtil + .logAndDrop(eventAdapterConfiguration.getName(), message, "Job queue is full", e, log, tenantId); + } catch (MalformedURLException e) { + log.error("Malformed url: '" + url + "'", e); + } + } + + @Override + public void disconnect() { + //not required + } + + @Override + public void destroy() { + //not required + } + + @Override + public boolean isPolled() { + return false; + } + + private void checkHTTPClientInit(Map staticProperties) { + + if (this.httpClient != null) { + return; + } + + synchronized (HTTPEventAdapter.class) { + if (this.httpClient != null) { + return; + } + + httpClient = new HttpClient(connectionManager); + + String messageFormat = eventAdapterConfiguration.getMessageFormat(); + if (messageFormat.equalsIgnoreCase("json")) { + contentType = "application/json"; + } else if (messageFormat.equalsIgnoreCase("text")) { + contentType = "text/plain"; + } else { + contentType = "text/xml"; + } + } + } + + private Map extractHeaders(String headers) { + if (headers == null || headers.trim().length() == 0) { + return null; + } + + String[] entries = headers.split(HTTPEventAdapterConstants.HEADER_SEPARATOR); + String[] keyValue; + Map result = new HashMap<>(); + for (String header : entries) { + try { + keyValue = header.split(HTTPEventAdapterConstants.ENTRY_SEPARATOR, 2); + result.put(keyValue[0].trim(), keyValue[1].trim()); + } catch (Exception e) { + log.warn("Header property '" + header + "' is not defined in the correct format.", e); + } + } + return result; + } + + private void generateToken() { + String username = httpConnectionConfiguration.getUsername(); + String password = httpConnectionConfiguration.getPassword(); + String dcrUrlString = httpConnectionConfiguration.getDcrUrl(); + + if (dcrUrlString != null && !dcrUrlString.isEmpty()) { + try { + URL dcrUrl = new URL(dcrUrlString); + org.apache.http.client.HttpClient dcrHttpClient = HTTPUtil.getHttpClient(dcrUrl.getProtocol()); + HttpPost postMethod = new HttpPost(dcrUrlString); + RegistrationProfile registrationProfile = new RegistrationProfile(); + registrationProfile.setCallbackUrl(HTTPEventAdapterConstants.EMPTY_STRING); + registrationProfile.setGrantType(HTTPEventAdapterConstants.GRANT_TYPE); + registrationProfile.setOwner(username); + registrationProfile.setTokenScope(HTTPEventAdapterConstants.TOKEN_SCOPE); + if (!httpConnectionConfiguration.isGlobalCredentialSet()) { + registrationProfile.setClientName(HTTPEventAdapterConstants.APPLICATION_NAME_PREFIX + + httpConnectionConfiguration.getAdapterName() + + "_" + tenantId); + registrationProfile.setIsSaasApp(false); + } else { + registrationProfile.setClientName(HTTPEventAdapterConstants.APPLICATION_NAME_PREFIX + + httpConnectionConfiguration.getAdapterName()); + registrationProfile.setIsSaasApp(true); + } + String jsonString = registrationProfile.toJSON(); + StringEntity requestEntity = new StringEntity(jsonString, ContentType.APPLICATION_JSON); + postMethod.setEntity(requestEntity); + String basicAuth = getBase64Encode(username, password); + postMethod.setHeader(new BasicHeader(HTTPEventAdapterConstants.AUTHORIZATION_HEADER_NAME, + HTTPEventAdapterConstants.AUTHORIZATION_HEADER_VALUE_PREFIX + + basicAuth)); + HttpResponse httpResponse = dcrHttpClient.execute(postMethod); + if (httpResponse != null) { + String response = HTTPUtil.getResponseString(httpResponse); + try { + if (response != null) { + JSONParser jsonParser = new JSONParser(); + JSONObject jsonPayload = (JSONObject) jsonParser.parse(response); + clientId = (String) jsonPayload.get(HTTPEventAdapterConstants.CLIENT_ID); + clientSecret = (String) jsonPayload.get(HTTPEventAdapterConstants.CLIENT_SECRET); + } + } catch (ParseException e) { + String msg = "error occurred while parsing generating token for the adapter"; + log.error(msg, e); + } + } + } catch (MalformedURLException e) { + throw new OutputEventAdapterRuntimeException("Invalid dcrUrl : " + dcrUrlString); + } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | IOException e) { + throw new OutputEventAdapterRuntimeException("Failed to create an https connection.", e); + } + } else { + throw new OutputEventAdapterRuntimeException("Invalid configuration for mqtt publisher"); + } + } + + private String getBase64Encode(String key, String value) { + return new String(org.apache.commons.ssl.Base64.encodeBase64((key + ":" + value).getBytes())); + } + + + /** + * This class represents a job to send an HTTP request to a target URL. + */ + class HTTPSender implements Runnable { + + private String url; + private String payload; + private Map headers; + + private HttpClient httpClient; + + public HTTPSender(String url, String payload, Map headers, + HttpClient httpClient) throws MalformedURLException { + + if (tenantId == -1234) { + this.url = url; + } else { + URL urlObj = new URL(url); + String protocol = urlObj.getProtocol(); + String host = urlObj.getHost(); + int port = urlObj.getPort(); + String path = "t/" + PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getTenantDomain(true) + "/" + urlObj.getPath(); + this.url = protocol + "://" + host + ":" + port + "/" + path; + } + this.payload = payload; + this.headers = headers; + this.httpClient = httpClient; + } + + public String getUrl() { + return url; + } + + public String getPayload() { + return payload; + } + + public Map getHeaders() { + return headers; + } + + public HttpClient getHttpClient() { + return httpClient; + } + + public void run() { + + EntityEnclosingMethod method = null; + + try { + + if (clientMethod.equalsIgnoreCase(HTTPEventAdapterConstants.CONSTANT_HTTP_PUT)) { + method = new PutMethod(this.getUrl()); + } else { + method = new PostMethod(this.getUrl()); + } + + if (hostConfiguration == null) { + URL hostUrl = new URL(this.getUrl()); + hostConfiguration = new HostConfiguration(); + hostConfiguration.setHost(hostUrl.getHost(), hostUrl.getPort(), hostUrl.getProtocol()); + } + + method.setRequestEntity(new StringRequestEntity(this.getPayload(), contentType, "UTF-8")); + method.setRequestHeader("Authorization", + "Bearer " + getToken(clientId, clientSecret)); + + if (this.getHeaders() != null) { + for (Map.Entry header : this.getHeaders().entrySet()) { + method.setRequestHeader(header.getKey(), header.getValue()); + } + } + + this.getHttpClient().executeMethod(hostConfiguration, method); + + } catch (UnknownHostException e) { + EventAdapterUtil.logAndDrop(eventAdapterConfiguration.getName(), this.getPayload(), + "Cannot connect to " + this.getUrl(), e, log, tenantId); + } catch (IOException e) { + EventAdapterUtil + .logAndDrop(eventAdapterConfiguration.getName(), this.getPayload(), null, e, log, tenantId); + } catch (JWTClientException | UserStoreException e) { + log.error("Failed to create an oauth token with jwt grant type.", e); + } finally { + if (method != null) { + method.releaseConnection(); + } + } + } + + private String getToken(String clientId, String clientSecret) + throws UserStoreException, JWTClientException { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true); + try { + String scopes = httpConnectionConfiguration.getScopes(); + String username = httpConnectionConfiguration.getUsername(); + if (httpConnectionConfiguration.isGlobalCredentialSet()) { + username = PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getUserRealm().getRealmConfiguration().getAdminUserName() + "@" + PrivilegedCarbonContext + .getThreadLocalCarbonContext().getTenantDomain(true); + } + + JWTClientManagerService jwtClientManagerService = + OutputAdapterServiceDataHolder.getJwtClientManagerService(); + AccessTokenInfo accessTokenInfo = jwtClientManagerService.getJWTClient().getAccessToken( + clientId, clientSecret, username, scopes); + return accessTokenInfo.getAccessToken(); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } + } + +} \ No newline at end of file diff --git a/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/HTTPEventAdapterFactory.java b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/HTTPEventAdapterFactory.java new file mode 100644 index 0000000000..6be72a2140 --- /dev/null +++ b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/HTTPEventAdapterFactory.java @@ -0,0 +1,116 @@ +/* +* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. 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.wso2.carbon.device.mgt.output.adapter.http; + +import org.wso2.carbon.device.mgt.output.adapter.http.util.HTTPEventAdapterConstants; +import org.wso2.carbon.event.output.adapter.core.MessageType; +import org.wso2.carbon.event.output.adapter.core.OutputEventAdapter; +import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterConfiguration; +import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterFactory; +import org.wso2.carbon.event.output.adapter.core.Property; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.ResourceBundle; + +/** + * The http event adapter factory class to create a http output adapter + */ +public class HTTPEventAdapterFactory extends OutputEventAdapterFactory { + private ResourceBundle resourceBundle = + ResourceBundle.getBundle("org.wso2.carbon.device.mgt.output.adapter.http.i18n.Resources", Locale.getDefault()); + + @Override + public String getType() { + return HTTPEventAdapterConstants.ADAPTER_TYPE_HTTP; + } + + @Override + public List getSupportedMessageFormats() { + List supportedMessageFormats = new ArrayList<>(); + supportedMessageFormats.add(MessageType.TEXT); + supportedMessageFormats.add(MessageType.XML); + supportedMessageFormats.add(MessageType.JSON); + return supportedMessageFormats; + } + + @Override + public List getStaticPropertyList() { + + List staticPropertyList = new ArrayList<>(); + + Property clientMethod = new Property(HTTPEventAdapterConstants.ADAPTER_HTTP_CLIENT_METHOD); + clientMethod.setDisplayName( + resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_HTTP_CLIENT_METHOD)); + clientMethod.setRequired(true); + clientMethod.setOptions(new String[]{HTTPEventAdapterConstants.CONSTANT_HTTP_POST, HTTPEventAdapterConstants.CONSTANT_HTTP_PUT}); + clientMethod.setDefaultValue(HTTPEventAdapterConstants.CONSTANT_HTTP_POST); + + staticPropertyList.add(clientMethod); + + return staticPropertyList; + + } + + @Override + public List getDynamicPropertyList() { + List dynamicPropertyList = new ArrayList<>(); + + Property urlProp = new Property(HTTPEventAdapterConstants.ADAPTER_MESSAGE_URL); + urlProp.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_MESSAGE_URL)); + urlProp.setHint(resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_MESSAGE_URL_HINT)); + urlProp.setRequired(true); + + Property usernameProp = new Property(HTTPEventAdapterConstants.ADAPTER_USERNAME); + usernameProp.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_USERNAME)); + usernameProp.setHint(resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_USERNAME_HINT)); + usernameProp.setRequired(false); + + Property passwordProp = new Property(HTTPEventAdapterConstants.ADAPTER_PASSWORD); + passwordProp.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_PASSWORD)); + passwordProp.setHint(resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_PASSWORD_HINT)); + passwordProp.setRequired(false); + passwordProp.setSecured(true); + passwordProp.setEncrypted(true); + + Property headersProp = new Property(HTTPEventAdapterConstants.ADAPTER_HEADERS); + headersProp.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_HEADERS)); + headersProp.setHint(resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_HEADERS_HINT)); + headersProp.setRequired(false); + + dynamicPropertyList.add(urlProp); + dynamicPropertyList.add(usernameProp); + dynamicPropertyList.add(passwordProp); + dynamicPropertyList.add(headersProp); + + return dynamicPropertyList; + } + + @Override + public String getUsageTips() { + return null; + } + + @Override + public OutputEventAdapter createEventAdapter(OutputEventAdapterConfiguration eventAdapterConfiguration, + Map globalProperties) { + return new HTTPEventAdapter(eventAdapterConfiguration, globalProperties); + } +} diff --git a/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/internal/HTTPEventAdapterServiceComponent.java b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/internal/HTTPEventAdapterServiceComponent.java new file mode 100644 index 0000000000..11352af3ee --- /dev/null +++ b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/internal/HTTPEventAdapterServiceComponent.java @@ -0,0 +1,59 @@ +/* +* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. 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.wso2.carbon.device.mgt.output.adapter.http.internal; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.osgi.service.component.ComponentContext; +import org.wso2.carbon.device.mgt.output.adapter.http.HTTPEventAdapterFactory; +import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterFactory; +import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService; + +/** + * @scr.component component.name="output.Http.AdapterService.component" immediate="true" + * @scr.reference name="jwt.client.service" interface="org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService" + * cardinality="1..1" + * policy="dynamic" + * bind="setJWTClientManagerService" + * unbind="unsetJWTClientManagerService" + */ +public class HTTPEventAdapterServiceComponent { + + private static final Log log = LogFactory.getLog(HTTPEventAdapterServiceComponent.class); + + protected void activate(ComponentContext context) { + try { + HTTPEventAdapterFactory httpEventAdaptorFactory = new HTTPEventAdapterFactory(); + context.getBundleContext().registerService(OutputEventAdapterFactory.class.getName(), + httpEventAdaptorFactory, null); + if (log.isDebugEnabled()) { + log.debug("Successfully deployed the output HTTP event adaptor service"); + } + } catch (RuntimeException e) { + log.error("Exception occurred when deploying HTTP publisher service", e); + } + } + + protected void setJWTClientManagerService(JWTClientManagerService jwtClientManagerService) { + OutputAdapterServiceDataHolder.setJwtClientManagerService(jwtClientManagerService); + } + + protected void unsetJWTClientManagerService(JWTClientManagerService jwtClientManagerService) { + OutputAdapterServiceDataHolder.setJwtClientManagerService(null); + } +} diff --git a/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/internal/OutputAdapterServiceDataHolder.java b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/internal/OutputAdapterServiceDataHolder.java new file mode 100644 index 0000000000..57e3438b91 --- /dev/null +++ b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/internal/OutputAdapterServiceDataHolder.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * Licensed 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.wso2.carbon.device.mgt.output.adapter.http.internal; + +import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService; + +/** + * common place to hold some OSGI service references. + */ +public final class OutputAdapterServiceDataHolder { + + private static JWTClientManagerService jwtClientManagerService; + + public static JWTClientManagerService getJwtClientManagerService() { + return jwtClientManagerService; + } + + public static void setJwtClientManagerService( + JWTClientManagerService jwtClientManagerService) { + OutputAdapterServiceDataHolder.jwtClientManagerService = jwtClientManagerService; + } +} diff --git a/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/util/HTTPConnectionConfiguration.java b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/util/HTTPConnectionConfiguration.java new file mode 100644 index 0000000000..30e9e2560d --- /dev/null +++ b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/util/HTTPConnectionConfiguration.java @@ -0,0 +1,83 @@ +/* +* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. 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.wso2.carbon.device.mgt.output.adapter.http.util; + +import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterConfiguration; + +import java.util.Map; + +public class HTTPConnectionConfiguration { + + private String adapterName; + private String username; + private String password; + private String dcrUrl; + private String scopes; + private String tokenUrl; + private boolean globalCredentialSet; + + public HTTPConnectionConfiguration(OutputEventAdapterConfiguration eventAdapterConfiguration, + Map globalProperties) { + adapterName = eventAdapterConfiguration.getName(); + this.username = eventAdapterConfiguration.getStaticProperties().get(HTTPEventAdapterConstants.ADAPTER_USERNAME); + this.password = eventAdapterConfiguration.getStaticProperties().get(HTTPEventAdapterConstants.ADAPTER_PASSWORD); + if ((username == null || username.isEmpty()) && (password == null || password.isEmpty())) { + username = globalProperties.get(HTTPEventAdapterConstants.ADAPTER_USERNAME); + password = globalProperties.get(HTTPEventAdapterConstants.ADAPTER_PASSWORD); + globalCredentialSet = true; + } + + this.dcrUrl = PropertyUtils + .replaceMqttProperty(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_CONF_DCR_URL)); + this.tokenUrl = PropertyUtils + .replaceMqttProperty(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_CONF_TOKEN_URL)); + this.scopes = eventAdapterConfiguration.getStaticProperties().get(HTTPEventAdapterConstants.ADAPTER_CONF_SCOPES); + if (scopes == null) { + this.scopes = HTTPEventAdapterConstants.EMPTY_STRING; + } + } + + public String getTokenUrl() { + return tokenUrl; + } + + public String getDcrUrl() { + return dcrUrl; + } + + public String getScopes() { + return scopes; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public String getAdapterName() { + return adapterName; + } + + public boolean isGlobalCredentialSet() { + return globalCredentialSet; + } + +} diff --git a/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/util/HTTPEventAdapterConstants.java b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/util/HTTPEventAdapterConstants.java new file mode 100644 index 0000000000..212afe7367 --- /dev/null +++ b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/util/HTTPEventAdapterConstants.java @@ -0,0 +1,66 @@ +/* +* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. 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.wso2.carbon.device.mgt.output.adapter.http.util; + +public class HTTPEventAdapterConstants { + + public static final String ADAPTER_TYPE_HTTP = "oauth-http"; + public static final String ADAPTER_MESSAGE_URL = "http.url"; + public static final String ADAPTER_MESSAGE_URL_HINT = "http.url.hint"; + public static final String ADAPTER_CONF_DCR_URL = "dcrUrl"; + public static final String ADAPTER_CONF_TOKEN_URL = "tokenUrl"; + public static final int ADAPTER_MIN_THREAD_POOL_SIZE = 8; + public static final int ADAPTER_MAX_THREAD_POOL_SIZE = 100; + public static final int ADAPTER_EXECUTOR_JOB_QUEUE_SIZE = 2000; + public static final long DEFAULT_KEEP_ALIVE_TIME_IN_MILLIS = 20000; + public static final String ADAPTER_MIN_THREAD_POOL_SIZE_NAME = "minThread"; + public static final String ADAPTER_MAX_THREAD_POOL_SIZE_NAME = "maxThread"; + public static final String ADAPTER_KEEP_ALIVE_TIME_NAME = "keepAliveTimeInMillis"; + public static final String ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME = "jobQueueSize"; + public static final String ADAPTER_USERNAME = "username"; + public static final String ADAPTER_USERNAME_HINT = "http.username.hint"; + public static final String ADAPTER_PASSWORD = "password"; + public static final String ADAPTER_PASSWORD_HINT = "http.password.hint"; + public static final String ADAPTER_CONF_SCOPES = "scopes"; + public static final String ADAPTER_CONF_SCOPES_HINT = "scopes.hint"; + public static final String ADAPTER_HEADERS = "http.headers"; + public static final String ADAPTER_HEADERS_HINT = "http.headers.hint"; + public static final String HEADER_SEPARATOR = ","; + public static final String ENTRY_SEPARATOR = ":"; + public static final String ADAPTER_HTTP_CLIENT_METHOD = "http.client.method"; + public static final String CONSTANT_HTTP_POST = "HttpPost"; + public static final String CONSTANT_HTTP_PUT = "HttpPut"; + + public static final String EMPTY_STRING = ""; + public static final String DEFAULT_CALLBACK = ""; + public static final String DEFAULT_PASSWORD = ""; + public static final String GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer"; + public static final String TOKEN_SCOPE = "production"; + public static final String APPLICATION_NAME_PREFIX = "OutputAdapter_"; + public static final String CLIENT_ID = "clientId"; + public static final String CLIENT_SECRET = "clientSecret"; + + public static final String AUTHORIZATION_HEADER_NAME = "Authorization"; + public static final String AUTHORIZATION_HEADER_VALUE_PREFIX = "Basic "; + + //configurations for the httpConnectionManager + public static final String DEFAULT_MAX_CONNECTIONS_PER_HOST = "defaultMaxConnectionsPerHost"; + public static final int DEFAULT_DEFAULT_MAX_CONNECTIONS_PER_HOST = 2; + public static final String MAX_TOTAL_CONNECTIONS = "maxTotalConnections"; + public static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 20; +} diff --git a/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/util/HTTPUtil.java b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/util/HTTPUtil.java new file mode 100644 index 0000000000..4e9b4c86dc --- /dev/null +++ b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/util/HTTPUtil.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.wso2.carbon.device.mgt.output.adapter.http.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLContextBuilder; +import org.apache.http.conn.ssl.TrustSelfSignedStrategy; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; + +/** + * This is the utility class that is used for HTTP input adapter. + */ +public class HTTPUtil { + private static final String HTTPS_PROTOCOL = "https"; + private static final Log log = LogFactory.getLog(HTTPUtil.class); + + /** + * Return a http client instance + * + * @param protocol- service endpoint protocol http/https + * @return + */ + public static HttpClient getHttpClient(String protocol) + throws IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException { + HttpClient httpclient; + if (HTTPS_PROTOCOL.equals(protocol)) { + SSLContextBuilder builder = new SSLContextBuilder(); + builder.loadTrustMaterial(null, new TrustSelfSignedStrategy()); + SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build()); + httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); + } else { + httpclient = HttpClients.createDefault(); + } + return httpclient; + } + + public static String getResponseString(HttpResponse httpResponse) throws IOException { + BufferedReader br = null; + try { + br = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent())); + String readLine; + String response = ""; + while (((readLine = br.readLine()) != null)) { + response += readLine; + } + return response; + } finally { + EntityUtils.consumeQuietly(httpResponse.getEntity()); + if (br != null) { + try { + br.close(); + } catch (IOException e) { + log.warn("Error while closing the connection! " + e.getMessage()); + } + } + } + } + +} diff --git a/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/util/PropertyUtils.java b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/util/PropertyUtils.java new file mode 100644 index 0000000000..47773148b0 --- /dev/null +++ b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/util/PropertyUtils.java @@ -0,0 +1,40 @@ +/* +* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. 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.wso2.carbon.device.mgt.output.adapter.http.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PropertyUtils { + + //This method is only used if the mb features are within DAS. + public static String replaceMqttProperty(String urlWithPlaceholders) { + String regex = "\\$\\{(.*?)\\}"; + Pattern pattern = Pattern.compile(regex); + Matcher matchPattern = pattern.matcher(urlWithPlaceholders); + while (matchPattern.find()) { + String sysPropertyName = matchPattern.group(1); + String sysPropertyValue = System.getProperty(sysPropertyName); + if (sysPropertyValue != null && !sysPropertyName.isEmpty()) { + urlWithPlaceholders = urlWithPlaceholders.replaceAll("\\$\\{(" + sysPropertyName + ")\\}", sysPropertyValue); + } + } + return urlWithPlaceholders; + } +} diff --git a/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/util/RegistrationProfile.java b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/util/RegistrationProfile.java new file mode 100644 index 0000000000..9095bbde22 --- /dev/null +++ b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/java/org/wso2/carbon/device/mgt/output/adapter/http/util/RegistrationProfile.java @@ -0,0 +1,98 @@ +/* +* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. 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.wso2.carbon.device.mgt.output.adapter.http.util; + +/** + * This class represents the data that are required to register + * the oauth application. + */ +public class RegistrationProfile { + + private static final String TAG = RegistrationProfile.class.getSimpleName(); + private String callbackUrl; + private String clientName; + private String tokenScope; + private String owner; + private String grantType; + private String applicationType; + private boolean isSaasApp; + + public String getCallbackUrl() { + return callbackUrl; + } + + public void setCallbackUrl(String callBackUrl) { + this.callbackUrl = callBackUrl; + } + + public String getClientName() { + return clientName; + } + + public void setClientName(String clientName) { + this.clientName = clientName; + } + + public String getTokenScope() { + return tokenScope; + } + + public void setTokenScope(String tokenScope) { + this.tokenScope = tokenScope; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public String getGrantType() { + return grantType; + } + + public void setGrantType(String grantType) { + this.grantType = grantType; + } + + public String getApplicationType() { + return applicationType; + } + + public void setApplicationType(String applicationType) { + this.applicationType = applicationType; + } + + public boolean isSaasApp() { + return isSaasApp; + } + + public void setIsSaasApp(boolean isSaasApp) { + this.isSaasApp = isSaasApp; + } + + public String toJSON() { + String jsonString = + "{\"callbackUrl\": \"" + callbackUrl + "\",\"clientName\": \"" + clientName + "\", \"tokenScope\": " + + "\"" + tokenScope + "\", \"owner\": \"" + owner + "\"," + "\"grantType\": \"" + grantType + + "\", \"saasApp\" : " + isSaasApp + " }\n"; + return jsonString; + } +} \ No newline at end of file diff --git a/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/resources/org/wso2/carbon/device/mgt/output/adapter/http/i18n/Resources.properties b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/resources/org/wso2/carbon/device/mgt/output/adapter/http/i18n/Resources.properties new file mode 100644 index 0000000000..0ceb2d520a --- /dev/null +++ b/components/extensions/cdmf-transport-adapters/output/org.wso2.carbon.device.mgt.output.adapter.http/src/main/resources/org/wso2/carbon/device/mgt/output/adapter/http/i18n/Resources.properties @@ -0,0 +1,28 @@ +# +# Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +# +# WSO2 Inc. 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. +# + +http.url=URL +http.url.hint=The target HTTP/HTTPS URL, e.g. "http://yourhost:8080/service (URL will auto format for tenants)" +username=Username +http.username.hint=Username to obtain oauth token. Leave empty to use default. +password=Password +http.password.hint=Password Username to obtain oauth token. Leave empty to use default. +http.headers=Headers +http.headers.hint=Custom HTTP headers, e.g. "header1: value1, header2: value2" +http.client.method=HTTP Client Method +http.description=Publish events to the target url according to the selected http client method \ No newline at end of file diff --git a/components/extensions/cdmf-transport-adapters/pom.xml b/components/extensions/cdmf-transport-adapters/pom.xml index 94f5f6939a..43e46252a5 100644 --- a/components/extensions/cdmf-transport-adapters/pom.xml +++ b/components/extensions/cdmf-transport-adapters/pom.xml @@ -38,6 +38,7 @@ input/org.wso2.carbon.device.mgt.input.adapter.mqtt input/org.wso2.carbon.device.mgt.input.adapter.xmpp input/org.wso2.carbon.device.mgt.input.adapter.thrift + output/org.wso2.carbon.device.mgt.output.adapter.http output/org.wso2.carbon.device.mgt.output.adapter.mqtt output/org.wso2.carbon.device.mgt.output.adapter.xmpp output/org.wso2.carbon.device.mgt.output.adapter.websocket diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/impl/EventReceiverServiceImpl.java b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/impl/EventReceiverServiceImpl.java index 9f16bea058..85d7461166 100644 --- a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/impl/EventReceiverServiceImpl.java +++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/impl/EventReceiverServiceImpl.java @@ -24,7 +24,10 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException; import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException; +import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil; import org.wso2.carbon.mdm.services.android.bean.DeviceState; import org.wso2.carbon.mdm.services.android.bean.ErrorResponse; @@ -69,6 +72,14 @@ public class EventReceiverServiceImpl implements EventReceiverService { if (!DeviceManagerUtil.isOperationAnalyticsEnabled()) { return Response.status(Response.Status.ACCEPTED).entity("Event is publishing has not enabled.").build(); } + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(eventBeanWrapper.getDeviceIdentifier(), + AndroidConstants.DEVICE_TYPE_ANDROID); + Device device = AndroidAPIUtils.getDeviceManagementService().getDevice(deviceIdentifier); + if (device != null && EnrolmentInfo.Status.ACTIVE != device.getEnrolmentInfo().getStatus()){ + return Response.status(Response.Status.ACCEPTED).entity("Device is not in Active state.").build(); + } else if (device == null){ + return Response.status(Response.Status.ACCEPTED).entity("Device is not enrolled yet.").build(); + } } catch (DeviceManagementException e) { log.error("Error occurred while checking Operation Analytics is Enabled.", e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); diff --git a/features/extensions-feature/org.wso2.carbon.device.mgt.adapter.feature/pom.xml b/features/extensions-feature/org.wso2.carbon.device.mgt.adapter.feature/pom.xml index 5f6a6b5ec6..b3175317d1 100644 --- a/features/extensions-feature/org.wso2.carbon.device.mgt.adapter.feature/pom.xml +++ b/features/extensions-feature/org.wso2.carbon.device.mgt.adapter.feature/pom.xml @@ -1,7 +1,7 @@ - 3.0.135 + 3.0.136-SNAPSHOT [3.0.0, 4.0.0)