diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/pom.xml b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/pom.xml
new file mode 100644
index 0000000000..449706e39c
--- /dev/null
+++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/pom.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+ iot-base-plugin
+ org.wso2.carbon.devicemgt-plugins
+ 2.1.1-SNAPSHOT
+ ../pom.xml
+
+
+ 4.0.0
+ org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint
+ war
+ WSO2 - Webapp for UI Output Event Adapter
+ http://wso2.org
+
+
+
+ junit
+ junit
+ test
+
+
+ org.apache.tomcat
+ tomcat-websocket-api
+
+
+ org.wso2.carbon.devicemgt-plugins
+ org.wso2.carbon.device.mgt.iot.output.adapter.ui
+ provided
+
+
+ javax.ws.rs
+ javax.ws.rs-api
+
+
+ org.apache.cxf
+ cxf-rt-frontend-jaxrs
+
+
+ org.apache.httpcomponents.wso2
+ httpcore
+ provided
+
+
+ org.wso2.orbit.org.apache.httpcomponents
+ httpclient
+ provided
+
+
+ org.wso2.carbon.identity
+ org.wso2.carbon.identity.oauth.stub
+ provided
+
+
+
+
+ secured-outputui
+
+
diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/SubscriptionEndpoint.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/SubscriptionEndpoint.java
new file mode 100644
index 0000000000..9439b422cd
--- /dev/null
+++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/SubscriptionEndpoint.java
@@ -0,0 +1,73 @@
+/*
+ *
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import util.ServiceHolder;
+
+import javax.websocket.CloseReason;
+import javax.websocket.Session;
+
+/**
+ * Interface for subscription and un-subscription for web socket
+ */
+
+public class SubscriptionEndpoint {
+
+ private static final Log log = LogFactory.getLog(SubscriptionEndpoint.class);
+
+ public SubscriptionEndpoint() {
+
+ }
+
+ /**
+ * 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.
+ */
+ public void onClose(Session session, CloseReason reason, String streamName, String version) {
+ if (log.isDebugEnabled()) {
+ log.debug("Closing a WebSocket due to " + reason.getReasonPhrase() + ", for session ID:" + session.getId
+ () +
+ ", for request URI - " + session.getRequestURI());
+ }
+ ServiceHolder.getInstance().getUiOutputCallbackControllerService().unsubscribeWebsocket(streamName, version,
+ session);
+ }
+
+ /**
+ * 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.
+ */
+ public void onError(Session session, Throwable throwable, String streamName, String version) {
+ log.error(
+ "Error occurred in session ID: " + session.getId() + ", for request URI - " + session.getRequestURI() +
+ ", " + throwable.getMessage(), throwable);
+ ServiceHolder.getInstance().getUiOutputCallbackControllerService().unsubscribeWebsocket(streamName, version,
+ session);
+ }
+}
diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/SuperTenantSubscriptionEndpoint.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/SuperTenantSubscriptionEndpoint.java
new file mode 100644
index 0000000000..546473cd3c
--- /dev/null
+++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/SuperTenantSubscriptionEndpoint.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+import oauth.OAuthTokenValdiator;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import util.ServiceHolder;
+import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
+import util.AuthenticationInfo;
+
+import javax.websocket.CloseReason;
+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;
+import java.io.IOException;
+
+/**
+ * Connect to web socket with Super tenant
+ */
+
+@ServerEndpoint(value = "/{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, @PathParam("streamname") String streamName,
+ @PathParam("version") String version) {
+ if (log.isDebugEnabled()) {
+ log.debug("WebSocket opened, for Session id: " + session.getId() + ", for the Stream:" + streamName);
+ }
+ AuthenticationInfo authenticationInfo = OAuthTokenValdiator.getInstance().validateToken(session);
+ //TODO Authorization
+ if (authenticationInfo != null && authenticationInfo.isAuthenticated()) {
+ try {
+ PrivilegedCarbonContext.startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(MultitenantConstants.SUPER_TENANT_ID);
+ ServiceHolder.getInstance().getUiOutputCallbackControllerService().subscribeWebsocket(streamName,
+ version, session);
+ } finally {
+ PrivilegedCarbonContext.endTenantFlow();
+ }
+ } else {
+ try {
+ session.close(new CloseReason(CloseReason.CloseCodes.CANNOT_ACCEPT, "Unauthorized Access"));
+ } catch (IOException e) {
+ log.error("Failed to disconnect the unauthorized client.");
+ }
+ }
+ }
+
+ /**
+ * 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 and dropped message from client. Message: " + message + ", " +
+ "for Session id: " + session.getId() + ", for the Stream:" + streamName);
+ }
+ }
+
+ /**
+ * 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) {
+ try {
+ PrivilegedCarbonContext.startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(MultitenantConstants.SUPER_TENANT_ID);
+ super.onClose(session, reason, streamName, version);
+ } finally {
+ PrivilegedCarbonContext.endTenantFlow();
+ }
+ }
+
+ /**
+ * 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) {
+ try {
+ PrivilegedCarbonContext.startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(MultitenantConstants.SUPER_TENANT_ID);
+ super.onError(session, throwable, streamName, version);
+ } finally {
+ PrivilegedCarbonContext.endTenantFlow();
+ }
+ }
+
+}
diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/TenantSubscriptionEndpoint.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/TenantSubscriptionEndpoint.java
new file mode 100644
index 0000000000..837e75f00d
--- /dev/null
+++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/TenantSubscriptionEndpoint.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+import oauth.OAuthTokenValdiator;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import util.ServiceHolder;
+import util.AuthenticationInfo;
+
+import javax.websocket.CloseReason;
+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;
+import java.io.IOException;
+
+/**
+ * Connect to web socket with a tenant
+ */
+
+@ServerEndpoint(value = "/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, @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);
+ }
+ AuthenticationInfo authenticationInfo = OAuthTokenValdiator.getInstance().validateToken(session);
+ //TODO Authorization
+ if (authenticationInfo != null && authenticationInfo.isAuthenticated()) {
+ try {
+ PrivilegedCarbonContext.startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tdomain, true);
+ ServiceHolder.getInstance().getUiOutputCallbackControllerService().subscribeWebsocket(streamName,
+ version, session);
+ } finally {
+ PrivilegedCarbonContext.endTenantFlow();
+ }
+ } else {
+ try {
+ session.close(new CloseReason(CloseReason.CloseCodes.CANNOT_ACCEPT, "Unauthorized Access"));
+ } catch (IOException e) {
+ log.error("Failed to disconnect the unauthorized client.");
+ }
+ }
+ }
+
+ /**
+ * 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 and dropped message from client. Message: " + message+", for Session id: "+session.getId()+", for tenant domain"+tdomain+", for the Adaptor:"+streamName);
+ }
+ }
+
+ /**
+ * 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) {
+
+ try {
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tdomain,true);
+ super.onClose(session, reason, streamName, version);
+ } finally {
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().endTenantFlow();
+ }
+ }
+
+ /**
+ * 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) {
+
+ try {
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tdomain, true);
+ super.onError(session, throwable, streamName, version);
+ } finally {
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().endTenantFlow();
+ }
+ }
+}
diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/OAuthTokenValdiator.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/OAuthTokenValdiator.java
new file mode 100644
index 0000000000..e33bb39faf
--- /dev/null
+++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/OAuthTokenValdiator.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2016, 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 oauth;
+
+import org.apache.axis2.context.ServiceContext;
+import org.apache.axis2.transport.http.HTTPConstants;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.pool.impl.GenericObjectPool;
+import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
+import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO;
+import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO_OAuth2AccessToken;
+import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationResponseDTO;
+import org.wso2.carbon.user.api.UserStoreException;
+import org.wso2.carbon.utils.CarbonUtils;
+import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
+import util.AuthenticationInfo;
+
+import javax.websocket.Session;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.rmi.RemoteException;
+import java.util.Properties;
+
+/**
+ * This acts as a contract point for OAuth token validation.
+ */
+public class OAuthTokenValdiator {
+
+ private static String cookie;
+ private GenericObjectPool stubs;
+ private static Log log = LogFactory.getLog(OAuthTokenValdiator.class);
+ private static final String WEBSOCKET_CONFIG_LOCATION =
+ CarbonUtils.getEtcCarbonConfigDirPath() + File.separator + "websocket-validation.properties";
+ private static final String QUERY_STRING_SEPERATOR = "&";
+ private static final String QUERY_KEY_VALUE_SEPERATOR = "=";
+ private static final String TOKEN_TYPE = "bearer";
+ private static final String TOKEN_IDENTIFIER = "token";
+ private static OAuthTokenValdiator oAuthTokenValdiator;
+
+ public static OAuthTokenValdiator getInstance() {
+ if (oAuthTokenValdiator == null) {
+ synchronized (OAuthTokenValdiator.class) {
+ if (oAuthTokenValdiator == null) {
+ oAuthTokenValdiator = new OAuthTokenValdiator();
+ }
+ }
+ }
+ return oAuthTokenValdiator;
+ }
+
+ private OAuthTokenValdiator() {
+ try {
+ Properties properties = getWebSocketConfig();
+ this.stubs = new GenericObjectPool(new OAuthTokenValidaterStubFactory(properties));
+ } catch (IOException e) {
+ log.error("Failed to parse the web socket config file " + WEBSOCKET_CONFIG_LOCATION);
+ }
+ }
+
+ /**
+ * This method gets a string accessToken and validates it
+ *
+ * @param session which need to be validated.
+ * @return AuthenticationInfo with the validated results.
+ */
+ public AuthenticationInfo validateToken(Session session) {
+ String token = getTokenFromSession(session);
+ if (token == null) {
+ AuthenticationInfo authenticationInfo = new AuthenticationInfo();
+ authenticationInfo.setAuthenticated(false);
+ return authenticationInfo;
+ }
+ OAuth2TokenValidationServiceStub tokenValidationServiceStub = null;
+ try {
+ Object stub = this.stubs.borrowObject();
+ if (stub != null) {
+ tokenValidationServiceStub = (OAuth2TokenValidationServiceStub) stub;
+ if (cookie != null) {
+ tokenValidationServiceStub._getServiceClient().getOptions().setProperty(
+ HTTPConstants.COOKIE_STRING, cookie);
+ }
+ return getAuthenticationInfo(token, tokenValidationServiceStub);
+ } else {
+ log.warn("Stub initialization failed.");
+ }
+ } catch (RemoteException e) {
+ log.error("Error on connecting with the validation endpoint.", e);
+ } catch (Exception e) {
+ log.error("Error occurred in borrowing an validation stub from the pool.", e);
+
+ } finally {
+ try {
+ if (tokenValidationServiceStub != null) {
+ this.stubs.returnObject(tokenValidationServiceStub);
+ }
+ } catch (Exception e) {
+ log.warn("Error occurred while returning the object back to the oauth token validation service " +
+ "stub pool.", e);
+ }
+ }
+ AuthenticationInfo authenticationInfo = new AuthenticationInfo();
+ authenticationInfo.setAuthenticated(false);
+ return authenticationInfo;
+ }
+
+ /**
+ * This creates an AuthenticationInfo object that is used for authorization. This method will validate the token
+ * and
+ * sets the required parameters to the object.
+ *
+ * @param token that needs to be validated.
+ * @param tokenValidationServiceStub stub that is used to call the external service.
+ * @return AuthenticationInfo This contains the information related to authenticated client.
+ * @throws RemoteException that triggers when failing to call the external service..
+ */
+ private AuthenticationInfo getAuthenticationInfo(String token,
+ OAuth2TokenValidationServiceStub tokenValidationServiceStub)
+ throws RemoteException, UserStoreException {
+ AuthenticationInfo authenticationInfo = new AuthenticationInfo();
+ OAuth2TokenValidationRequestDTO validationRequest = new OAuth2TokenValidationRequestDTO();
+ OAuth2TokenValidationRequestDTO_OAuth2AccessToken accessToken =
+ new OAuth2TokenValidationRequestDTO_OAuth2AccessToken();
+ accessToken.setTokenType(TOKEN_TYPE);
+ accessToken.setIdentifier(token);
+ validationRequest.setAccessToken(accessToken);
+ boolean authenticated;
+ OAuth2TokenValidationResponseDTO tokenValidationResponse;
+ tokenValidationResponse = tokenValidationServiceStub.validate(validationRequest);
+ if (tokenValidationResponse == null) {
+ authenticationInfo.setAuthenticated(false);
+ return authenticationInfo;
+ }
+ authenticated = tokenValidationResponse.getValid();
+ if (authenticated) {
+ String authorizedUser = tokenValidationResponse.getAuthorizedUser();
+ String username = MultitenantUtils.getTenantAwareUsername(authorizedUser);
+ String tenantDomain = MultitenantUtils.getTenantDomain(authorizedUser);
+ authenticationInfo.setUsername(username);
+ authenticationInfo.setTenantDomain(tenantDomain);
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("Token validation failed for token: " + token);
+ }
+ }
+ ServiceContext serviceContext = tokenValidationServiceStub._getServiceClient()
+ .getLastOperationContext().getServiceContext();
+ cookie = (String) serviceContext.getProperty(HTTPConstants.COOKIE_STRING);
+ authenticationInfo.setAuthenticated(authenticated);
+ return authenticationInfo;
+ }
+
+ /**
+ * Retrieve JWT configs from registry.
+ */
+ private Properties getWebSocketConfig() throws IOException {
+ Properties properties = new Properties();
+ File configFile =new File(WEBSOCKET_CONFIG_LOCATION);
+ if (configFile.exists()) {
+ InputStream fileInputStream = new FileInputStream(configFile);
+ if (fileInputStream != null) {
+ properties.load(fileInputStream);
+ }
+ }
+ return properties;
+ }
+
+ /**
+ * @param session of the user.
+ * @return retreive the token from the query string
+ */
+ private String getTokenFromSession(Session session) {
+ String queryString = session.getQueryString();
+ if (queryString != null) {
+ String[] allQueryParamPairs = queryString.split(QUERY_STRING_SEPERATOR);
+
+ for (String keyValuePair : allQueryParamPairs) {
+ String[] queryParamPair = keyValuePair.split(QUERY_KEY_VALUE_SEPERATOR);
+
+ if (queryParamPair.length != 2) {
+ log.warn("Invalid query string [" + queryString + "] passed in.");
+ break;
+ }
+ if (queryParamPair[0].equals(TOKEN_IDENTIFIER)) {
+ return queryParamPair[1];
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/OAuthTokenValidaterStubFactory.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/OAuthTokenValidaterStubFactory.java
new file mode 100644
index 0000000000..a43f874729
--- /dev/null
+++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/OAuthTokenValidaterStubFactory.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2016, 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 oauth;
+
+import oauth.exception.OAuthTokenValidationException;
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.Constants;
+import org.apache.axis2.client.Options;
+import org.apache.axis2.client.ServiceClient;
+import org.apache.axis2.transport.http.HTTPConstants;
+import org.apache.axis2.transport.http.HttpTransportProperties;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpConnectionManager;
+import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
+import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory;
+import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
+import org.apache.commons.pool.BasePoolableObjectFactory;
+import org.apache.log4j.Logger;
+import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
+import util.UIConstants;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.util.Properties;
+
+/**
+ * This follows object pool pattern to manage the stub for oauth validation service.
+ */
+public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
+ private static final Logger log = Logger.getLogger(OAuthTokenValidaterStubFactory.class);
+ private HttpClient httpClient;
+ Properties tokenValidationProperties;
+
+
+ public OAuthTokenValidaterStubFactory(Properties tokenValidationProperties) {
+ this.tokenValidationProperties = tokenValidationProperties;
+ this.httpClient = createHttpClient();
+ }
+
+ /**
+ * This creates a OAuth2TokenValidationServiceStub object to the pool.
+ *
+ * @return an OAuthValidationStub object
+ * @throws Exception thrown when creating the object.
+ */
+ @Override
+ public Object makeObject() throws Exception {
+ return this.generateStub();
+ }
+
+ /**
+ * This is used to clean up the OAuth validation stub and releases to the object pool.
+ *
+ * @param o object that needs to be released.
+ * @throws Exception throws when failed to release to the pool
+ */
+ @Override
+ public void passivateObject(Object o) throws Exception {
+ if (o instanceof OAuth2TokenValidationServiceStub) {
+ OAuth2TokenValidationServiceStub stub = (OAuth2TokenValidationServiceStub) o;
+ stub._getServiceClient().cleanupTransport();
+ }
+ }
+
+ /**
+ * This is used to create a stub which will be triggered through object pool factory, which will create an
+ * instance of it.
+ *
+ * @return OAuth2TokenValidationServiceStub stub that is used to call an external service.
+ * @throws OAuthTokenValidationException will be thrown when initialization failed.
+ */
+ private OAuth2TokenValidationServiceStub generateStub() throws OAuthTokenValidationException {
+ OAuth2TokenValidationServiceStub stub;
+ try {
+ URL hostURL = new URL(tokenValidationProperties.getProperty((UIConstants.TOKEN_VALIDATION_ENDPOINT_URL)));
+ if (hostURL != null) {
+ stub = new OAuth2TokenValidationServiceStub(hostURL.toString());
+ if (stub != null) {
+ ServiceClient client = stub._getServiceClient();
+ client.getServiceContext().getConfigurationContext().setProperty(
+ HTTPConstants.CACHED_HTTP_CLIENT, httpClient);
+
+ HttpTransportProperties.Authenticator auth =
+ new HttpTransportProperties.Authenticator();
+ auth.setPreemptiveAuthentication(true);
+ String username = tokenValidationProperties.getProperty(UIConstants.USERNAME);
+ String password = tokenValidationProperties.getProperty(UIConstants.PASSWORD);
+ auth.setPassword(username);
+ auth.setUsername(password);
+ Options options = client.getOptions();
+ options.setProperty(HTTPConstants.AUTHENTICATE, auth);
+ options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Constants.VALUE_TRUE);
+ client.setOptions(options);
+ if (hostURL.getProtocol().equals("https")) {
+ // set up ssl factory since axis2 https transport is used.
+ EasySSLProtocolSocketFactory sslProtocolSocketFactory =
+ createProtocolSocketFactory();
+ Protocol authhttps = new Protocol(hostURL.getProtocol(),
+ (ProtocolSocketFactory) sslProtocolSocketFactory,
+ hostURL.getPort());
+ Protocol.registerProtocol(hostURL.getProtocol(), authhttps);
+ options.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, authhttps);
+ }
+ } else {
+ String errorMsg = "OAuth Validation instanization failed.";
+ throw new OAuthTokenValidationException(errorMsg);
+ }
+ } else {
+ String errorMsg = "host url is invalid";
+ throw new OAuthTokenValidationException(errorMsg);
+ }
+ } catch (AxisFault axisFault) {
+ throw new OAuthTokenValidationException(
+ "Error occurred while creating the OAuth2TokenValidationServiceStub.", axisFault);
+ } catch (MalformedURLException e) {
+ throw new OAuthTokenValidationException(
+ "Error occurred while parsing token endpoint URL", e);
+ }
+
+ return stub;
+ }
+
+ /**
+ * This is required to create a trusted connection with the external entity.
+ * Have to manually configure it since we use CommonHTTPTransport(axis2 transport) in axis2.
+ *
+ * @return an EasySSLProtocolSocketFactory for SSL communication.
+ */
+ private EasySSLProtocolSocketFactory createProtocolSocketFactory() throws OAuthTokenValidationException {
+ try {
+ EasySSLProtocolSocketFactory easySSLPSFactory = new EasySSLProtocolSocketFactory();
+ return easySSLPSFactory;
+ } catch (IOException e) {
+ String errorMsg = "Failed to initiate EasySSLProtocolSocketFactory.";
+ throw new OAuthTokenValidationException(errorMsg, e);
+ } catch (GeneralSecurityException e) {
+ String errorMsg = "Failed to set the key material in easy ssl factory.";
+ throw new OAuthTokenValidationException(errorMsg, e);
+ }
+ }
+
+ /**
+ * This created httpclient pool that can be used to connect to external entity. This connection can be configured
+ * via broker.xml by setting up the required http connection parameters.
+ *
+ * @return an instance of HttpClient that is configured with MultiThreadedHttpConnectionManager
+ */
+ private HttpClient createHttpClient() {
+ HttpConnectionManagerParams params = new HttpConnectionManagerParams();
+ params.setDefaultMaxConnectionsPerHost(Integer.parseInt(tokenValidationProperties.getProperty(
+ UIConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST)));
+ params.setMaxTotalConnections(Integer.parseInt(tokenValidationProperties.getProperty(
+ UIConstants.MAXIMUM_TOTAL_HTTP_CONNECTION)));
+ HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
+ connectionManager.setParams(params);
+ return new HttpClient(connectionManager);
+ }
+}
diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/exception/OAuthTokenValidationException.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/exception/OAuthTokenValidationException.java
new file mode 100644
index 0000000000..3f54c5244c
--- /dev/null
+++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/exception/OAuthTokenValidationException.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2016, 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 oauth.exception;
+
+/**
+ * This Exception will be thrown, when there any interference with token validation flow.
+ */
+public class OAuthTokenValidationException extends Exception {
+ private String errMessage;
+
+ public OAuthTokenValidationException(String msg, Exception nestedEx) {
+ super(msg, nestedEx);
+ setErrorMessage(msg);
+ }
+
+ public OAuthTokenValidationException(String message, Throwable cause) {
+ super(message, cause);
+ setErrorMessage(message);
+ }
+
+ public OAuthTokenValidationException(String msg) {
+ super(msg);
+ setErrorMessage(msg);
+ }
+
+ public OAuthTokenValidationException() {
+ super();
+ }
+
+ public OAuthTokenValidationException(Throwable cause) {
+ super(cause);
+ }
+
+ public String getErrorMessage() {
+ return errMessage;
+ }
+
+ public void setErrorMessage(String errMessage) {
+ this.errMessage = errMessage;
+ }
+}
diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/AuthenticationInfo.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/AuthenticationInfo.java
new file mode 100644
index 0000000000..4e2115cf0c
--- /dev/null
+++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/AuthenticationInfo.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016, 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 util;
+
+/**
+ * This is returned after authentication.
+ */
+public class AuthenticationInfo {
+
+ /**
+ * this variable is used to check whether the client is authenticated.
+ */
+ private boolean authenticated;
+ private String username;
+ private String tenantDomain;
+ /**
+ * returns whether the client is authenticated
+ */
+ public boolean isAuthenticated() {
+ return authenticated;
+ }
+
+ public void setAuthenticated(boolean authenticated) {
+ this.authenticated = authenticated;
+ }
+
+ /**
+ * returns the authenticated client username
+ */
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ /**
+ * return the authenticated client tenant domain
+ */
+ public String getTenantDomain() {
+ return tenantDomain;
+ }
+
+ public void setTenantDomain(String tenantDomain) {
+ this.tenantDomain = tenantDomain;
+ }
+}
diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/ServiceHolder.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/ServiceHolder.java
new file mode 100644
index 0000000000..1f35b27d04
--- /dev/null
+++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/ServiceHolder.java
@@ -0,0 +1,27 @@
+package util;
+
+
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.device.mgt.iot.output.adapter.ui.UIOutputCallbackControllerService;
+
+public class ServiceHolder {
+
+ private static ServiceHolder instance;
+ private UIOutputCallbackControllerService uiOutputCallbackControllerService;
+
+ private ServiceHolder(){
+ uiOutputCallbackControllerService = (UIOutputCallbackControllerService) PrivilegedCarbonContext
+ .getThreadLocalCarbonContext().getOSGiService(UIOutputCallbackControllerService.class, null);
+ }
+
+ public synchronized static ServiceHolder getInstance(){
+ if (instance==null){
+ instance= new ServiceHolder();
+ }
+ return instance;
+ }
+
+ public UIOutputCallbackControllerService getUiOutputCallbackControllerService() {
+ return uiOutputCallbackControllerService;
+ }
+}
diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/UIConstants.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/UIConstants.java
new file mode 100644
index 0000000000..2db13ce816
--- /dev/null
+++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/UIConstants.java
@@ -0,0 +1,38 @@
+/*
+ *
+ * *
+ * * Copyright (c) 2015, 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 util;
+
+/**
+ * This class contains the constants related to ui client.
+ */
+public class UIConstants {
+
+ private UIConstants() {
+ }
+ public static final String ADAPTER_UI_COLON = ":";
+ public static final String MAXIMUM_TOTAL_HTTP_CONNECTION = "maximumTotalHttpConnection";
+ public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST = "maximumHttpConnectionPerHost";
+ public static final String TOKEN_VALIDATION_ENDPOINT_URL = "tokenValidationEndpoint";
+ public static final String USERNAME = "username";
+ public static final String PASSWORD = "password";
+}
diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/webapp/WEB-INF/web.xml b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000000..2ec7fc7e94
--- /dev/null
+++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,24 @@
+
+
+
+
+ Output WebSocket
+
diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/pom.xml b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/pom.xml
new file mode 100644
index 0000000000..0739a96d4c
--- /dev/null
+++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/pom.xml
@@ -0,0 +1,137 @@
+
+
+
+
+
+ iot-base-plugin
+ org.wso2.carbon.devicemgt-plugins
+ 2.1.1-SNAPSHOT
+ ../pom.xml
+
+
+ 4.0.0
+ org.wso2.carbon.device.mgt.iot.output.adapter.ui
+ bundle
+ WSO2 Carbon - Event Output UI Adapter Module
+ org.wso2.carbon.event.output.adapter.ui provides the back-end functionality of
+ ui 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.wso2.carbon
+ org.wso2.carbon.core
+
+
+ javax.websocket
+ javax.websocket-api
+
+
+ org.wso2.carbon.analytics-common
+ org.wso2.carbon.databridge.commons
+
+
+ com.google.code.gson
+ gson
+
+
+ org.wso2.carbon.analytics-common
+ org.wso2.carbon.event.stream.core
+
+
+
+
+
+
+ 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.iot.output.adapter.ui.internal,
+ org.wso2.carbon.device.mgt.iot.output.adapter.ui.internal.*
+
+
+ !org.wso2.carbon.device.mgt.iot.output.adapter.ui.internal,
+ !org.wso2.carbon.device.mgt.iot.output.adapter.ui.internal.*,
+ org.wso2.carbon.device.mgt.iot.output.adapter.ui.*
+
+
+ org.wso2.carbon.event.output.adapter.core.*,
+ javax.xml.namespace; version=0.0.0,
+ org.apache.axis2,
+ org.apache.axis2.client,
+ org.apache.axis2.context,
+ org.apache.axis2.transport.http,
+ org.apache.commons.httpclient,
+ org.apache.commons.httpclient.contrib.ssl,
+ org.apache.commons.httpclient.params,
+ org.apache.commons.httpclient.protocol,
+ org.apache.commons.pool,
+ org.apache.commons.pool.impl,
+ org.apache.log4j,
+ com.google.gson,
+ javax.websocket,
+ org.apache.commons.logging,
+ org.osgi.framework,
+ org.osgi.service.component,
+ org.wso2.carbon.context,
+ org.wso2.carbon.databridge.commons,
+ org.wso2.carbon.event.stream.core,
+ org.wso2.carbon.event.stream.core.exception,
+ org.wso2.carbon.utils
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIEventAdapter.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIEventAdapter.java
new file mode 100644
index 0000000000..4f28987954
--- /dev/null
+++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIEventAdapter.java
@@ -0,0 +1,455 @@
+/*
+ *
+ * Copyright (c) 2015, 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.iot.output.adapter.ui;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.context.CarbonContext;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.databridge.commons.Attribute;
+import org.wso2.carbon.databridge.commons.Event;
+import org.wso2.carbon.databridge.commons.StreamDefinition;
+import org.wso2.carbon.device.mgt.iot.output.adapter.ui.internal.UIEventAdaptorServiceDataHolder;
+import org.wso2.carbon.device.mgt.iot.output.adapter.ui.util.UIEventAdapterConstants;
+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.device.mgt.iot.output.adapter.ui.util.WebSocketSessionUtil;
+import org.wso2.carbon.event.stream.core.EventStreamService;
+import org.wso2.carbon.event.stream.core.exception.EventStreamConfigurationException;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Contains the life cycle of executions regarding the UI Adapter
+ */
+
+public class UIEventAdapter implements OutputEventAdapter {
+
+ private static final Log log = LogFactory.getLog(UIEventAdapter.class);
+ private OutputEventAdapterConfiguration eventAdapterConfiguration;
+ private Map globalProperties;
+ private int queueSize;
+ private LinkedBlockingDeque