From 82778f06c6b3f337906b2ec64fb1e02c395ff496 Mon Sep 17 00:00:00 2001 From: charitha Date: Mon, 20 Aug 2018 15:44:55 +0530 Subject: [PATCH] Add secure web socket proxy to route ws connections in IoTS cluster --- .../data/publisher/DataPublisherUtil.java | 71 ++++++++- .../data/publisher/DeviceDataPublisher.java | 87 +++++++---- .../config/AnalyticsConfiguration.java | 20 ++- .../service/EventsPublisherService.java | 6 +- .../service/EventsPublisherServiceImpl.java | 43 ++++-- .../pom.xml | 82 ++++++++++ .../wsproxy/exception/WSProxyException.java | 37 +++++ .../wsproxy/inbound/SubscriptionEndpoint.java | 146 ++++++++++++++++++ .../SuperTenantSubscriptionEndpoint.java | 104 +++++++++++++ .../inbound/TenantSubscriptionEndpoint.java | 103 ++++++++++++ .../wsproxy/outbound/AnalyticsClient.java | 120 ++++++++++++++ .../src/main/webapp/WEB-INF/web.xml | 46 ++++++ .../devicemgt/app/conf/config.json | 2 +- .../analytics-view.js | 4 +- .../cdmf.unit.geo-dashboard/geo-dashboard.js | 4 +- .../public/js/application_options.js | 2 +- .../cdmf.unit.geo-devices/geo-devices.js | 4 +- .../public/js/application_options.js | 2 +- components/device-mgt/pom.xml | 1 + .../src/main/resources/p2.inf | 2 - .../pom.xml | 40 ++++- .../src/main/resources/build.properties | 0 .../conf/device-analytics-config.xml | 21 ++- .../src/main/resources/p2.inf | 4 + features/device-mgt/pom.xml | 2 +- pom.xml | 33 +++- 26 files changed, 910 insertions(+), 76 deletions(-) create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/pom.xml create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/exception/WSProxyException.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/inbound/SubscriptionEndpoint.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/inbound/SuperTenantSubscriptionEndpoint.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/inbound/TenantSubscriptionEndpoint.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/outbound/AnalyticsClient.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/webapp/WEB-INF/web.xml delete mode 100644 features/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher.feature/src/main/resources/p2.inf rename features/device-mgt/{org.wso2.carbon.device.mgt.analytics.data.publisher.feature => org.wso2.carbon.device.mgt.analytics.feature}/pom.xml (74%) rename features/device-mgt/{org.wso2.carbon.device.mgt.analytics.data.publisher.feature => org.wso2.carbon.device.mgt.analytics.feature}/src/main/resources/build.properties (100%) rename features/device-mgt/{org.wso2.carbon.device.mgt.analytics.data.publisher.feature => org.wso2.carbon.device.mgt.analytics.feature}/src/main/resources/conf/device-analytics-config.xml (53%) create mode 100644 features/device-mgt/org.wso2.carbon.device.mgt.analytics.feature/src/main/resources/p2.inf diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/DataPublisherUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/DataPublisherUtil.java index a86b38ee1d2..f810ecbd7bf 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/DataPublisherUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/DataPublisherUtil.java @@ -19,13 +19,16 @@ package org.wso2.carbon.device.mgt.analytics.data.publisher; import org.w3c.dom.Document; -import org.wso2.carbon.databridge.agent.DataPublisher; +import org.wso2.carbon.databridge.agent.exception.DataEndpointConfigurationException; import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException; import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.File; +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class DataPublisherUtil { @@ -46,4 +49,70 @@ public class DataPublisherUtil { } } + public static ArrayList getEndpointGroups(String urlSet) { + ArrayList urlGroups = new ArrayList<>(); + Pattern regex = Pattern.compile("\\{.*?\\}"); + Matcher regexMatcher = regex.matcher(urlSet); + + while(regexMatcher.find()) { + urlGroups.add(regexMatcher.group().replace("{", "").replace("}", "")); + } + + if (urlGroups.size() == 0) { + urlGroups.add(urlSet.replace("{", "").replace("}", "")); + } + return urlGroups; + } + + public static String[] getEndpoints(String aURLGroup) throws DataEndpointConfigurationException { + boolean isLBURL = false; + boolean isFailOverURL = false; + if (aURLGroup.contains(",")) { + isLBURL = true; + } + + if (aURLGroup.contains("|")) { + isFailOverURL = true; + } + + if (isLBURL && isFailOverURL) { + throw new DataEndpointConfigurationException("Invalid data endpoints URL set provided : " + aURLGroup + + ", a URL group can be configured as failover OR load balancing endpoints."); + } else { + String[] urls; + if (isLBURL) { + urls = aURLGroup.split(","); + } else if (isFailOverURL) { + urls = aURLGroup.split("\\|"); + } else { + urls = new String[]{aURLGroup}; + } + return urls; + } + } + + public static int obtainHashId(String deviceId, int urlGroupsCount) { + byte[] chars = deviceId.getBytes(); + int sum = 0; + for (byte b : chars) { + sum += b; + } + return sum % urlGroupsCount; + } + + @SuppressWarnings("Duplicates") + public static String replaceProperty(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/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/DeviceDataPublisher.java b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/DeviceDataPublisher.java index 8753dc2af7b..18d5be42874 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/DeviceDataPublisher.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/DeviceDataPublisher.java @@ -18,6 +18,8 @@ */ package org.wso2.carbon.device.mgt.analytics.data.publisher; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.wso2.carbon.databridge.agent.DataPublisher; import org.wso2.carbon.databridge.agent.exception.DataEndpointAgentConfigurationException; import org.wso2.carbon.databridge.agent.exception.DataEndpointAuthenticationException; @@ -26,15 +28,25 @@ import org.wso2.carbon.databridge.agent.exception.DataEndpointException; import org.wso2.carbon.databridge.commons.exception.TransportException; import org.wso2.carbon.device.mgt.analytics.data.publisher.config.AnalyticsConfiguration; import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException; +import org.wso2.carbon.device.mgt.analytics.data.publisher.service.EventsPublisherServiceImpl; + +import java.util.HashMap; +import java.util.Map; /** * This is used to manage data publisher per tenant. */ public class DeviceDataPublisher { - private DataPublisher dataPublisher; + private static Log log = LogFactory.getLog(EventsPublisherServiceImpl.class); + + private Map dataPublishers; private static DeviceDataPublisher deviceDataPublisher; + private DeviceDataPublisher() { + dataPublishers = new HashMap<>(); + } + public static DeviceDataPublisher getInstance() { if (deviceDataPublisher == null) { synchronized (DeviceDataPublisher.class) { @@ -47,45 +59,52 @@ public class DeviceDataPublisher { } /** - * this return the data publisher for the tenant. + * This returns the data publisher for the tenant based on the analytics node id. * + * @param analyticsConfig Analytics configurations + * @param receiverURLSet Data receiver URL set as string * @return instance of data publisher - * @throws DataPublisherConfigurationException - * + * @throws DataPublisherConfigurationException on exception */ - public DataPublisher getDataPublisher() throws DataPublisherConfigurationException { - if (this.dataPublisher == null) { - synchronized (this) { - if (this.dataPublisher == null) { - AnalyticsConfiguration analyticsConfig = AnalyticsConfiguration.getInstance(); - if (!analyticsConfig.isEnable()) { - return null; - } - String analyticsServerUrlGroups = analyticsConfig.getReceiverServerUrl(); - String analyticsServerUsername = analyticsConfig.getAdminUsername(); - String analyticsServerPassword = analyticsConfig.getAdminPassword(); - try { - this.dataPublisher = new DataPublisher(analyticsServerUrlGroups, analyticsServerUsername, - analyticsServerPassword); - } catch (DataEndpointAgentConfigurationException e) { - throw new DataPublisherConfigurationException("Configuration Exception on data publisher for " + - "ReceiverGroup = " + analyticsServerUrlGroups + " for username " + analyticsServerUsername, e); - } catch (DataEndpointException e) { - throw new DataPublisherConfigurationException("Invalid ReceiverGroup = " + analyticsServerUrlGroups, e); - } catch (DataEndpointConfigurationException e) { - throw new DataPublisherConfigurationException("Invalid Data endpoint configuration.", e); - } catch (DataEndpointAuthenticationException e) { - throw new DataPublisherConfigurationException("Authentication Failed for user " + - analyticsServerUsername, e); - } catch (TransportException e) { - throw new DataPublisherConfigurationException("Error occurred while retrieving data publisher", e); - } - } else { - return this.dataPublisher; + public DataPublisher getDataPublisher(AnalyticsConfiguration analyticsConfig, String receiverURLSet) + throws DataPublisherConfigurationException { + synchronized (this) { + if (this.dataPublishers.containsKey(receiverURLSet)) { + return this.dataPublishers.get(receiverURLSet); + } else { + String analyticsServerUrlGroups = analyticsConfig.getReceiverServerUrl(); + String analyticsServerUsername = analyticsConfig.getAdminUsername(); + String analyticsServerPassword = analyticsConfig.getAdminPassword(); + + try { + DataPublisher dataPublisher = new DataPublisher(receiverURLSet, analyticsServerUsername, + analyticsServerPassword); + this.dataPublishers.put(receiverURLSet, dataPublisher); + return dataPublisher; + } catch (DataEndpointAgentConfigurationException e) { + String msg = "Configuration Exception on data publisher for " + + "ReceiverGroup = " + analyticsServerUrlGroups + " for username " + analyticsServerUsername; + log.error(msg, e); + throw new DataPublisherConfigurationException(msg, e); + } catch (DataEndpointException e) { + String msg = "Invalid ReceiverGroup = " + analyticsServerUrlGroups; + log.error(msg, e); + throw new DataPublisherConfigurationException(msg, e); + } catch (DataEndpointConfigurationException e) { + String msg = "Invalid Data endpoint configuration."; + log.error(msg, e); + throw new DataPublisherConfigurationException(msg, e); + } catch (DataEndpointAuthenticationException e) { + String msg = "Authentication Failed for user " + analyticsServerUsername; + log.error(msg, e); + throw new DataPublisherConfigurationException(msg, e); + } catch (TransportException e) { + String msg = "Error occurred while retrieving data publisher"; + log.error(msg, e); + throw new DataPublisherConfigurationException(msg, e); } } } - return this.dataPublisher; } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/config/AnalyticsConfiguration.java b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/config/AnalyticsConfiguration.java index b758d4cf1c8..67a8c36333d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/config/AnalyticsConfiguration.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/config/AnalyticsConfiguration.java @@ -39,6 +39,7 @@ import java.io.File; public class AnalyticsConfiguration { private String receiverServerUrl; + private String analyticsPublisherUrl; private String adminUsername; private String adminPassword; private boolean enable; @@ -81,13 +82,22 @@ public class AnalyticsConfiguration { @XmlElement(name = "ReceiverServerUrl", required = true) public String getReceiverServerUrl() { - return receiverServerUrl; + return DataPublisherUtil.replaceProperty(receiverServerUrl); } public void setReceiverServerUrl(String receiverServerUrl) { this.receiverServerUrl = receiverServerUrl; } + @XmlElement(name = "AnalyticsPublisherUrl", required = true) + public String getAnalyticsPublisherUrl() { + return DataPublisherUtil.replaceProperty(analyticsPublisherUrl); + } + + public void setAnalyticsPublisherUrl(String analyticsPublisherUrl) { + this.analyticsPublisherUrl = analyticsPublisherUrl; + } + @XmlElement(name = "Enabled", required = true) public boolean isEnable() { return enable; @@ -102,8 +112,14 @@ public class AnalyticsConfiguration { } public static void init(String analyticsConfigPath) throws DataPublisherConfigurationException { + File authConfig = new File(analyticsConfigPath); + if (!authConfig.exists()) { + log.warn(DEVICE_ANALYTICS_CONFIG_PATH + " does not exist. Disabling AnalyticsConfiguration."); + config = new AnalyticsConfiguration(); + config.setEnable(false); + return; + } try { - File authConfig = new File(analyticsConfigPath); Document doc = DataPublisherUtil.convertToDocument(authConfig); /* Un-marshaling device analytics configuration */ diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/service/EventsPublisherService.java b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/service/EventsPublisherService.java index 7be1ac574b8..f75496d0e2f 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/service/EventsPublisherService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/service/EventsPublisherService.java @@ -21,7 +21,7 @@ package org.wso2.carbon.device.mgt.analytics.data.publisher.service; import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException; /** - * This service can be used to publish and retreive data from the Analytics Server. + * This service can be used to publish and retrieve data from the Analytics Server. */ public interface EventsPublisherService { @@ -32,8 +32,8 @@ public interface EventsPublisherService { * @param metaDataArray - meta data that needs to pushed * @param correlationDataArray - correlation data that needs to be pushed * @param payloadDataArray - payload data that needs to be pushed - * @return - * @throws DataPublisherConfigurationException + * @return if success returns true + * @throws DataPublisherConfigurationException on exception */ boolean publishEvent(String streamName, String version, Object[] metaDataArray, Object[] correlationDataArray, Object[] payloadDataArray) throws DataPublisherConfigurationException; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/service/EventsPublisherServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/service/EventsPublisherServiceImpl.java index 4c039221c81..6b7b81aa36b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/service/EventsPublisherServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/src/main/java/org/wso2/carbon/device/mgt/analytics/data/publisher/service/EventsPublisherServiceImpl.java @@ -24,44 +24,67 @@ import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.databridge.agent.DataPublisher; import org.wso2.carbon.databridge.commons.utils.DataBridgeCommonsUtils; +import org.wso2.carbon.device.mgt.analytics.data.publisher.DataPublisherUtil; import org.wso2.carbon.device.mgt.analytics.data.publisher.DeviceDataPublisher; +import org.wso2.carbon.device.mgt.analytics.data.publisher.config.AnalyticsConfiguration; import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException; import org.wso2.carbon.utils.multitenancy.MultitenantConstants; +import java.util.ArrayList; + /** * This is the implementation of Osgi Service which can be used to publish and retireved * event/records. */ public class EventsPublisherServiceImpl implements EventsPublisherService { + private static Log log = LogFactory.getLog(EventsPublisherServiceImpl.class); /** * @param streamName is the name of the stream that the data needs to pushed * @param version is the version of the stream - * @param metaDataArray - meta data that needs to pushed - * @param correlationDataArray - correlation data that needs to be pushed - * @param payloadDataArray - payload data that needs to be pushed + * @param metaDataArray meta data that needs to pushed + * @param correlationDataArray correlation data that needs to be pushed + * @param payloadDataArray payload data that needs to be pushed * @return if success returns true - * @throws DataPublisherConfigurationException + * @throws DataPublisherConfigurationException on exception */ @Override public boolean publishEvent(String streamName, String version, Object[] metaDataArray, Object[] correlationDataArray, Object[] payloadDataArray) throws DataPublisherConfigurationException { + AnalyticsConfiguration analyticsConfig = AnalyticsConfiguration.getInstance(); + if (!analyticsConfig.isEnable()) { + log.warn("Analytics data publishing not enabled."); + return false; + } + + if (metaDataArray == null || metaDataArray.length == 0) { + String msg = "meta data[0] must have the device Id field"; + log.error(msg); + throw new DataPublisherConfigurationException(msg); + } + + ArrayList receiverURLGroups = DataPublisherUtil.getEndpointGroups(analyticsConfig.getReceiverServerUrl()); + int hashId = DataPublisherUtil.obtainHashId(metaDataArray[0].toString(), receiverURLGroups.size()); + if (receiverURLGroups.size() <= hashId) { + String msg = "Invalid receiver url group size. Expected to be higher than: " + hashId + " Actual: " + + receiverURLGroups.size(); + log.error(msg); + throw new DataPublisherConfigurationException(msg); + } + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { - if (metaDataArray == null || metaDataArray.length == 0) { - throw new DataPublisherConfigurationException("meta data[0] should have the device Id field"); - } else { - metaDataArray[0] = tenantDomain + "@" + metaDataArray[0]; - } + metaDataArray[0] = tenantDomain + "@" + metaDataArray[0]; } PrivilegedCarbonContext.startTenantFlow(); PrivilegedCarbonContext.getThreadLocalCarbonContext() .setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, true); try { - DataPublisher dataPublisher = DeviceDataPublisher.getInstance().getDataPublisher(); + DataPublisher dataPublisher = DeviceDataPublisher.getInstance() + .getDataPublisher(analyticsConfig, receiverURLGroups.get(hashId)); if (dataPublisher != null) { String streamId = DataBridgeCommonsUtils.generateStreamId(streamName, version); return dataPublisher.tryPublish(streamId, System.currentTimeMillis(), metaDataArray, diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/pom.xml b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/pom.xml new file mode 100644 index 00000000000..25f5f70a11b --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/pom.xml @@ -0,0 +1,82 @@ + + + + + device-mgt + org.wso2.carbon.devicemgt + 3.1.34-SNAPSHOT + + 4.0.0 + + org.wso2.carbon.device.mgt.analytics.wsproxy + war + WSO2 - Webapp for Web Socket Proxy + http://wso2.org + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.analytics.data.publisher + provided + + + javax.ws.rs + javax.ws.rs-api + + + org.apache.cxf + cxf-rt-frontend-jaxrs + + + + + secured-websocket-proxy + + + org.jacoco + jacoco-maven-plugin + + ${basedir}/target/coverage-reports/jacoco-unit.exec + + + + jacoco-initialize + + prepare-agent + + + + jacoco-site + test + + report + + + ${basedir}/target/coverage-reports/jacoco-unit.exec + ${basedir}/target/coverage-reports/site + + + + + + + + \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/exception/WSProxyException.java b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/exception/WSProxyException.java new file mode 100644 index 00000000000..7937ada3710 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/exception/WSProxyException.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018, 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.analytics.wsproxy.exception; + +/** + * Indicates an error with deployment tinkerer + * + * @since 1.0.0 + */ +public class WSProxyException extends Exception { + + /** + * Constructs a new exception with the message provided and the cause. + * + * @param message the detailed message of the exception + * @param cause the cause of the exception + */ + public WSProxyException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/inbound/SubscriptionEndpoint.java b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/inbound/SubscriptionEndpoint.java new file mode 100644 index 00000000000..14db789fa9d --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/inbound/SubscriptionEndpoint.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2018, 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.analytics.wsproxy.inbound; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.databridge.agent.exception.DataEndpointConfigurationException; +import org.wso2.carbon.device.mgt.analytics.data.publisher.DataPublisherUtil; +import org.wso2.carbon.device.mgt.analytics.data.publisher.config.AnalyticsConfiguration; +import org.wso2.carbon.device.mgt.analytics.wsproxy.exception.WSProxyException; +import org.wso2.carbon.device.mgt.analytics.wsproxy.outbound.AnalyticsClient; + +import javax.websocket.CloseReason; +import javax.websocket.Session; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Interface for subscription and un-subscription for web socket + */ + +public class SubscriptionEndpoint { + + private static final Log log = LogFactory.getLog(SubscriptionEndpoint.class); + private Map> analyticsClientsMap = new HashMap<>(); + + /** + * Web socket onOpen - When client sends a message + * + * @param session - Users registered session. + */ + public void onOpen(Session session) { + if (log.isDebugEnabled()) { + log.debug("WebSocket opened, for Session id: " + session.getId()); + } + + AnalyticsConfiguration analyticsConfig = AnalyticsConfiguration.getInstance(); + ArrayList publisherGroups = + DataPublisherUtil.getEndpointGroups(analyticsConfig.getAnalyticsPublisherUrl()); + List analyticsClients = new ArrayList<>(); + for (String publisherURLGroup : publisherGroups) { + try { + String[] endpoints = DataPublisherUtil.getEndpoints(publisherURLGroup); + for (String endpoint : endpoints) { + try { + endpoint = endpoint.trim(); + if (!endpoint.endsWith("/")) { + endpoint += "/"; + } + endpoint += session.getRequestURI().getSchemeSpecificPart().replace("secured-websocket-proxy",""); + AnalyticsClient analyticsClient = new AnalyticsClient(session); + analyticsClient.connectClient(new URI(endpoint)); + analyticsClients.add(analyticsClient); + } catch (URISyntaxException e) { + log.error("Unable to create URL from: " + endpoint, e); + } catch (WSProxyException e) { + log.error("Unable to create WS client for: " + endpoint, e); + } + } + } catch (DataEndpointConfigurationException e) { + log.error("Unable to obtain endpoints from receiverURLGroup: " + publisherURLGroup, e); + } + } + if (log.isDebugEnabled()) { + log.debug("Configured " + analyticsClients.size() + " analytics clients for Session id: " + + session.getId()); + } + analyticsClientsMap.put(session.getId(), analyticsClients); + } + + /** + * Web socket onClose - Remove the registered sessions + * + * @param session - Users registered session. + * @param reason - Status code for web-socket close. + * @param streamName - StreamName extracted from the ws url. + * @param version - Version extracted from the ws url. + * @param tenantDomain - Domain of the tenant. + */ + public void onClose(Session session, CloseReason reason, String streamName, String version, String tenantDomain) { + if (log.isDebugEnabled()) { + log.debug("Closing a WebSocket due to " + reason.getReasonPhrase() + ", for session ID:" + + session.getId() + ", for request URI - " + session.getRequestURI()); + } + for (AnalyticsClient analyticsClient : analyticsClientsMap.get(session.getId())) { + if (analyticsClient != null) { + try { + analyticsClient.closeConnection(reason); + } catch (WSProxyException e) { + log.error("Error occurred while closing ws connection due to " + reason.getReasonPhrase() + + ", for session ID:" + session.getId() + ", for request URI - " + session.getRequestURI(), e); + } + } + } + analyticsClientsMap.remove(session.getId()); + } + + /** + * Web socket onMessage - When client sens a message + * + * @param session - Users registered session. + * @param message - Status code for web-socket close. + */ + public void onMessage(Session session, String message) { + for (AnalyticsClient analyticsClient : analyticsClientsMap.get(session.getId())) { + if (analyticsClient != null) { + analyticsClient.sendMessage(message); + } + } + } + + /** + * Web socket onError + * + * @param session - Users registered session. + * @param throwable - Status code for web-socket close. + * @param streamName - StreamName extracted from the ws url. + * @param version - Version extracted from the ws url. + * @param tenantDomain - Domain of the tenant. + */ + public void onError(Session session, Throwable throwable, String streamName, String version, String tenantDomain) { + log.error("Error occurred in session ID: " + session.getId() + ", for request URI - " + + session.getRequestURI() + ", " + throwable.getMessage(), throwable); + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/inbound/SuperTenantSubscriptionEndpoint.java b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/inbound/SuperTenantSubscriptionEndpoint.java new file mode 100644 index 00000000000..0e4bc3684d9 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/inbound/SuperTenantSubscriptionEndpoint.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018, 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.analytics.wsproxy.inbound; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.base.MultitenantConstants; + +import javax.websocket.CloseReason; +import javax.websocket.EndpointConfig; +import javax.websocket.OnClose; +import javax.websocket.OnError; +import javax.websocket.OnMessage; +import javax.websocket.OnOpen; +import javax.websocket.Session; +import javax.websocket.server.PathParam; +import javax.websocket.server.ServerEndpoint; + +/** + * Connect to web socket with Super tenant + */ + +@ServerEndpoint(value = "/{destination}/{streamname}/{version}") +public class SuperTenantSubscriptionEndpoint extends SubscriptionEndpoint { + + private static final Log log = LogFactory.getLog(SuperTenantSubscriptionEndpoint.class); + + /** + * Web socket onOpen - When client sends a message + * + * @param session - Users registered session. + * @param streamName - StreamName extracted from the ws url. + * @param version - Version extracted from the ws url. + */ + @OnOpen + public void onOpen(Session session, EndpointConfig config, @PathParam("streamname") String streamName, + @PathParam("version") String version) { + if (log.isDebugEnabled()) { + log.debug("WebSocket opened, for Session id: " + session.getId() + ", for the Stream:" + streamName); + } + super.onOpen(session); + } + + /** + * Web socket onMessage - When client sens a message + * + * @param session - Users registered session. + * @param message - Status code for web-socket close. + * @param streamName - StreamName extracted from the ws url. + */ + @OnMessage + public void onMessage(Session session, String message, @PathParam("streamname") String streamName) { + if (log.isDebugEnabled()) { + log.debug("Received message from client. Message: " + message + ", " + + "for Session id: " + session.getId() + ", for the Stream:" + streamName); + } + super.onMessage(session, message); + } + + /** + * Web socket onClose - Remove the registered sessions + * + * @param session - Users registered session. + * @param reason - Status code for web-socket close. + * @param streamName - StreamName extracted from the ws url. + * @param version - Version extracted from the ws url. + */ + @OnClose + public void onClose(Session session, CloseReason reason, @PathParam("streamname") String streamName, + @PathParam("version") String version) { + super.onClose(session, reason, streamName, version, MultitenantConstants.SUPER_TENANT_NAME); + } + + /** + * Web socket onError - Remove the registered sessions + * + * @param session - Users registered session. + * @param throwable - Status code for web-socket close. + * @param streamName - StreamName extracted from the ws url. + * @param version - Version extracted from the ws url. + */ + @OnError + public void onError(Session session, Throwable throwable, @PathParam("streamname") String streamName, + @PathParam("version") String version) { + super.onError(session, throwable, streamName, version, MultitenantConstants.SUPER_TENANT_NAME); + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/inbound/TenantSubscriptionEndpoint.java b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/inbound/TenantSubscriptionEndpoint.java new file mode 100644 index 00000000000..02e55cfed6c --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/inbound/TenantSubscriptionEndpoint.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2018, 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.analytics.wsproxy.inbound; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.websocket.CloseReason; +import javax.websocket.EndpointConfig; +import javax.websocket.OnClose; +import javax.websocket.OnError; +import javax.websocket.OnMessage; +import javax.websocket.OnOpen; +import javax.websocket.Session; +import javax.websocket.server.PathParam; +import javax.websocket.server.ServerEndpoint; + +/** + * Connect to web socket with a tenant + */ + +@ServerEndpoint(value = "/{destination}/t/{tdomain}/{streamname}/{version}") +public class TenantSubscriptionEndpoint extends SubscriptionEndpoint { + + private static final Log log = LogFactory.getLog(TenantSubscriptionEndpoint.class); + + /** + * Web socket onOpen - When client sends a message + * + * @param session - Users registered session. + * @param streamName - StreamName extracted from the ws url. + * @param version - Version extracted from the ws url. + * @param tdomain - Tenant domain extracted from ws url. + */ + @OnOpen + public void onOpen(Session session, EndpointConfig config, @PathParam("streamname") String streamName, + @PathParam("version") String version, @PathParam("tdomain") String tdomain) { + if (log.isDebugEnabled()) { + log.debug("WebSocket opened, for Session id: " + session.getId() + ", for the Stream:" + streamName); + } + super.onOpen(session); + } + + /** + * Web socket onMessage - When client sens a message + * + * @param session - Users registered session. + * @param message - Status code for web-socket close. + * @param streamName - StreamName extracted from the ws url. + */ + @OnMessage + public void onMessage(Session session, String message, @PathParam("streamname") String streamName, @PathParam("tdomain") String tdomain) { + if (log.isDebugEnabled()) { + log.debug("Received message from client. Message: " + message + ", for Session id: " + + session.getId() + ", for tenant domain" + tdomain + ", for the Adaptor:" + streamName); + } + super.onMessage(session, message); + } + + /** + * Web socket onClose - Remove the registered sessions + * + * @param session - Users registered session. + * @param reason - Status code for web-socket close. + * @param streamName - StreamName extracted from the ws url. + * @param version - Version extracted from the ws url. + */ + @OnClose + public void onClose(Session session, CloseReason reason, @PathParam("streamname") String streamName, + @PathParam("version") String version, @PathParam("tdomain") String tdomain) { + super.onClose(session, reason, streamName, version, tdomain); + } + + /** + * Web socket onError - Remove the registered sessions + * + * @param session - Users registered session. + * @param throwable - Status code for web-socket close. + * @param streamName - StreamName extracted from the ws url. + * @param version - Version extracted from the ws url. + */ + @OnError + public void onError(Session session, Throwable throwable, @PathParam("streamname") String streamName, + @PathParam("version") String version, @PathParam("tdomain") String tdomain) { + super.onError(session, throwable, streamName, version, tdomain); + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/outbound/AnalyticsClient.java b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/outbound/AnalyticsClient.java new file mode 100644 index 00000000000..7bfd480288e --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/java/org/wso2/carbon/device/mgt/analytics/wsproxy/outbound/AnalyticsClient.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2018, 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.analytics.wsproxy.outbound; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.analytics.wsproxy.exception.WSProxyException; + +import javax.websocket.CloseReason; +import javax.websocket.ContainerProvider; +import javax.websocket.DeploymentException; +import javax.websocket.OnClose; +import javax.websocket.OnMessage; +import javax.websocket.Session; +import javax.websocket.WebSocketContainer; +import java.io.IOException; +import java.net.URI; + +/** + * This class holds web socket client implementation + * + * @since 1.0.0 + */ +@javax.websocket.ClientEndpoint +public class AnalyticsClient { + + private static final Log log = LogFactory.getLog(AnalyticsClient.class); + + private WebSocketContainer container; + private Session analyticsSession = null; + private Session clientSession; + + /** + * Create {@link AnalyticsClient} instance. + */ + public AnalyticsClient(Session clientSession) { + container = ContainerProvider.getWebSocketContainer(); + this.clientSession = clientSession; + } + + /** + * Create web socket client connection using {@link WebSocketContainer}. + */ + public void connectClient(URI endpointURI) throws WSProxyException { + try { + analyticsSession = container.connectToServer(this, endpointURI); + } catch (DeploymentException | IOException e) { + String msg = "Error occurred while connecting to remote endpoint " + endpointURI.toString(); + log.error(msg, e); + throw new WSProxyException(msg, e); + } + } + + /** + * Callback hook for Connection close events. + * + * @param userSession the analyticsSession which is getting closed. + * @param reason the reason for connection close + */ + @OnClose + public void onClose(Session userSession, CloseReason reason) { + if (log.isDebugEnabled()) { + log.debug("Closing web socket session: '" + userSession.getId() + "'. Code: " + + reason.getCloseCode().toString() + " Reason: " + reason.getReasonPhrase()); + } + this.analyticsSession = null; + } + + /** + * Callback hook for Message Events. + * + *

This method will be invoked when a client send a message. + * + * @param message The text message. + */ + @OnMessage + public void onMessage(String message) { + this.clientSession.getAsyncRemote().sendText(message); + } + + /** + * Send a message. + * + * @param message the message which is going to send. + */ + public void sendMessage(String message) { + this.analyticsSession.getAsyncRemote().sendText(message); + } + + /** + * Close current connection. + */ + public void closeConnection(CloseReason closeReason) throws WSProxyException { + if (this.analyticsSession != null) { + try { + this.analyticsSession.close(closeReason); + } catch (IOException e) { + String msg = "Error on closing WS connection."; + log.error(msg, e); + throw new WSProxyException(msg, e); + } + } + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/webapp/WEB-INF/web.xml b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..bf625c9256d --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.wsproxy/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,46 @@ + + + + + Output WebSocket Proxy + + + ContentTypeBasedCachePreventionFilter + org.wso2.carbon.ui.filters.cache.ContentTypeBasedCachePreventionFilter + + patterns + text/html" ,application/json" ,text/plain + + + filterAction + enforce + + + httpHeaders + Cache-Control: no-store, no-cache, must-revalidate, private + + + + + ContentTypeBasedCachePreventionFilter + /* + + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json index 6a59e99d0fa..63171a15953 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json @@ -5,7 +5,7 @@ "managerHTTPSURL": "https://%iot.manager.host%:%iot.manager.https.port%", "httpsURL": "https://%iot.gateway.host%:%iot.gateway.https.port%", "httpURL": "http://%iot.gateway.host%:%iot.gateway.http.port%", - "wssURL": "https://%iot.analytics.host%:%iot.analytics.https.port%", + "wssURL": "https://%iot.core.host%:%iot.core.https.port%", "remoteSessionWSURL": "https://%iot.core.host%:%iot.core.https.port%", "portalURL": "https://%iot.analytics.host%:%iot.analytics.https.port%", "dashboardServerURL": "%https.ip%", diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.default.device.type.realtime.analytics-view/analytics-view.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.default.device.type.realtime.analytics-view/analytics-view.js index cfefa850e02..a13b87502f8 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.default.device.type.realtime.analytics-view/analytics-view.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.default.device.type.realtime.analytics-view/analytics-view.js @@ -43,14 +43,14 @@ function onRequest(context) { if (tokenPair) { token = tokenPair.accessToken; } - websocketEndpoint = websocketEndpoint + "/secured-websocket/iot.per.device.stream." + tenantDomain + "." + device.type + "/1.0.0?" + websocketEndpoint = websocketEndpoint + "/secured-websocket-proxy/secured-websocket/iot.per.device.stream." + tenantDomain + "." + device.type + "/1.0.0?" + "deviceId=" + device.deviceIdentifier + "&deviceType=" + device.type + "&websocketToken=" + token; } else { var tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username + "@" + tenantDomain,"default", {}); if (tokenPair) { token = tokenPair.accessToken; } - websocketEndpoint = websocketEndpoint + "/secured-websocket" + "/t/" + tenantDomain + "/iot.per.device.stream." + tenantDomain + websocketEndpoint = websocketEndpoint + "/secured-websocket-proxy/secured-websocket/t/" + tenantDomain + "/iot.per.device.stream." + tenantDomain + "." + device.type + "/1.0.0?" + "deviceId=" + device.deviceIdentifier + "&deviceType=" + device.type + "&websocketToken=" + token; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-dashboard/geo-dashboard.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-dashboard/geo-dashboard.js index de15fc40e46..b44eb2be496 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-dashboard/geo-dashboard.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-dashboard/geo-dashboard.js @@ -37,14 +37,14 @@ function onRequest(context) { tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username,"default", {}); if (tokenPair) { token = tokenPair.accessToken; - wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket/"; + wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket-proxy/secured-websocket/"; } } else { tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username + "@" + context.user.domain, "default", {}); if (tokenPair) { token = tokenPair.accessToken; - wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket/t/" + + wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket-proxy/secured-websocket/t/" + context.user.domain + "/"; } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-dashboard/public/js/application_options.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-dashboard/public/js/application_options.js index cd1915e67a9..8b18b96158b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-dashboard/public/js/application_options.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-dashboard/public/js/application_options.js @@ -32,7 +32,7 @@ var ApplicationOptions = { CEP_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'iot.per.device.stream.geo.FusedSpatialEvent', CEP_ON_ALERT_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'org.wso2.geo.AlertsNotifications', CEP_Traffic_STREAM_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'DefaultWebsocketOutputAdaptorOnTrafficStream', - CEP_WEB_SOCKET_OUTPUT_ADAPTOR_WEBAPP_NAME: 'secured-websocket', + CEP_WEB_SOCKET_OUTPUT_ADAPTOR_WEBAPP_NAME: 'secured-websocket-proxy', TENANT_INDEX: 't', COLON : ':', PATH_SEPARATOR : '/', diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/geo-devices.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/geo-devices.js index eddb14ea91b..9db76cedadf 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/geo-devices.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/geo-devices.js @@ -38,13 +38,13 @@ function onRequest(context) { tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username,"default", {}); if (tokenPair) { token = tokenPair.accessToken; - wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket/"; + wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket-proxy/secured-websocket/"; } } else { tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username + "@" + context.user.domain,"default", {}); if (tokenPair) { token = tokenPair.accessToken; - wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket/t/"+context.user.domain+"/"; + wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket-proxy/secured-websocket/t/"+context.user.domain+"/"; } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/application_options.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/application_options.js index 2ca6536b452..bba55e27002 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/application_options.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/application_options.js @@ -32,7 +32,7 @@ var ApplicationOptions = { CEP_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'iot.per.device.stream.geo.FusedSpatialEvent', CEP_ON_ALERT_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'org.wso2.geo.AlertsNotifications', CEP_Traffic_STREAM_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'DefaultWebsocketOutputAdaptorOnTrafficStream', - CEP_WEB_SOCKET_OUTPUT_ADAPTOR_WEBAPP_NAME: 'secured-websocket', + CEP_WEB_SOCKET_OUTPUT_ADAPTOR_WEBAPP_NAME: 'secured-websocket-proxy', TENANT_INDEX: 't', COLON : ':', PATH_SEPARATOR : '/', diff --git a/components/device-mgt/pom.xml b/components/device-mgt/pom.xml index 7ec456690fa..6573d0203ff 100644 --- a/components/device-mgt/pom.xml +++ b/components/device-mgt/pom.xml @@ -41,6 +41,7 @@ org.wso2.carbon.device.mgt.v09.api org.wso2.carbon.device.mgt.analytics.data.publisher org.wso2.carbon.device.mgt.url.printer + org.wso2.carbon.device.mgt.analytics.wsproxy diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher.feature/src/main/resources/p2.inf b/features/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher.feature/src/main/resources/p2.inf deleted file mode 100644 index 70f1acd33f8..00000000000 --- a/features/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher.feature/src/main/resources/p2.inf +++ /dev/null @@ -1,2 +0,0 @@ -instructions.configure = \ -org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.analytics.data.publisher_${feature.version}/conf/device-analytics-config.xml,target:${installFolder}/../../conf/etc/device-analytics-config.xml,overwrite:true);\ \ No newline at end of file diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher.feature/pom.xml b/features/device-mgt/org.wso2.carbon.device.mgt.analytics.feature/pom.xml similarity index 74% rename from features/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher.feature/pom.xml rename to features/device-mgt/org.wso2.carbon.device.mgt.analytics.feature/pom.xml index f59d768e6c4..989feb61942 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher.feature/pom.xml +++ b/features/device-mgt/org.wso2.carbon.device.mgt.analytics.feature/pom.xml @@ -1,6 +1,6 @@ + true - false - tcp://localhost:7612 + tcp://${iot.analytics.host}:${iot.analytics.thrift.port} + + wss://${iot.analytics.host}:${iot.analytics.https.port} admin admin diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.analytics.feature/src/main/resources/p2.inf b/features/device-mgt/org.wso2.carbon.device.mgt.analytics.feature/src/main/resources/p2.inf new file mode 100644 index 00000000000..a0a1b3d0058 --- /dev/null +++ b/features/device-mgt/org.wso2.carbon.device.mgt.analytics.feature/src/main/resources/p2.inf @@ -0,0 +1,4 @@ +instructions.configure = \ +org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.analytics_${feature.version}/conf/device-analytics-config.xml,target:${installFolder}/../../conf/etc/device-analytics-config.xml,overwrite:true);\ +org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/webapps/);\ +org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.analytics_${feature.version}/webapps/secured-websocket-proxy.war,target:${installFolder}/../../deployment/server/webapps/secured-websocket-proxy.war,overwrite:true);\ \ No newline at end of file diff --git a/features/device-mgt/pom.xml b/features/device-mgt/pom.xml index fe70581b8a9..e380d37cc4f 100644 --- a/features/device-mgt/pom.xml +++ b/features/device-mgt/pom.xml @@ -39,7 +39,7 @@ org.wso2.carbon.device.mgt.api.feature org.wso2.carbon.device.mgt.feature org.wso2.carbon.device.mgt.extensions.feature - org.wso2.carbon.device.mgt.analytics.data.publisher.feature + org.wso2.carbon.device.mgt.analytics.feature diff --git a/pom.xml b/pom.xml index fea478ca60e..836b59f8260 100644 --- a/pom.xml +++ b/pom.xml @@ -241,6 +241,11 @@ org.wso2.carbon.device.mgt.analytics.data.publisher ${carbon.device.mgt.version} + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.analytics.wsproxy + ${carbon.device.mgt.version} + org.wso2.carbon.devicemgt org.wso2.carbon.device.mgt.server.feature @@ -1307,11 +1312,11 @@ provided - + mysql mysql-connector-java - ${tomcat.version} + ${mysql.connector.version} test @@ -1647,6 +1652,18 @@ test ${slf4j.nop.version} + + + javax.websocket + javax.websocket-api + ${javax.websocket.version} + + + org.apache.tomcat + tomcat-websocket-api + ${tomcat.websocket.version} + provided + @@ -1909,8 +1926,8 @@ 1.2.140.wso2v3 - 7.0.59.wso2v1 - 7.0.59.wso2v1 + 7.0.85.wso2v1 + 7.0.85.wso2v1 7.0.34.wso2v2 @@ -2018,8 +2035,8 @@ (3.2.0, 3.3.0] 1.8 - - 5.1.34 + + 5.1.34 3.0.4.wso2v1 @@ -2087,6 +2104,10 @@ 1.4.0.wso2v1 1.7.25 + + 7.0.85 + 1.0 + 1.13.1