components/extensions/pom.xml

revert-dabc3590
warunalakshitha 7 years ago
parent 3c464862d4
commit 0f09aa2a14

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>remote-session-extension</artifactId>
<version>4.0.35-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.extensions.remote.session.endpoint</artifactId>
<packaging>war</packaging>
<name>WSO2 - Webapp for UI Remote Session</name>
<url>http://wso2.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-websocket-api</artifactId>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>org.json.wso2</groupId>
<artifactId>json</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.extensions.remote.session</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>remote#session</finalName>
</build>
</project>

@ -0,0 +1,136 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* deviceId 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.extensions.remote.session.endpoint;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.extensions.remote.session.constants.RemoteSessionConstants;
import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionInvalidException;
import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionManagementException;
import org.wso2.carbon.device.mgt.extensions.remote.session.endpoint.utils.HttpSessionConfigurator;
import org.wso2.carbon.device.mgt.extensions.remote.session.endpoint.utils.ServiceHolder;
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;
/**
* This class represents web socket endpoint to manage Remote Sessions
*/
@ServerEndpoint(value = "/clients/{deviceType}/{deviceId}", configurator = HttpSessionConfigurator.class)
public class ClientSessionSubscriptionEndpoint extends SubscriptionEndpoint {
private static final Log log = LogFactory.getLog(ClientSessionSubscriptionEndpoint.class);
private RemoteSessionConstants.CONNECTION_MODES connectionMode = RemoteSessionConstants.CONNECTION_MODES.CLIENT_MODE;
/**
* Web socket onOpen - When client sends a message
*
* @param session - Users registered session..
*/
@OnOpen
public void onOpen(Session session, @PathParam("deviceType") String deviceType, @PathParam("deviceId") String
deviceId) {
System.out.print("**************Open***************");
if (log.isDebugEnabled()) {
log.debug("WebSocket opened, for RemoteSession id: " + session.getId());
}
try {
ServiceHolder.getInstance().getRemoteSessionManagementService().initializeSession(session, deviceType, deviceId);
System.out.print("**************Opened***************");
} catch (RemoteSessionInvalidException e) {
System.out.print(e.getMessage());
if (log.isDebugEnabled()) {
log.error("Error occurred while initializing session ", e);
}
try {
session.close(e.getCloseReason());
} catch (IOException ex) {
log.error("Failed to disconnect the client.", ex);
}
} catch (RemoteSessionManagementException e) {
System.out.print(e.getMessage());
if (log.isDebugEnabled()) {
log.error("Error occurred while initializing session ", e);
}
try {
session.close(new CloseReason(CloseReason.CloseCodes.CANNOT_ACCEPT, "Error occurred while adding operation"));
} catch (IOException ex) {
if (log.isDebugEnabled()) {
log.error("Failed to disconnect the client.", ex);
}
}
}
}
/**
* Web socket onMessage - When client sends a message
*
* @param session - Users registered session.
* @param message - Status code for web-socket close.
*/
@OnMessage
public void onMessage(Session session, String message, @PathParam("deviceType") String deviceType, @PathParam
("deviceId") String deviceId) throws RemoteSessionManagementException {
super.onMessage(session, message, deviceType, deviceId);
}
/**
* Web socket onMessage - When client sends a message
*
* @param session - Users registered session.
* @param message - Message which needs to send to peer
*/
@OnMessage
public void onMessage(Session session, byte[] message, @PathParam("deviceType") String deviceType, @PathParam
("deviceId") String deviceId) throws RemoteSessionManagementException {
super.onMessage(session, message, deviceType, deviceId);
}
/**
* Web socket onClose - Remove the registered sessions
*
* @param session - Users registered session.
* @param reason - Status code for web-socket close.
*/
@OnClose
public void onClose(Session session, CloseReason reason, @PathParam("deviceType") String deviceType, @PathParam
("deviceId") String deviceId) {
super.onClose(session, reason, deviceType, deviceId);
}
/**
* Web socket onError - Remove the registered sessions
*
* @param session - Users registered session.
* @param throwable - Status code for web-socket close.
*/
@OnError
public void onError(Session session, Throwable throwable, @PathParam("deviceType") String deviceType, @PathParam
("deviceId") String deviceId) {
super.onError(session, throwable, deviceType, deviceId);
}
}

@ -0,0 +1,137 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* deviceId 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.extensions.remote.session.endpoint;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.extensions.remote.session.constants.RemoteSessionConstants;
import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionInvalidException;
import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionManagementException;
import org.wso2.carbon.device.mgt.extensions.remote.session.endpoint.utils.HttpSessionConfigurator;
import org.wso2.carbon.device.mgt.extensions.remote.session.endpoint.utils.ServiceHolder;
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;
/**
* This class represents web socket endpoint to manage Remote Sessions
*/
@ServerEndpoint(value = "/devices/{deviceType}/{deviceId}/{operationId}", configurator = HttpSessionConfigurator.class)
public class DeviceSessionSubscriptionEndpoint extends SubscriptionEndpoint {
private static final Log log = LogFactory.getLog(DeviceSessionSubscriptionEndpoint.class);
private RemoteSessionConstants.CONNECTION_MODES connectionMode = RemoteSessionConstants.CONNECTION_MODES.DEVICE_MODE;
/**
* Web socket onOpen - When client sends a message
*
* @param session - Users registered session..
*/
@OnOpen
public void onOpen(Session session, @PathParam("deviceType") String deviceType, @PathParam("deviceId") String
deviceId, @PathParam("operationId") String operationId) {
System.out.print("**************Open***************"+operationId);
if (log.isDebugEnabled()) {
log.debug("WebSocket opened, for RemoteSession id: " + session.getId());
}
try {
ServiceHolder.getInstance().getRemoteSessionManagementService().initializeSession(session, deviceType,
deviceId, operationId);
System.out.print("**************Opened***************");
} catch (RemoteSessionInvalidException e) {
System.out.print(e.getMessage());
if (log.isDebugEnabled()) {
log.error("Error occurred while initializing session ", e);
}
try {
session.close(e.getCloseReason());
} catch (IOException ex) {
log.error("Failed to disconnect the client.", ex);
}
} catch (RemoteSessionManagementException e) {
System.out.print(e.getMessage());
if (log.isDebugEnabled()) {
log.error("Error occurred while initializing session ", e);
}
try {
session.close(new CloseReason(CloseReason.CloseCodes.CANNOT_ACCEPT, "Error occurred while adding operation"));
} catch (IOException ex) {
if (log.isDebugEnabled()) {
log.error("Failed to disconnect the client.", ex);
}
}
}
}
/**
* Web socket onMessage - When client sends a message
*
* @param session - Users registered session.
* @param message - Status code for web-socket close.
*/
@OnMessage
public void onMessage(Session session, String message, @PathParam("deviceType") String deviceType, @PathParam
("deviceId") String deviceId) throws RemoteSessionManagementException {
super.onMessage(session, message, deviceType, deviceId);
}
/**
* Web socket onMessage - When client sends a message
*
* @param session - Users registered session.
* @param message - Message which needs to send to peer
*/
@OnMessage
public void onMessage(Session session, byte[] message, @PathParam("deviceType") String deviceType, @PathParam
("deviceId") String deviceId) throws RemoteSessionManagementException {
super.onMessage(session, message, deviceType, deviceId);
}
/**
* Web socket onClose - Remove the registered sessions
*
* @param session - Users registered session.
* @param reason - Status code for web-socket close.
*/
@OnClose
public void onClose(Session session, CloseReason reason, @PathParam("deviceType") String deviceType, @PathParam
("deviceId") String deviceId) {
super.onClose(session, reason, deviceType, deviceId);
}
/**
* Web socket onError - Remove the registered sessions
*
* @param session - Users registered session.
* @param throwable - Status code for web-socket close.
*/
@OnError
public void onError(Session session, Throwable throwable, @PathParam("deviceType") String deviceType, @PathParam
("deviceId") String deviceId) {
super.onError(session, throwable, deviceType, deviceId);
}
}

@ -0,0 +1,144 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* deviceId 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.extensions.remote.session.endpoint;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionInvalidException;
import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionManagementException;
import org.wso2.carbon.device.mgt.extensions.remote.session.endpoint.utils.ServiceHolder;
import javax.websocket.CloseReason;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import java.io.IOException;
/**
* This class represents common web socket endpoint to manage Remote Sessions
*/
public class SubscriptionEndpoint {
private static final Log log = LogFactory.getLog(SubscriptionEndpoint.class);
/**
* Web socket onMessage - When client sends a message
*
* @param session - Users registered session.
* @param message - Status code for web-socket close.
*/
public void onMessage(Session session, String message, @PathParam("deviceType") String deviceType, @PathParam
("deviceId") String deviceId) throws RemoteSessionManagementException {
System.out.print("______________" + session.getId());
if (log.isDebugEnabled()) {
log.debug("Received message from client for RemoteSession id: " + session.getId() + " device type: " +
deviceType + " device id: " + deviceId);
}
try {
ServiceHolder.getInstance().getRemoteSessionManagementService().sendMessageToPeer(session, message);
} catch (RemoteSessionInvalidException e) {
if (log.isDebugEnabled()) {
log.error("Error occurred while send message to peer session ", e);
}
try {
session.close(e.getCloseReason());
} catch (IOException ex) {
if (log.isDebugEnabled()) {
log.error("Failed to disconnect the client.", ex);
}
}
}
}
/**
* Web socket onMessage - When client sends a message
*
* @param session - Users registered session.
* @param message - Message which needs to send to peer
*/
public void onMessage(Session session, byte[] message, @PathParam("deviceType") String deviceType, @PathParam
("deviceId") String deviceId) throws RemoteSessionManagementException {
System.out.print("______________" + session.getId());
if (log.isDebugEnabled()) {
log.debug("Received message from client for RemoteSession id: " + session.getId() + " device type: " +
deviceType + " device id: " + deviceId);
}
try {
ServiceHolder.getInstance().getRemoteSessionManagementService().sendMessageToPeer(session, message);
} catch (RemoteSessionInvalidException e) {
if (log.isDebugEnabled()) {
log.error("Error occurred while send message to peer session ", e);
}
try {
session.close(e.getCloseReason());
} catch (IOException ex) {
if (log.isDebugEnabled()) {
log.error("Failed to disconnect the client.", ex);
}
}
}
}
/**
* Web socket onClose - Remove the registered sessions
*
* @param session - Users registered session.
* @param reason - Status code for web-socket close.
*/
public void onClose(Session session, CloseReason reason, @PathParam("deviceType") String deviceType, @PathParam
("deviceId") String deviceId) {
if (log.isDebugEnabled()) {
log.debug("Closing a WebSocket due to " + reason.getReasonPhrase() + ", for session ID:" + session.getId
() + ", for request URI - " + session.getRequestURI() + " device type: " + deviceType + " device id: " + deviceId);
}
try {
ServiceHolder.getInstance().getRemoteSessionManagementService().endSession(session);
if (session.isOpen()) {
session.close(new CloseReason(CloseReason.CloseCodes.PROTOCOL_ERROR, "Unexpected Error Occurred"));
}
} catch (IOException ex) {
if (log.isDebugEnabled()) {
log.error("Failed to disconnect the client.", ex);
}
}
}
/**
* Web socket onError - Remove the registered sessions
*
* @param session - Users registered session.
* @param throwable - Status code for web-socket close.
*/
public void onError(Session session, Throwable throwable, @PathParam("deviceType") String deviceType, @PathParam
("deviceId") String deviceId) {
log.error(
"Error occurred in session ID: " + session.getId() + " device type: " + deviceType + " device id: " +
deviceId + ", for request URI - " + session.getRequestURI() +
", " + throwable.getMessage(), throwable);
try {
ServiceHolder.getInstance().getRemoteSessionManagementService().endSession(session);
if (session.isOpen()) {
session.close(new CloseReason(CloseReason.CloseCodes.PROTOCOL_ERROR, "Unexpected Error Occurred"));
}
} catch (IOException ex) {
if (log.isDebugEnabled()) {
log.error("Failed to disconnect the client.", ex);
}
}
}
}

@ -0,0 +1,25 @@
/*
*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.wso2.carbon.device.mgt.extensions.remote.session.endpoint.constants;
public class Constants {
public static final String HTTP_HEADERS = "HttpHeaders";
}

@ -0,0 +1,36 @@
/*
*
* 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 org.wso2.carbon.device.mgt.extensions.remote.session.endpoint.utils;
import org.wso2.carbon.device.mgt.extensions.remote.session.endpoint.constants.Constants;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import java.util.List;
import java.util.Map;
public class HttpSessionConfigurator extends ServerEndpointConfig.Configurator {
public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
Map<String, List<String>> httpHeaders = request.getHeaders();
config.getUserProperties().put(Constants.HTTP_HEADERS, httpHeaders);
}
}

@ -0,0 +1,53 @@
/*
* 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.extensions.remote.session.endpoint.utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.extensions.remote.session.RemoteSessionManagementService;
public class ServiceHolder {
private static ServiceHolder instance;
private static final Log log = LogFactory.getLog(ServiceHolder.class);
private ServiceHolder() {
}
public synchronized static ServiceHolder getInstance() {
if (instance == null) {
instance = new ServiceHolder();
}
return instance;
}
public RemoteSessionManagementService getRemoteSessionManagementService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
RemoteSessionManagementService RemoteSessionManagementService =
(RemoteSessionManagementService) ctx.getOSGiService(RemoteSessionManagementService.class, null);
if (RemoteSessionManagementService == null) {
String msg = "Remote Session Management service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return RemoteSessionManagementService;
}
}

@ -0,0 +1,59 @@
<!--
~ 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.
-->
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Remote Session</display-name>
<filter>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<init-param>
<param-name>hstsEnabled</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter>
<filter-name>ContentTypeBasedCachePreventionFilter</filter-name>
<filter-class>org.wso2.carbon.ui.filters.cache.ContentTypeBasedCachePreventionFilter</filter-class>
<init-param>
<param-name>patterns</param-name>
<param-value>text/html" ,application/json" ,text/plain</param-value>
</init-param>
<init-param>
<param-name>filterAction</param-name>
<param-value>enforce</param-value>
</init-param>
<init-param>
<param-name>httpHeaders</param-name>
<param-value>Cache-Control: no-store, no-cache, must-revalidate, private</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>ContentTypeBasedCachePreventionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>remote-session-extension</artifactId>
<version>4.0.35-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.extensions.remote.session</artifactId>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Remote Session Manager Implementation</name>
<description>WSO2 Carbon - Remote Session Manager Implementation</description>
<url>http://wso2.org</url>
<dependencies>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.logging</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.core</artifactId>
</dependency>
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.wso2</groupId>
<artifactId>httpcore</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.orbit.org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity.inbound.auth.oauth2</groupId>
<artifactId>org.wso2.carbon.identity.oauth.stub</artifactId>
</dependency>
<dependency>
<groupId>commons-pool.wso2</groupId>
<artifactId>commons-pool</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-gson</artifactId>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-slf4j</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.core</artifactId>
</dependency>
<dependency>
<groupId>org.json.wso2</groupId>
<artifactId>json</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Bundle-Version>${carbon.devicemgt.plugins.version}</Bundle-Version>
<Bundle-Description>Remote Session Manager Bundle</Bundle-Description>
<Export-Package>
!org.wso2.carbon.device.mgt.extensions.remote.session.internal,
org.wso2.carbon.device.mgt.extensions.remote.session.*
</Export-Package>
<Import-Package>
*;resolution:=optional
</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,84 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.extensions.remote.session;
import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionInvalidException;
import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionManagementException;
import javax.websocket.Session;
/**
* Class @{@link RemoteSessionManagementService} use for managing remote sessions
*/
public interface RemoteSessionManagementService {
/**
* Initialize session based on web socket request .this method use by the device to connect
*
* @param session Web socket RemoteSession
* @param deviceType Device Type
* @param deviceId Device Id
* @throws RemoteSessionInvalidException throws when session cannot be made due to invalid data
* @throws RemoteSessionManagementException throws when session has error with accessing device resources
*/
public void initializeSession(Session session, String deviceType, String deviceId) throws
RemoteSessionInvalidException, RemoteSessionManagementException;
/**
* Initialize session based on web socket request .this method use by the device to connect
*
* @param session Web socket RemoteSession
* @param deviceType Device Type
* @param deviceId Device Id
* @param operationId Operation Id that device needs to connec
* @throws RemoteSessionInvalidException throws when session cannot be made due to invalid data
* @throws RemoteSessionManagementException throws when session has error with accessing device resources
*/
public void initializeSession(Session session, String deviceType, String deviceId, String operationId) throws
RemoteSessionInvalidException, RemoteSessionManagementException;
/**
* Send message to connected remote device or client
*
* @param session Web socket RemoteSession
* @param message Message needs to send to peer connection client
* @throws RemoteSessionInvalidException
* @throws RemoteSessionManagementException
*/
public void sendMessageToPeer(Session session, String message) throws
RemoteSessionInvalidException, RemoteSessionManagementException;
/**
* Send message to connected remote device or client
*
* @param session Web socket RemoteSession
* @param message Message needs to send to peer connection
* @throws RemoteSessionInvalidException
* @throws RemoteSessionManagementException
*/
public void sendMessageToPeer(Session session, byte[] message) throws
RemoteSessionInvalidException, RemoteSessionManagementException;
/**
* Close the session
*
* @param session Web socket RemoteSession
*/
public void endSession(Session session);
}

@ -0,0 +1,274 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.extensions.remote.session;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONObject;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.InvalidDeviceException;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.core.DeviceManagementConstants;
import org.wso2.carbon.device.mgt.core.operation.mgt.ConfigOperation;
import org.wso2.carbon.device.mgt.extensions.remote.session.authentication.AuthenticationInfo;
import org.wso2.carbon.device.mgt.extensions.remote.session.authentication.OAuthAuthenticator;
import org.wso2.carbon.device.mgt.extensions.remote.session.constants.RemoteSessionConstants;
import org.wso2.carbon.device.mgt.extensions.remote.session.dto.RemoteSession;
import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionInvalidException;
import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionManagementException;
import org.wso2.carbon.device.mgt.extensions.remote.session.internal.RemoteSessionManagementDataHolder;
import javax.websocket.CloseReason;
import javax.websocket.Session;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class RemoteSessionManagementServiceImpl implements RemoteSessionManagementService {
private static final Log log = LogFactory.getLog(RemoteSessionManagementServiceImpl.class);
private static final String DATE_FORMAT_NOW = "yyyy-MM-dd HH:mm:ss";
private static final int MAX_BUFFER_SIZE = 640 * 1024;
@Override
public void initializeSession(Session session, String deviceType, String deviceId, String operationId) throws
RemoteSessionInvalidException, RemoteSessionManagementException {
if (!RemoteSessionManagementDataHolder.getInstance().isEnabled()) {
throw new RemoteSessionManagementException("Remote session feature is disabled.");
} else if (RemoteSessionManagementDataHolder.getInstance().getServerUrl() == null) {
throw new RemoteSessionManagementException("Server url haven't been configured.");
}
Map<String, List<String>> sessionQueryParam = new HashedMap();
List<String> sessionQueryParamList = new LinkedList<>();
sessionQueryParamList.add(session.getQueryString());
sessionQueryParam.put(RemoteSessionConstants.QUERY_STRING, sessionQueryParamList);
// Validate the token
OAuthAuthenticator oAuthAuthenticator = RemoteSessionManagementDataHolder.getInstance().getOauthAuthenticator();
AuthenticationInfo authenticationInfo = oAuthAuthenticator.isAuthenticated(sessionQueryParam);
if (authenticationInfo != null && authenticationInfo.isAuthenticated()) {
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(authenticationInfo.getTenantDomain()
, true);
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(authenticationInfo.getUsername());
if (deviceId != null && !deviceId.isEmpty() && deviceType != null && !deviceType.isEmpty()) {
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(deviceType);
boolean userAuthorized = RemoteSessionManagementDataHolder.getInstance()
.getDeviceAccessAuthorizationService()
.isUserAuthorized(deviceIdentifier, authenticationInfo.getUsername());
if (userAuthorized) {
log.info("Operation ID: " + operationId);
if (operationId != null) {
Session pendingSession = RemoteSessionManagementDataHolder.getInstance()
.getDeviceRequestMap().get((authenticationInfo.getTenantDomain() + "/" + deviceType
+ "/" + deviceId));
if (pendingSession != null) {
RemoteSession clientRemote = RemoteSessionManagementDataHolder.getInstance()
.getSessionMap().get(pendingSession.getId());
if (clientRemote != null) {
if (clientRemote.getOperationId().equals(operationId)) {
RemoteSession deviceRemote = new RemoteSession(authenticationInfo.getTenantDomain
(), deviceType, deviceId, operationId, RemoteSessionConstants
.CONNECTION_MODES.DEVICE_MODE);
deviceRemote.setPeerSession(pendingSession);
clientRemote.setPeerSession(session);
RemoteSessionManagementDataHolder.getInstance().getSessionMap().put(session
.getId(), deviceRemote);
RemoteSessionManagementDataHolder.getInstance().getDeviceRequestMap().remove(
(authenticationInfo.getTenantDomain() + "/" + deviceType + "/" + deviceId));
// Send Remote connect response
JSONObject message = new JSONObject();
message.put("code", RemoteSessionConstants.REMOTE_CONNECT);
message.put("operation_response", "connected");
deviceRemote.sendMessageToPeer(message.toString());
// set buffer sizes
session.setMaxBinaryMessageBufferSize(MAX_BUFFER_SIZE);
session.setMaxTextMessageBufferSize(MAX_BUFFER_SIZE);
} else {
throw new RemoteSessionManagementException("Device and Operation information does" +
" not matched with client information for operation id: " + operationId +
" device Type : " + deviceType + " , " + "deviceId : " +
deviceId);
}
} else {
throw new RemoteSessionManagementException("Device session is inactive for operation " +
"id: " + operationId + " device Type : " + deviceType + " , " + "deviceId : " +
deviceId);
}
} else {
throw new RemoteSessionManagementException("Device session is inactive for operation " +
"id: " + operationId + " device Type : " + deviceType + " , " + "deviceId : " +
deviceId);
}
} else {
// Create new remote control operation to start the session
Session pendingSession = RemoteSessionManagementDataHolder.getInstance().getDeviceRequestMap().get(
(authenticationInfo.getTenantDomain() + "/" + deviceType + "/" + deviceId));
if (pendingSession != null && pendingSession.isOpen()) {
throw new RemoteSessionManagementException("Another client session waiting on device to connect.");
} else {
Session lastSession = RemoteSessionManagementDataHolder.getInstance().getDeviceRequestMap().putIfAbsent(
(authenticationInfo.getTenantDomain() + "/" + deviceType + "/" + deviceId),
session);
if (lastSession == null) {
Operation operation = new ConfigOperation();
operation.setCode(RemoteSessionConstants.REMOTE_CONNECT);
operation.setEnabled(true);
JSONObject payload = new JSONObject();
payload.put("serverUrl", RemoteSessionManagementDataHolder.getInstance().getServerUrl());
operation.setPayLoad(payload.toString());
String date = new SimpleDateFormat(DATE_FORMAT_NOW).format(new Date());
operation.setCreatedTimeStamp(date);
List<DeviceIdentifier> deviceIdentifiers = new ArrayList<>();
deviceIdentifiers.add(new DeviceIdentifier(deviceId, deviceType));
Activity activity = RemoteSessionManagementDataHolder.getInstance()
.getDeviceManagementProviderService().addOperation(deviceType, operation,
deviceIdentifiers);
log.info("Activity id: " + activity.getActivityId());
RemoteSession clientRemote = new RemoteSession(authenticationInfo.getTenantDomain(),
deviceType, deviceId, activity.getActivityId().replace(DeviceManagementConstants
.OperationAttributes.ACTIVITY, ""), RemoteSessionConstants
.CONNECTION_MODES.CLIENT_MODE);
RemoteSessionManagementDataHolder.getInstance().getSessionMap().put(session.getId(), clientRemote);
session.setMaxBinaryMessageBufferSize(MAX_BUFFER_SIZE);
session.setMaxTextMessageBufferSize(MAX_BUFFER_SIZE);
}
}
}
log.info("Current session count: " + RemoteSessionManagementDataHolder
.getInstance().getSessionMap().size());
} else {
throw new RemoteSessionInvalidException("Missing device Id or type ", new CloseReason
(CloseReason.CloseCodes.CANNOT_ACCEPT, "Missing device Id or device type "));
}
} else {
throw new RemoteSessionInvalidException("Unauthorized Access for the device Type : " + deviceType
+ " , deviceId : " + deviceId, new CloseReason(CloseReason.CloseCodes.CANNOT_ACCEPT,
"Unauthorized Access"));
}
} catch (OperationManagementException | InvalidDeviceException e) {
throw new RemoteSessionManagementException("Error occurred while adding initial operation for the device Type : " +
deviceType + " , deviceId : " + deviceId, e);
} catch (DeviceAccessAuthorizationException e) {
throw new RemoteSessionManagementException("Error occurred while device access authorization for the device Type : " +
deviceType + " , " + "deviceId : " + deviceId, e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
} else {
throw new RemoteSessionInvalidException("Invalid token", new CloseReason(CloseReason.CloseCodes
.CANNOT_ACCEPT, "Invalid token"));
}
}
@Override
public void initializeSession(Session session, String deviceType, String deviceId) throws RemoteSessionInvalidException, RemoteSessionManagementException {
initializeSession(session, deviceType, deviceId, null);
}
/**
* Implements the behaviour of sending message to peer connection
*
* @param session Web socket RemoteSession
* @param message Message needs to send to peer connection
* @throws RemoteSessionInvalidException throws when session cannot be made due to invalid data
* @throws RemoteSessionManagementException throws when session has error with accessing device resources
*/
@Override
public void sendMessageToPeer(Session session, String message) throws RemoteSessionManagementException,
RemoteSessionInvalidException {
JSONObject jsonObject = new JSONObject(message);
RemoteSession remoteSession = RemoteSessionManagementDataHolder.getInstance().getSessionMap().get(session.getId());
if (remoteSession != null) {
if (remoteSession.getConnection_mode().equals(RemoteSessionConstants.CONNECTION_MODES.CLIENT_MODE)) {
jsonObject.put("id", remoteSession.getOperationId());
}
remoteSession.sendMessageToPeer(jsonObject.toString());
} else {
throw new RemoteSessionInvalidException("Remote Session cannot be found ", new CloseReason(CloseReason
.CloseCodes.CANNOT_ACCEPT, "Invalid RemoteSession"));
}
}
@Override
public void sendMessageToPeer(Session session, byte[] message) throws RemoteSessionInvalidException,
RemoteSessionManagementException {
RemoteSession remoteSession = RemoteSessionManagementDataHolder.getInstance().getSessionMap().get(session.getId());
if (remoteSession != null) {
remoteSession.sendMessageToPeer(message);
} else {
throw new RemoteSessionInvalidException("Remote Session cannot be found ", new CloseReason(CloseReason
.CloseCodes.CANNOT_ACCEPT, "Invalid RemoteSession"));
}
}
/**
* Closing the session and cleanup the resources
*
* @param session Web socket RemoteSession
*/
@Override
public void endSession(Session session) {
RemoteSession remoteSession = RemoteSessionManagementDataHolder.getInstance().getSessionMap().remove(session.getId());
if (remoteSession != null) {
String operationId = remoteSession.getOperationId();
Session peerSession = remoteSession.getPeerSession();
if (peerSession != null) {
RemoteSessionManagementDataHolder.getInstance().getSessionMap().remove(peerSession.getId());
}
if (operationId != null) {
Session lastSession = RemoteSessionManagementDataHolder.getInstance().getDeviceRequestMap().get(
(remoteSession.getTenantDomain() + "/" + remoteSession.getDeviceType() + "/" + remoteSession
.getDeviceId()));
if (lastSession != null && lastSession.getId().equals(session.getId())) {
RemoteSessionManagementDataHolder.getInstance().getDeviceRequestMap().remove(
(remoteSession.getTenantDomain() + "/" + remoteSession.getDeviceType() + "/" + remoteSession
.getDeviceId()));
}
}
}
}
}

@ -0,0 +1,76 @@
/*
* 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 org.wso2.carbon.device.mgt.extensions.remote.session.authentication;
import java.util.Map;
/**
* 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;
/**
* To hold authentication related properties eg: scopes in oauth
*/
private Map<String, Object> properties;
/**
* 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;
}
public Map<String, Object> getProperties() {
return properties;
}
public void setProperties(Map<String, Object> properties) {
this.properties = properties;
}
}

@ -0,0 +1,33 @@
/*
* 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 org.wso2.carbon.device.mgt.extensions.remote.session.authentication;
import org.wso2.carbon.device.mgt.extensions.remote.session.authentication.oauth.OAuthTokenValidator;
import java.util.List;
import java.util.Map;
public class OAuthAuthenticator {
OAuthTokenValidator oAuthTokenValidator;
public void init(Map<String, String> globalProperties) {
oAuthTokenValidator = new OAuthTokenValidator(globalProperties);
}
public AuthenticationInfo isAuthenticated(Map<String, List<String>> webSocketConnectionProperties) {
return oAuthTokenValidator.validateToken(webSocketConnectionProperties);
}
}

@ -0,0 +1,197 @@
/*
* 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 org.wso2.carbon.device.mgt.extensions.remote.session.authentication.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.device.mgt.extensions.remote.session.authentication.AuthenticationInfo;
import org.wso2.carbon.device.mgt.extensions.remote.session.constants.RemoteSessionConstants;
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.utils.multitenancy.MultitenantUtils;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* This acts as a contract point for OAuth token validation.
*/
public class OAuthTokenValidator {
private static String cookie;
private GenericObjectPool stubs;
private static Log log = LogFactory.getLog(OAuthTokenValidator.class);
private static final String COOKIE_KEY_VALUE_SEPERATOR = "=";
private static final String COOKIE_KEYPAIR_SEPERATOR = ";";
private static final String COOKIE = "cookie";
private static final String TOKEN_TYPE = "bearer";
private static final String TOKEN_IDENTIFIER = "websocketToken";
private static final String QUERY_STRING_SEPERATOR = "&";
private static final String QUERY_KEY_VALUE_SEPERATOR = "=";
private static final String QUERY_STRING = "queryString";
private static OAuthTokenValidator oAuthTokenValidator;
public OAuthTokenValidator(Map<String, String> globalProperties) {
this.stubs = new GenericObjectPool(new OAuthTokenValidatorStubFactory(globalProperties));
}
/**
* This method gets a string accessToken and validates it
* @param webSocketConnectionProperties WebSocket connection information including http headers
* @return AuthenticationInfo with the validated results.
*/
public AuthenticationInfo validateToken(Map<String, List<String>> webSocketConnectionProperties) {
String token = getTokenFromSession(webSocketConnectionProperties);
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 {
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);
String scopes[] = tokenValidationResponse.getScope();
if (scopes != null) {
Map<String, Object> properties = new HashMap<>();
properties.put(RemoteSessionConstants.SCOPE_IDENTIFIER, scopes);
authenticationInfo.setProperties(properties);
}
} 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;
}
/**
* Retrieving the token from the http header
* @param webSocketConnectionProperties WebSocket connection information including http headers
* @return retrieved token
*/
private String getToken(Map<String, List<String>> webSocketConnectionProperties) {
String cookieString = webSocketConnectionProperties.get(COOKIE).get(0);
String[] properties = cookieString.split(COOKIE_KEYPAIR_SEPERATOR);
String token;
for (String keyValuePair: properties) {
if(TOKEN_IDENTIFIER.equals((keyValuePair.split(COOKIE_KEY_VALUE_SEPERATOR)[0]).trim())){
token = (keyValuePair.split(COOKIE_KEY_VALUE_SEPERATOR)[1]).trim();
return token;
}
}
log.error("WebSocket token should be specified in cookie");
return null;
}
/**
* Retrieving the token from the http session
* @param webSocketConnectionProperties WebSocket connection information including http headers
* @return retrieved token
*/
private String getTokenFromSession(Map<String, List<String>> webSocketConnectionProperties) {
String queryString = webSocketConnectionProperties.get(QUERY_STRING).get(0);
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;
}
}

@ -0,0 +1,174 @@
/*
* 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 org.wso2.carbon.device.mgt.extensions.remote.session.authentication.oauth;
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.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.pool.BasePoolableObjectFactory;
import org.wso2.carbon.device.mgt.extensions.remote.session.authentication.oauth.exception.OAuthTokenValidationException;
import org.wso2.carbon.device.mgt.extensions.remote.session.constants.RemoteSessionConstants;
import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionManagementException;
import org.wso2.carbon.device.mgt.extensions.remote.session.util.PropertyUtils;
import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.Map;
/**
* This follows object pool pattern to manage the stub for oauth validation service.
*/
public class OAuthTokenValidatorStubFactory extends BasePoolableObjectFactory {
private static final Log log = LogFactory.getLog(OAuthTokenValidatorStubFactory.class);
private HttpClient httpClient;
Map<String, String> tokenValidationProperties;
public OAuthTokenValidatorStubFactory(Map<String, String> globalProperties) {
this.tokenValidationProperties = globalProperties;
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(PropertyUtils.replaceProperty(tokenValidationProperties.get(
(RemoteSessionConstants.TOKEN_VALIDATION_ENDPOINT_URL)))
+ RemoteSessionConstants.TOKEN_VALIDATION_CONTEX);
stub = new OAuth2TokenValidationServiceStub(hostURL.toString());
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.get(RemoteSessionConstants.USERNAME);
String password = tokenValidationProperties.get(RemoteSessionConstants.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 notification 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);
}
} 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);
} catch (RemoteSessionManagementException e) {
throw new OAuthTokenValidationException("Invalid 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 notification) 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.get(
RemoteSessionConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST)));
params.setMaxTotalConnections(Integer.parseInt(tokenValidationProperties.get(
RemoteSessionConstants.MAXIMUM_TOTAL_HTTP_CONNECTION)));
HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
connectionManager.setParams(params);
return new HttpClient(connectionManager);
}
}

@ -0,0 +1,29 @@
/*
* 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 org.wso2.carbon.device.mgt.extensions.remote.session.authentication.oauth.exception;
/**
* This Exception will be thrown, when there any interference with token validation flow.
*/
public class OAuthTokenValidationException extends Exception {
public OAuthTokenValidationException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
}

@ -0,0 +1,49 @@
/*
* 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 org.wso2.carbon.device.mgt.extensions.remote.session.constants;
/**
* This holds the constants related to this feature
*/
public class RemoteSessionConstants {
public static final String SCOPE_IDENTIFIER = "scopes";
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 = "tokenValidationUrl";
public static final String TOKEN_VALIDATION_CONTEX = "/services/OAuth2TokenValidationService";
public static final String USERNAME = "username";
public static final String PASSWORD = "password";
public static final String DEVICE_ID = "deviceId";
public static final String DEVICE_TYPE = "deviceType";
public static final String REMOTE_CONNECT = "REMOTE_CONNECT";
public static final String QUERY_STRING = "queryString";
public static final String OPERATION_CODE = "operation_code";
public static final String REMOTE_SESSION_DEVICE_ENDPOINT_CONTEXT = "/remote/session/devices";
// Constants for remote session Connection modes
public enum CONNECTION_MODES {
CLIENT_MODE, DEVICE_MODE
}
private RemoteSessionConstants() {
}
}

@ -0,0 +1,125 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.extensions.remote.session.dto;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.extensions.remote.session.constants.RemoteSessionConstants;
import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionInvalidException;
import javax.websocket.CloseReason;
import javax.websocket.Session;
import java.io.IOException;
import java.nio.ByteBuffer;
public class RemoteSession {
private static final Log log = LogFactory.getLog(RemoteSession.class);
private String tenantDomain, operationId, deviceType, deviceId;
private Session peerSession;
private RemoteSessionConstants.CONNECTION_MODES connection_mode;
private final Object writeLockObject = new Object();
public RemoteSession(String tenantDomain, String deviceType, String deviceId, String operationId, RemoteSessionConstants.CONNECTION_MODES connection_mode) {
this.deviceType = deviceType;
this.deviceId = deviceId;
this.tenantDomain = tenantDomain;
this.operationId = operationId;
this.connection_mode = connection_mode;
}
public void sendMessageToPeer(String message) throws RemoteSessionInvalidException {
if (peerSession != null && peerSession.isOpen()) {
synchronized (writeLockObject) {
try {
peerSession.getBasicRemote().sendText(message);
} catch (IOException e) {
log.warn("Send data to session failed due to ", e);
}
}
} else {
throw new RemoteSessionInvalidException("Peer Session already closed ", new CloseReason
(CloseReason.CloseCodes.CANNOT_ACCEPT, "Peer Session already closed "));
}
}
public void sendMessageToPeer(byte[] message) throws RemoteSessionInvalidException {
if (peerSession != null && peerSession.isOpen()) {
synchronized (writeLockObject) {
try {
peerSession.getBasicRemote().sendBinary(ByteBuffer.wrap(message));
} catch (IOException e) {
log.warn("Send data to session failed due to ", e);
}
}
} else {
throw new RemoteSessionInvalidException("Peer Session already closed ", new CloseReason
(CloseReason.CloseCodes.CANNOT_ACCEPT, "Peer Session already closed "));
}
}
public Session getPeerSession() {
return peerSession;
}
public void setPeerSession(Session peerSession) {
this.peerSession = peerSession;
}
public String getTenantDomain() {
return tenantDomain;
}
public void setTenantDomain(String tenantDomain) {
this.tenantDomain = tenantDomain;
}
public String getOperationId() {
return operationId;
}
public void setOperationId(String operationId) {
this.operationId = operationId;
}
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public RemoteSessionConstants.CONNECTION_MODES getConnection_mode() {
return connection_mode;
}
public void setConnection_mode(RemoteSessionConstants.CONNECTION_MODES connection_mode) {
this.connection_mode = connection_mode;
}
}

@ -0,0 +1,52 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.extensions.remote.session.exception;
import javax.websocket.CloseReason;
/**
* This Exception will be thrown, when there any interference with Remote RemoteSession.
*/
public class RemoteSessionInvalidException extends Exception {
CloseReason closeReason;
public RemoteSessionInvalidException(String msg, CloseReason closeReason, Exception nestedEx) {
super(msg, nestedEx);
this.closeReason = closeReason;
}
public RemoteSessionInvalidException(String message, CloseReason closeReason, Throwable cause) {
super(message, cause);
this.closeReason = closeReason;
}
public RemoteSessionInvalidException(String msg, CloseReason closeReason) {
super(msg);
this.closeReason = closeReason;
}
public CloseReason getCloseReason() {
return closeReason;
}
public void setCloseReason(CloseReason closeReason) {
this.closeReason = closeReason;
}
}

@ -0,0 +1,45 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.extensions.remote.session.exception;
/**
* This Exception will be thrown, when there any interference with Remote RemoteSession.
*/
public class RemoteSessionManagementException extends Exception {
public RemoteSessionManagementException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
public RemoteSessionManagementException(String message, Throwable cause) {
super(message, cause);
}
public RemoteSessionManagementException(String msg) {
super(msg);
}
public RemoteSessionManagementException() {
super();
}
public RemoteSessionManagementException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,101 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.wso2.carbon.device.mgt.extensions.remote.session.internal;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService;
import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.extensions.remote.session.authentication.OAuthAuthenticator;
import org.wso2.carbon.device.mgt.extensions.remote.session.dto.RemoteSession;
import javax.websocket.Session;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class RemoteSessionManagementDataHolder {
private static RemoteSessionManagementDataHolder thisInstance = new RemoteSessionManagementDataHolder();
private DeviceManagementProviderService deviceManagementProviderService;
private DeviceAccessAuthorizationService deviceAccessAuthorizationService;
private boolean isEnabled;
private String serverUrl;
private OAuthAuthenticator oAuthAuthenticator;
private Map<String, Session> deviceRequestMap = new ConcurrentHashMap<String, Session>();
private Map<String, RemoteSession> sessionMap = new ConcurrentHashMap<String, RemoteSession>();
public static RemoteSessionManagementDataHolder getInstance() {
return thisInstance;
}
public DeviceManagementProviderService getDeviceManagementProviderService() {
return deviceManagementProviderService;
}
public void setDeviceManagementProviderService(DeviceManagementProviderService deviceManagementProviderService) {
this.deviceManagementProviderService = deviceManagementProviderService;
}
public DeviceAccessAuthorizationService getDeviceAccessAuthorizationService() {
return deviceAccessAuthorizationService;
}
public void setDeviceAccessAuthorizationService(DeviceAccessAuthorizationService deviceAccessAuthorizationService) {
this.deviceAccessAuthorizationService = deviceAccessAuthorizationService;
}
public OAuthAuthenticator getOauthAuthenticator() {
return oAuthAuthenticator;
}
public void setOauthAuthenticator(OAuthAuthenticator oAuthAuthenticator) {
this.oAuthAuthenticator = oAuthAuthenticator;
}
public Map<String, RemoteSession> getSessionMap() {
return sessionMap;
}
public void setSessionMap(Map<String, RemoteSession> sessionMap) {
this.sessionMap = sessionMap;
}
public Map<String, Session> getDeviceRequestMap() {
return deviceRequestMap;
}
public void setDeviceRequestMap(Map<String, Session> deviceRequestMap) {
this.deviceRequestMap = deviceRequestMap;
}
public boolean isEnabled() {
return isEnabled;
}
public void setEnabled(boolean enabled) {
isEnabled = enabled;
}
public String getServerUrl() {
return serverUrl;
}
public void setServerUrl(String serverUrl) {
this.serverUrl = serverUrl;
}
}

@ -0,0 +1,91 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.wso2.carbon.device.mgt.extensions.remote.session.internal;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.core.ServerStartupObserver;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.extensions.remote.session.RemoteSessionManagementService;
import org.wso2.carbon.device.mgt.extensions.remote.session.RemoteSessionManagementServiceImpl;
import org.wso2.carbon.device.mgt.extensions.remote.session.listener.RemoteSessionManagerStartupListener;
/**
* @scr.component name="RemoteSessionManagementServiceComponent" immediate="true"
* @scr.reference name="carbon.device.mgt.provider"
* interface="org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService"
* cardinality="1..1"
* policy="dynamic"
* bind="setDeviceManagementProviderService"
* unbind="unsetDeviceManagementProviderService"
* @scr.reference name="device.manager.service"
* interface="org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService"
* cardinality="0..n"
* policy="dynamic"
* bind="setDeviceAccessAuthorizationService"
* unbind="unsetDeviceAccessAuthorizationService"
*/
public class RemoteSessionManagementServiceComponent {
private static final Log log = LogFactory.getLog(RemoteSessionManagementServiceComponent.class);
@SuppressWarnings("unused")
protected void activate(ComponentContext componentContext) {
try {
BundleContext bundleContext = componentContext.getBundleContext();
bundleContext.registerService(ServerStartupObserver.class.getName(), new RemoteSessionManagerStartupListener(),
null);
bundleContext.registerService(RemoteSessionManagementService.class.getName(), new RemoteSessionManagementServiceImpl(),
null);
if (log.isDebugEnabled()) {
log.debug("Remote Session device access service implementation bundle has been successfully " +
"initialized");
}
} catch (Throwable e) {
log.error("Error occurred while initializing Remote Session device access service " +
"implementation bundle", e);
}
}
protected void deactivate(ComponentContext componentContext) {
//Do nothing
}
protected void setDeviceManagementProviderService(DeviceManagementProviderService deviceManagementProviderService) {
RemoteSessionManagementDataHolder.getInstance().setDeviceManagementProviderService(deviceManagementProviderService);
}
protected void unsetDeviceManagementProviderService(DeviceManagementProviderService deviceManagementProviderService) {
RemoteSessionManagementDataHolder.getInstance().setDeviceManagementProviderService(null);
}
protected void setDeviceAccessAuthorizationService(DeviceAccessAuthorizationService deviceAccessAuthorizationService) {
RemoteSessionManagementDataHolder.getInstance().setDeviceAccessAuthorizationService(deviceAccessAuthorizationService);
}
protected void unsetDeviceAccessAuthorizationService(DeviceAccessAuthorizationService deviceAccessAuthorizationService) {
RemoteSessionManagementDataHolder.getInstance().setDeviceManagementProviderService(null);
}
}

@ -0,0 +1,73 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.wso2.carbon.device.mgt.extensions.remote.session.listener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.core.ServerStartupObserver;
import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager;
import org.wso2.carbon.device.mgt.extensions.remote.session.authentication.OAuthAuthenticator;
import org.wso2.carbon.device.mgt.extensions.remote.session.constants.RemoteSessionConstants;
import org.wso2.carbon.device.mgt.extensions.remote.session.internal.RemoteSessionManagementDataHolder;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import java.util.HashMap;
import java.util.Map;
/**
* Startup listener is been used to make sure the reciever gets activated after the server start up to avoid
* Bundle not loading issues.
*/
public class RemoteSessionManagerStartupListener implements ServerStartupObserver {
private static final Log log = LogFactory.getLog(RemoteSessionManagerStartupListener.class);
@Override
public void completingServerStartup() {
}
@Override
public void completedServerStartup() {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, true);
try {
RemoteSessionManagementDataHolder.getInstance().setEnabled(DeviceConfigurationManager.getInstance()
.getDeviceManagementConfig().getRemoteSessionConfiguration().getIsEnabled());
RemoteSessionManagementDataHolder.getInstance().setServerUrl(DeviceConfigurationManager.getInstance()
.getDeviceManagementConfig().getRemoteSessionConfiguration().getRemoteSessionServerUrl());
Map<String, String> configProperties = new HashMap<>();
configProperties.put(RemoteSessionConstants.TOKEN_VALIDATION_ENDPOINT_URL, "https://localhost:9443");
configProperties.put(RemoteSessionConstants.USERNAME,"admin");
configProperties.put(RemoteSessionConstants.PASSWORD,"admin");
configProperties.put(RemoteSessionConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST,"2");
configProperties.put(RemoteSessionConstants.MAXIMUM_TOTAL_HTTP_CONNECTION,"100");
OAuthAuthenticator oAuthAuthenticator= new OAuthAuthenticator();
oAuthAuthenticator.init(configProperties);
RemoteSessionManagementDataHolder.getInstance().setOauthAuthenticator(oAuthAuthenticator);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}

@ -0,0 +1,45 @@
/*
* 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 org.wso2.carbon.device.mgt.extensions.remote.session.util;
import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionManagementException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PropertyUtils {
//This method is only used if the mb features are within DAS.
public static String replaceProperty(String urlWithPlaceholders) throws RemoteSessionManagementException {
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);
} else {
throw new RemoteSessionManagementException("System property - " + sysPropertyName
+ " is not defined, hence cannot resolve : " + urlWithPlaceholders);
}
}
return urlWithPlaceholders;
}
}

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2014, 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>extensions</artifactId>
<version>4.0.35-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>remote-session-extension</artifactId>
<packaging>pom</packaging>
<name>WSO2 Carbon - Remote Sessions Extension</name>
<url>http://wso2.org</url>
<modules>
<module>org.wso2.carbon.device.mgt.extensions.remote.session</module>
<module>org.wso2.carbon.device.mgt.extensions.remote.session.endpoint</module>
</modules>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.7.2</version>
<executions>
<execution>
<id>generate-scr-scrdescriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

@ -1,6 +1,8 @@
{{unit "cdmf.unit.lib.qrcode"}}
{{unit "cdmf.unit.device.type.qr-modal"}}
{{#zone "topCss"}}
{{css "css/terminal.css"}}
{{/zone}}
{{#if deviceFound}}
{{#if isAuthorized}}
@ -82,6 +84,7 @@
</li>
<li><a data-toggle="tab" href="#app">Applications</a></li>
<li><a data-toggle="tab" href="#policy">Policy Compliance</a></li>
<li><a data-toggle="tab" href="#remote-session">Remote Session</a></li>
{{/zone}}
{{#zone "device-view-tab-injected-conents"}}
@ -113,6 +116,86 @@
<div id="policy-list-container">
</div>
</div>
<div id="remote-session" class="tab-pane fade" data-remote-session-uri="{{remoteSessionEndpoint}}">
<div class="remote-session-container">
<div class="tab-actions">
<div class="action-btn-container">
<div class="action-btn show filter">
<a href="javascript:void(0);" id="btn-connect-device">
<i class="fw fw-mobile"></i> Connect to Device
</a>
<a href="javascript:void(0);" class="hidden" id="btn-close-remote-session">
<i class="fw fw-mobile"></i> Close Session
</a>
<div id="loading-remote-session" class="hidden">
<i class="fw fw-sync fw-spin fw-2x"></i>
<label id="lbl-remote-session-status"></label>
</div>
</div>
</div>
</div>
<div id="remote-session-operations" class="hidden">
<div id="remote-session-operations-bar">
<ul class="nav nav-pills">
<li class="active">
<a href="#1a" data-toggle="tab">
<span>Shell</span>
</a>
</li>
<li><a href="#2a" data-toggle="tab">
<span>Logcat</span>
</a>
</li>
<li><a href="#3a" data-toggle="tab">
<span>Screen Share</span>
</a>
</li>
</ul>
</div>
<div id="remote-session-operations-center" class="tab-content clearfix">
<div class="tab-pane active" id="1a">
<div id="loading-terminal" class="hidden">
<i class="fw fw-loader fw-spin"></i>
<span>Executing shell command...</span>
</div>
<textarea id="shell-command" class="terminal" autocomplete="on"
placeholder="Write your shell command here and press Enter..."
required></textarea>
<textarea id="shell-response" class="terminal" readonly rows="20"></textarea>
</div>
<div class="tab-pane" id="2a">
<a href="javascript:void(0);" id="btn-refresh-logCat">
<i class="fw fw-refresh"></i> Refresh Logcat
</a>
<div id="loading-logcat" class="hidden">
<i class="fw fw-loader fw-spin"></i>
<span>Fetching Logcat....</span>
</div>
<textarea id="logcat-response" readonly rows="30"></textarea>
</div>
<div class="tab-pane" id="3a">
<button id="btn-start-screen" type="button" class="btn btn-success">
Start
</button>
<div id="loading-screen" class="hidden">
<i class="fw fw-loader fw-spin"></i>
<span>Start Screen Sharing....</span>
</div>
<div id="remote-control-pannel" style="overflow: auto" class="hidden">
<canvas id="canvas"></canvas>
</div>
<button id="btn-stop-screen" type="button" class="btn btn-danger hidden">
Stop
</button>
</div>
</div>
</div>
</div>
</div>
<div class="panel panel-default visible-xs-block" role="tabpanel"
id="policy_compliance_tab">
<div class="panel-heading visible-xs collapsed" id="policy_compliance">
@ -274,5 +357,7 @@
type="text/x-handlebars-template"></script>
<!--suppress HtmlUnknownTarget -->
{{js "js/device-detail.js"}}
{{js "js/remote-session.js"}}
{{js "js/jquery.touchSwipe.min.js"}}
{{/if}}
{{/zone}}

@ -22,6 +22,8 @@ function onRequest(context) {
var deviceId = request.getParameter("id");
var deviceViewData = {};
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
var carbonServer = require("carbon").server;
var constants = require("/app/modules/constants.js")
if (deviceType && deviceId) {
var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"];
@ -182,6 +184,23 @@ function onRequest(context) {
} else if (response["status"] == "notFound") {
deviceViewData["deviceFound"] = false;
}
var remoteSessionEndpoint = devicemgtProps["remoteSessionWSURL"].replace("https", "wss");
var jwtService = carbonServer.osgiService('org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService');
var jwtClient = jwtService.getJWTClient();
var encodedClientKeys = session.get(constants["ENCODED_TENANT_BASED_WEB_SOCKET_CLIENT_CREDENTIALS"]);
var token = "";
if (encodedClientKeys) {
var tokenUtil = require("/app/modules/oauth/token-handler-utils.js")["utils"];
var resp = tokenUtil.decode(encodedClientKeys).split(":");
var tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username,"default", {});
if (tokenPair) {
token = tokenPair.accessToken;
}
}
remoteSessionEndpoint = remoteSessionEndpoint + "/remote/session/clients/" + deviceType + "/" + deviceId +
"?websocketToken=" + token
deviceViewData["remoteSessionEndpoint"] = remoteSessionEndpoint;
} else {
deviceViewData["deviceFound"] = false;
}

@ -0,0 +1,25 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
.terminal {
background-color: #1f1d1d;
border: 1px solid #000;
color: #39ef39;
padding: 8px;
font-family: courier new;
}

@ -0,0 +1,261 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var rs_websocket;
var rs_WebSocketURL;
var shellMessageField = document.getElementById('shell-command');
var shellResponseField = document.getElementById('shell-response');
WebSocket.prototype.set_opened = function () {
this._opened = true;
};
WebSocket.prototype.set_closed = function () {
this._opened = false;
};
WebSocket.prototype.get_opened = function () {
return this._opened || false;
};
var remoteSessionWebSocketOnOpen = function () {
rs_websocket.set_opened();
};
var remoteSessionWebSocketOnMessage = function (message) {
$('#lbl-remote-session-status').text('Server Connected...');
$('#remote-session-operations').removeClass('hidden');
$('#loading-remote-session').addClass('hidden');
$('#btn-close-remote-session').removeClass('hidden');
$('#shell-terminal').removeClass('hidden');
if (typeof message.data !== 'string') {
$('#loading-screen').addClass('hidden');
var url = URL.createObjectURL(event.data);
var img = new Image;
img.onload = function() {
var ctx = document.getElementById("canvas").getContext('2d');
ctx.canvas.height = this.height;
ctx.canvas.width =this.width;
ctx.drawImage(this, 0, 0);
URL.revokeObjectURL(url);
}
img.src = url;
} else {
var json = $.parseJSON(message.data);
if (json.code == "REMOTE_SHELL") {
if(json.status != "NEW"){
$('#loading-terminal').addClass('hidden');
}
if(json.operationResponse != null ){
var shellResponse = $("#shell-response");
shellResponse.val(shellResponse.val() + json.operationResponse);
}
} else if (json.code == "REMOTE_LOGCAT") {
if(json.status != "NEW"){
$('#btn-refresh-logCat').removeClass('hidden');
$('#loading-logcat').addClass('hidden');
}
if(json.operationResponse != null ){
var logcatResponse = $("#logcat-response");
logcatResponse.val(logcatResponse.val() + json.operationResponse);
}
} else if (json.code == "REMOTE_CONNECT") {
$('#loading-terminal').addClass('hidden');
if(json.operationResponse != null ){
var shellResponse = $("#shell-response");
shellResponse.val(json.operationResponse);
}
} else {
console.log("Message type not supported.");
}
}
};
var remoteSessionWebSocketOnClose = function (e) {
$('#btn-connect-device').removeClass('hidden');
$('#remote-session-operations').addClass('hidden');
$('#btn-close-remote-session').addClass('hidden');
$('#loading-screen').addClass('hidden');
$('#btn-stop-screen').addClass('hidden');
$('#btn-start-screen').removeClass('hidden');
if (rs_websocket.get_opened()) {
noty({text: 'Connection lost with Remote Session server!!', type: 'error'});
}
location.reload();
};
var remoteSessionWebSocketOnError = function (err) {
//if (!rs_websocket.get_opened()) return;
$('#btn-connect-device').removeClass('hidden');
$('#remote-session-operations').addClass('hidden');
$('#btn-close-remote-session').addClass('hidden');
noty({text: 'Something went wrong when trying to connect to <b>' + rs_WebSocketURL + '<b/>', type: 'error'});
rs_websocket.close();
location.reload();
};
$("#btn-connect-device").click(function() {
$('#loading-remote-session').removeClass('hidden');
$('#btn-connect-device').addClass('hidden');
$('#lbl-remote-session-status').text('Connecting to Server...');
initializeRemoteSession();
});
$("#btn-close-remote-session").click(function() {
// Close the WebSocket.
rs_websocket.close();
rs_websocket.set_closed();
$('#btn-connect-device').removeClass('hidden');
$('#remote-session-operations').addClass('hidden');
$('#btn-close-remote-session').addClass('hidden');
$('#loading-screen').addClass('hidden');
$('#btn-stop-screen').addClass('hidden');
$('#btn-start-screen').removeClass('hidden');
location.reload();
});
$("#btn-refresh-logCat").click(function() {
$('#loading-logcat').removeClass('hidden');
$('#btn-refresh-logCat').addClass('hidden');
var message = new Object();
message.code ="REMOTE_LOGCAT";
// Send the message through the WebSocket.
rs_websocket.send(JSON.stringify(message));
// Clear out the message field.
$("#logcat-response").val("") ;
});
function initializeRemoteSessionWebSocket() {
rs_websocket = new WebSocket(rs_WebSocketURL);
rs_websocket.onopen = remoteSessionWebSocketOnOpen;
rs_websocket.onmessage = remoteSessionWebSocketOnMessage;
rs_websocket.onclose = remoteSessionWebSocketOnClose;
rs_websocket.onerror = remoteSessionWebSocketOnError;
}
function initializeRemoteSession() {
rs_WebSocketURL = $("#remote-session").data("remote-session-uri");
if(rs_WebSocketURL != null) {
initializeRemoteSessionWebSocket();
window.onbeforeunload = function () {
rs_websocket.close();
}
$('#lbl-remote-session-status').text('Waiting on device to connect...');
} else {
noty({text: 'Remote Session endpoint connection Failed!', type: 'error'});
$('#btn-connect-device').removeClass('hidden');
$('#loading-remote-session').addClass('hidden');
}
}
$("#shell-command").keyup(function(event){
if(event.keyCode == 13){
var message = new Object();
message.code ="REMOTE_SHELL";
message.payload = $("#shell-command").val();
// Send the message through the WebSocket.
rs_websocket.send(JSON.stringify(message));
// Clear out the message field.
$("#shell-command").val("") ;
$("#shell-response").val("") ;
$('#loading-terminal').removeClass('hidden');
}
});
$("#btn-start-screen").click(function() {
$('#loading-screen').removeClass('hidden');
$('#btn-start-screen').addClass('hidden');
$('#remote-control-pannel').removeClass('hidden');
$('#btn-stop-screen').removeClass('hidden');
var message = new Object();
message.code ="REMOTE_SCREEN";
message.payload = "start";
// Send the message through the WebSocket.
rs_websocket.send(JSON.stringify(message));
});
$("#btn-stop-screen").click(function() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
$('#loading-screen').addClass('hidden');
$('#remote-control-pannel').addClass('hidden');
$('#btn-stop-screen').addClass('hidden');
$('#btn-start-screen').removeClass('hidden');
context.clearRect(0, 0, canvas.width, canvas.height);
var message = new Object();
message.code ="REMOTE_SCREEN";
message.payload = "stop";
// Send the message through the WebSocket.
rs_websocket.send(JSON.stringify(message));
});
$(function() {
//Enable swiping...
$("#canvas").swipe({
//Generic swipe handler for all directions
swipe: function(event, direction, distance, duration, fingerCount, fingerData) {
switch (direction) {
case "right":
$("#canvas")[0].getContext('2d').fillText("You swiped x:" + event.pageX + " y: " + event.pageY + " RIGHT", 10, 90)
break;
case "left":
$("#canvas")[0].getContext('2d').fillText("You swiped x:" + event.pageX + " y: " + event.pageY + " LEFT", 10, 90)
break;
case "up":
$("#canvas")[0].getContext('2d').fillText("You swiped x:" + event.pageX + " y: " + event.pageY + " UP", 10, 90)
break;
case "down":
$("#canvas")[0].getContext('2d').fillText("You swiped x:" + event.pageX + " y: " + event.pageY + " DOWN", 10, 90)
break;
default:
$("#canvas")[0].getContext('2d').fillText("You swiped x:" + event.pageX + " y: " + event.pageY, 10, 90)
break;
}
},
//Default is 75px, set to 0 for demo so any distance triggers swipe
threshold: 0
});
});

@ -0,0 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>extensions-feature</artifactId>
<version>4.0.35-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.remote.session.feature</artifactId>
<packaging>pom</packaging>
<version>4.0.35-SNAPSHOT</version>
<name>WSO2 Carbon - Remote Session Manager</name>
<url>http://wso2.org</url>
<description>This feature contains the core bundles required iot Remote Sessions</description>
<dependencies>
<dependency>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.extensions.remote.session</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jaxrs</artifactId>
<version>${io.github.openfeign.version}</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-gson</artifactId>
<version>${io.github.openfeign.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.extensions.remote.session.endpoint</artifactId>
<version>${carbon.devicemgt.plugins.version}</version>
<type>war</type>
<overWrite>true</overWrite>
<outputDirectory>
${project.build.directory}/maven-shared-archive-resources/webapps/
</outputDirectory>
<destFileName>remote-session.war</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>src/main/resources</outputDirectory>
<resources>
<resource>
<directory>resources</directory>
<includes>
<include>build.properties</include>
<include>p2.inf</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.wso2.maven</groupId>
<artifactId>carbon-p2-plugin</artifactId>
<version>${carbon.p2.plugin.version}</version>
<executions>
<execution>
<id>p2-feature-generation</id>
<phase>package</phase>
<goals>
<goal>p2-feature-gen</goal>
</goals>
<configuration>
<id>org.wso2.carbon.device.mgt.remote.session</id>
<propertiesFile>../../../features/etc/feature.properties</propertiesFile>
<adviceFile>
<properties>
<propertyDef>org.wso2.carbon.p2.category.type:server</propertyDef>
<propertyDef>org.eclipse.equinox.p2.type.group:true</propertyDef>
</properties>
</adviceFile>
<bundles>
<bundleDef>
org.wso2.carbon.devicemgt-plugins:org.wso2.carbon.device.mgt.extensions.remote.session:${carbon.devicemgt.plugins.version}
</bundleDef>
<bundleDef>
org.wso2.carbon.identity.inbound.auth.oauth2:org.wso2.carbon.identity.oauth.stub:${identity.inbound.auth.oauth.version}
</bundleDef>
<bundleDef>
io.github.openfeign:feign-core:${io.github.openfeign.version}
</bundleDef>
<bundleDef>
io.github.openfeign:feign-slf4j:${io.github.openfeign.version}
</bundleDef>
<bundleDef>
io.github.openfeign:feign-gson:${io.github.openfeign.version}
</bundleDef>
</bundles>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,19 @@
#
# 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.
#
custom = true

@ -0,0 +1,3 @@
instructions.configure = \
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.remote.session_${feature.version}/webapps/,target:${installFolder}/../../deployment/server/webapps/,overwrite:true);\
Loading…
Cancel
Save