removed DCR, added global configuration values for input and output adapter

revert-dabc3590
ayyoob 8 years ago
parent 2e8279b61a
commit ccaf47112a

@ -21,10 +21,8 @@
<from eventAdapterType="oauth-mqtt">
<property name="topic">carbon.super/android_sense/+/data</property>
<property name="username">admin</property>
<property name="password">admin</property>
<property name="contentValidator">org.wso2.carbon.device.mgt.input.adapter.mqtt.util.MQTTContentValidator</property>
<property name="contentTransformer">default</property>
<property name="dcrUrl">https://${iot.core.host}:${iot.core.https.port}/dynamic-client-web/register</property>
<property name="url">tcp://${mqtt.broker.host}:${mqtt.broker.port}</property>
<property name="cleanSession">true</property>
</from>
<mapping customMapping="disable" type="json"/>

@ -18,14 +18,7 @@
-->
<eventReceiver name="arduino_receiver" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver">
<from eventAdapterType="oauth-http">
<property name="maximumHttpConnectionPerHost">2</property>
<property name="username">admin</property>
<property name="contentValidator">org.wso2.carbon.device.mgt.input.adapter.http.util.HTTPContentValidator</property>
<property name="contentTransformer">default</property>
<property name="transports">all</property>
<property name="maximumTotalHttpConnection">100</property>
<property name="tokenValidationEndpointUrl">https://localhost:${dcr.endpoint.port}/services/OAuth2TokenValidationService</property>
<property name="password">admin</property>
</from>
<mapping customMapping="disable" type="json"/>
<to streamName="org.wso2.iot.arduino" version="1.0.0"/>

@ -20,10 +20,8 @@
<from eventAdapterType="oauth-mqtt">
<property name="topic">carbon.super/raspberrypi/+/temperature</property>
<property name="username">admin</property>
<property name="password">admin</property>
<property name="contentValidator">org.wso2.carbon.device.mgt.input.adapter.mqtt.util.MQTTContentValidator</property>
<property name="contentTransformer">default</property>
<property name="dcrUrl">https://${iot.core.host}:${iot.core.https.port}/dynamic-client-web/register</property>
<property name="url">tcp://${mqtt.broker.host}:${mqtt.broker.port}</property>
<property name="cleanSession">true</property>
</from>
<mapping customMapping="disable" type="json"/>

@ -20,10 +20,8 @@
<from eventAdapterType="oauth-mqtt">
<property name="topic">carbon.super/virtual_firealarm/+/temperature</property>
<property name="username">admin</property>
<property name="password">admin</property>
<property name="contentValidator">org.wso2.carbon.device.mgt.input.adapter.mqtt.util.MQTTContentValidator</property>
<property name="contentTransformer">default</property>
<property name="dcrUrl">https://${iot.core.host}:${iot.core.https.port}/dynamic-client-web/register</property>
<property name="url">tcp://${mqtt.broker.host}:${mqtt.broker.port}</property>
<property name="cleanSession">true</property>
</from>
<mapping customMapping="disable" type="json"/>

@ -186,7 +186,7 @@ public final class HTTPEventAdapter implements InputEventAdapter {
"HttpService not available, Error in registering endpoint " + endpoint);
}
httpService.registerServlet(endpoint, new HTTPMessageServlet(eventAdaptorListener, tenantId,
eventAdapterConfiguration),
eventAdapterConfiguration, globalProperties),
new Hashtable(), httpService.createDefaultHttpContext());
} catch (ServletException | NamespaceException e) {
throw new InputEventAdapterRuntimeException("Error in registering endpoint " + endpoint, e);

@ -75,45 +75,6 @@ public class HTTPEventAdapterFactory extends InputEventAdapterFactory {
exposedTransportsProperty.setDefaultValue(HTTPEventAdapterConstants.ALL);
propertyList.add(exposedTransportsProperty);
// OAUTH validation endpoint admin service username
Property username = new Property(HTTPEventAdapterConstants.USERNAME);
username.setRequired(true);
username.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.USERNAME));
username.setHint(resourceBundle.getString(HTTPEventAdapterConstants.USERNAME_HINT));
propertyList.add(username);
// OAUTH validation endpoint admin service password
Property password = new Property(HTTPEventAdapterConstants.PASSWORD);
password.setRequired(true);
password.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.PASSWORD));
password.setHint(resourceBundle.getString(HTTPEventAdapterConstants.PASSWORD_HINT));
propertyList.add(password);
// OAUTH validation endpoint
Property tokenValidationEndpoint = new Property(HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL);
tokenValidationEndpoint.setRequired(true);
tokenValidationEndpoint.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL));
tokenValidationEndpoint.setHint(resourceBundle.getString(HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL_HINT));
propertyList.add(tokenValidationEndpoint);
Property maximumHttpConnectionPerHost = new Property(HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST);
maximumHttpConnectionPerHost.setRequired(true);
maximumHttpConnectionPerHost.setDisplayName(resourceBundle.getString(
HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST));
maximumHttpConnectionPerHost.setHint(resourceBundle.getString(
HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST_HINT));
maximumHttpConnectionPerHost.setDefaultValue(HTTPEventAdapterConstants.MAX_HTTP_CONNECTION);
propertyList.add(maximumHttpConnectionPerHost);
Property maxTotalHttpConnection = new Property(HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION);
maxTotalHttpConnection.setRequired(true);
maxTotalHttpConnection.setDisplayName(resourceBundle.getString(
HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION));
maxTotalHttpConnection.setHint(resourceBundle.getString(
HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION_HINT));
maxTotalHttpConnection.setDefaultValue(HTTPEventAdapterConstants.MAX_TOTAL_HTTP_CONNECTION);
propertyList.add(maxTotalHttpConnection);
//Content Validator details
Property contentValidator = new Property(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME);
contentValidator.setDisplayName(

@ -60,7 +60,8 @@ public class HTTPMessageServlet extends HttpServlet {
private static OAuthAuthenticator oAuthAuthenticator;
public HTTPMessageServlet(InputEventAdapterListener eventAdaptorListener, int tenantId,
InputEventAdapterConfiguration eventAdapterConfiguration) {
InputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
this.eventAdaptorListener = eventAdaptorListener;
this.tenantId = tenantId;
this.exposedTransports = eventAdapterConfiguration.getProperties().get(
@ -107,7 +108,7 @@ public class HTTPMessageServlet extends HttpServlet {
}
jwtAuthenticator = new JWTAuthenticator();
oAuthAuthenticator = new OAuthAuthenticator(eventAdapterConfiguration);
oAuthAuthenticator = new OAuthAuthenticator(globalProperties);
}
@Override

@ -36,6 +36,7 @@ import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import javax.servlet.http.HttpServletRequest;
import java.rmi.RemoteException;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -51,8 +52,8 @@ public class OAuthAuthenticator {
private static final String AUTHORIZATION_HEADER = "Authorization";
private static Log log = LogFactory.getLog(OAuthAuthenticator.class);
public OAuthAuthenticator(InputEventAdapterConfiguration eventAdapterConfiguration) {
this.stubs = new GenericObjectPool(new OAuthTokenValidaterStubFactory(eventAdapterConfiguration));
public OAuthAuthenticator(Map<String, String> globalProperties) {
this.stubs = new GenericObjectPool(new OAuthTokenValidaterStubFactory(globalProperties));
}
public AuthenticationInfo authenticate(HttpServletRequest req) {

@ -34,7 +34,6 @@ import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.log4j.Logger;
import org.wso2.carbon.core.util.Utils;
import org.wso2.carbon.device.mgt.input.adapter.http.oauth.exception.OAuthTokenValidationException;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.device.mgt.input.adapter.http.util.HTTPEventAdapterConstants;
import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
@ -42,6 +41,7 @@ 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.
@ -49,11 +49,11 @@ import java.security.GeneralSecurityException;
public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
private static final Logger log = Logger.getLogger(OAuthTokenValidaterStubFactory.class);
private HttpClient httpClient;
InputEventAdapterConfiguration eventAdapterConfiguration;
Map<String, String> globalProperties;
public OAuthTokenValidaterStubFactory(InputEventAdapterConfiguration eventAdapterConfiguration) {
this.eventAdapterConfiguration = eventAdapterConfiguration;
public OAuthTokenValidaterStubFactory(Map<String, String> globalProperties) {
this.globalProperties = globalProperties;
this.httpClient = createHttpClient();
}
@ -92,9 +92,10 @@ public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
private OAuth2TokenValidationServiceStub generateStub() throws OAuthTokenValidationException {
OAuth2TokenValidationServiceStub stub;
try {
URL hostURL = new URL(Utils.replaceSystemProperty(eventAdapterConfiguration.getProperties().get(
HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL)));
if (hostURL != null) {
URL hostURL = new URL(Utils.replaceSystemProperty(globalProperties.get(
HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL)
+ HTTPEventAdapterConstants.TOKEN_VALIDATION_POST_FIX));
if (hostURL != null) {
stub = new OAuth2TokenValidationServiceStub(hostURL.toString());
if (stub != null) {
ServiceClient client = stub._getServiceClient();
@ -104,10 +105,8 @@ public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
HttpTransportProperties.Authenticator auth =
new HttpTransportProperties.Authenticator();
auth.setPreemptiveAuthentication(true);
String username = eventAdapterConfiguration.getProperties().get(HTTPEventAdapterConstants
.USERNAME);
String password = eventAdapterConfiguration.getProperties().get(HTTPEventAdapterConstants
.PASSWORD);
String username = globalProperties.get(HTTPEventAdapterConstants.USERNAME);
String password = globalProperties.get(HTTPEventAdapterConstants.PASSWORD);
auth.setPassword(username);
auth.setUsername(password);
Options options = client.getOptions();
@ -151,8 +150,7 @@ public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
*/
private EasySSLProtocolSocketFactory createProtocolSocketFactory() throws OAuthTokenValidationException {
try {
EasySSLProtocolSocketFactory easySSLPSFactory = new EasySSLProtocolSocketFactory();
return easySSLPSFactory;
return new EasySSLProtocolSocketFactory();
} catch (IOException e) {
String errorMsg = "Failed to initiate EasySSLProtocolSocketFactory.";
throw new OAuthTokenValidationException(errorMsg, e);
@ -170,9 +168,9 @@ public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
*/
private HttpClient createHttpClient() {
HttpConnectionManagerParams params = new HttpConnectionManagerParams();
params.setDefaultMaxConnectionsPerHost(Integer.parseInt(eventAdapterConfiguration.getProperties().get(
HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST)));
params.setMaxTotalConnections(Integer.parseInt(eventAdapterConfiguration.getProperties().get(
params.setDefaultMaxConnectionsPerHost(Integer.parseInt(globalProperties.get(
HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST)));
params.setMaxTotalConnections(Integer.parseInt(globalProperties.get(
HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION)));
HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
connectionManager.setParams(params);

@ -51,8 +51,8 @@ public final class HTTPEventAdapterConstants {
public static final String MAXIMUM_TOTAL_HTTP_CONNECTION_HINT = "maximumTotalHttpConnection.hint";
public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST = "maximumHttpConnectionPerHost";
public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST_HINT = "maximumHttpConnectionPerHost.hint";
public static final String TOKEN_VALIDATION_ENDPOINT_URL = "tokenValidationEndpointUrl";
public static final String TOKEN_VALIDATION_ENDPOINT_URL_HINT = "tokenValidationEndpointUrl.hint";
public static final String TOKEN_VALIDATION_ENDPOINT_URL = "keymanagerUrl";
public static final String TOKEN_VALIDATION_POST_FIX = "/services/OAuth2TokenValidationService";
public static final String USERNAME = "username";
public static final String USERNAME_HINT = "username.hint";
public static final String PASSWORD = "password";

@ -22,16 +22,6 @@ http.usage.tips_mid1=/endpoints/&lt;event_receiver_name&gt</i></br>&nbsp;&nbsp;<
http.usage.tips_mid2=/endpoints/&lt;event_receiver_name&gt;</i></br></br>For other tenants:</br>&nbsp;&nbsp;<i>http://localhost:
http.usage.tips_mid3=/endpoints/t/&lt;tenant_domain&gt;/&lt;event_receiver_name&gt;</i></br>&nbsp;&nbsp;<i>https://localhost:
http.usage.tips_postfix=/endpoints/t/&lt;tenant_domain&gt;/&lt;event_receiver_name&gt;</i>
tokenValidationEndpointUrl=tokenEndpointUrl
tokenValidationEndpointUrl.hint=OAUTH Token Validation Endpoint
username=username
username.hint=username of the user to connect to the admin services
password=password
password.hint=password of the user to connect to the admin services.
maximumTotalHttpConnection=maximumTotalHttpConnection
maximumTotalHttpConnection.hint=Maximum Total connection to be made with the endpoint
maximumHttpConnectionPerHost=maximumHttpConnectionPerHost
maximumHttpConnectionPerHost.hint=Maximum Http connection per host.
contentValidator=contentValidator
contentValidator.hint=Class Name of the content Validation or 'default' to set default class, required to implement (if required)
contentTransformer=contentTransformer

@ -60,10 +60,6 @@
<groupId>com.googlecode.json-simple.wso2</groupId>
<artifactId>json-simple</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
@ -128,7 +124,6 @@
org.apache.http.client.methods;version="${httpclient.version.range}",
org.apache.http.impl.client;version="${httpclient.version.range}",
org.json.simple.*,
org.wso2.carbon.identity.jwt.client.extension.*,
com.jayway.jsonpath.*
</Import-Package>
<DynamicImport-Package>*</DynamicImport-Package>

@ -53,29 +53,13 @@ public class MQTTEventAdapter implements InputEventAdapter {
public void init(InputEventAdapterListener eventAdapterListener) throws InputEventAdapterException {
this.eventAdapterListener = eventAdapterListener;
try {
int keepAlive;
//If global properties are available those will be assigned else constant values will be assigned
if (globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_KEEP_ALIVE) != null) {
keepAlive = Integer.parseInt((globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_KEEP_ALIVE)));
} else {
keepAlive = MQTTEventAdapterConstants.ADAPTER_CONF_DEFAULT_KEEP_ALIVE;
}
mqttBrokerConnectionConfiguration = new MQTTBrokerConnectionConfiguration(
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_URL),
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME),
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES),
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL),
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION),
keepAlive,
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME),
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME)
);
mqttAdapterListener = new MQTTAdapterListener(mqttBrokerConnectionConfiguration,
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC),
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID),
eventAdapterListener, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
mqttBrokerConnectionConfiguration = new MQTTBrokerConnectionConfiguration(eventAdapterConfiguration
,globalProperties);
mqttAdapterListener = new MQTTAdapterListener(mqttBrokerConnectionConfiguration
,eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC)
,eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID)
,eventAdapterListener, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
} catch (Throwable t) {
throw new InputEventAdapterException(t.getMessage(), t);
}

@ -59,16 +59,10 @@ public class MQTTEventAdapterFactory extends InputEventAdapterFactory {
//Broker Url
Property brokerUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
brokerUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL));
brokerUrl.setRequired(true);
brokerUrl.setRequired(false);
brokerUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL_HINT));
propertyList.add(brokerUrl);
//DCR endpoint details
Property dcrUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL);
dcrUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL));
dcrUrl.setRequired(false);
dcrUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL_HINT));
propertyList.add(dcrUrl);
//Content Validator details
Property contentValidator = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME);
@ -84,10 +78,18 @@ public class MQTTEventAdapterFactory extends InputEventAdapterFactory {
Property userName = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME);
userName.setDisplayName(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME));
userName.setRequired(false);
userName.setRequired(true);
userName.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME_HINT));
propertyList.add(userName);
//Broker Password
Property password = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD);
userName.setDisplayName(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD));
userName.setRequired(true);
userName.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD_HINT));
propertyList.add(password);
//Broker Required Scopes.
Property scopes = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES);
scopes.setDisplayName(

@ -23,13 +23,9 @@ import org.osgi.service.component.ComponentContext;
import org.osgi.service.http.HttpService;
import org.wso2.carbon.device.mgt.input.adapter.mqtt.MQTTEventAdapterFactory;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterFactory;
import org.wso2.carbon.user.core.service.RealmService;
/**
* @scr.component name="input.iot.mqtt.AdapterService.component" immediate="true"
* @scr.reference name="user.realmservice.default"
* interface="org.wso2.carbon.user.core.service.RealmService" cardinality="1..1"
* policy="dynamic" bind="setRealmService" unbind="unsetRealmService"
*/
public class InputAdapterServiceComponent {
@ -48,14 +44,6 @@ public class InputAdapterServiceComponent {
}
}
protected void setRealmService(RealmService realmService) {
InputAdapterServiceDataHolder.registerRealmService(realmService);
}
protected void unsetRealmService(RealmService realmService) {
InputAdapterServiceDataHolder.registerRealmService(null);
}
protected void setHttpService(HttpService httpService) {
InputAdapterServiceDataHolder.registerHTTPService(httpService);
}

@ -15,28 +15,17 @@
package org.wso2.carbon.device.mgt.input.adapter.mqtt.internal;
import org.osgi.service.http.HttpService;
import org.wso2.carbon.user.core.service.RealmService;
/**
* common place to hold some OSGI service references.
*/
public final class InputAdapterServiceDataHolder {
private static RealmService realmService;
private static HttpService httpService;
private InputAdapterServiceDataHolder() {
}
public static void registerRealmService(
RealmService realmService) {
InputAdapterServiceDataHolder.realmService = realmService;
}
public static RealmService getRealmService() {
return realmService;
}
public static void registerHTTPService(
HttpService httpService) {
InputAdapterServiceDataHolder.httpService = httpService;

@ -17,13 +17,18 @@
*/
package org.wso2.carbon.device.mgt.input.adapter.mqtt.util;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence;
import org.json.simple.JSONObject;
@ -39,9 +44,6 @@ import org.wso2.carbon.device.mgt.input.adapter.extension.DefaultContentValidato
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterListener;
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterRuntimeException;
import org.wso2.carbon.device.mgt.input.adapter.mqtt.exception.MQTTContentInitializationException;
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import java.io.IOException;
import java.net.MalformedURLException;
@ -49,7 +51,9 @@ import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MQTTAdapterListener implements MqttCallback, Runnable {
@ -144,16 +148,14 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
}
public void startListener() throws MqttException {
if (this.mqttBrokerConnectionConfiguration.getBrokerUsername() != null &&
if (this.mqttBrokerConnectionConfiguration.getUsername() != null &&
this.mqttBrokerConnectionConfiguration.getDcrUrl() != null) {
String username = this.mqttBrokerConnectionConfiguration.getBrokerUsername();
String username = this.mqttBrokerConnectionConfiguration.getUsername();
String password = this.mqttBrokerConnectionConfiguration.getPassword();
String dcrUrlString = this.mqttBrokerConnectionConfiguration.getDcrUrl();
String scopes = this.mqttBrokerConnectionConfiguration.getBrokerScopes();
//getJWT Client Parameters.
if (dcrUrlString != null && !dcrUrlString.isEmpty()) {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true);
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(username);
try {
URL dcrUrl = new URL(dcrUrlString);
HttpClient httpClient = MQTTUtil.getHttpClient(dcrUrl.getProtocol());
@ -163,11 +165,15 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
registrationProfile.setGrantType(MQTTEventAdapterConstants.GRANT_TYPE);
registrationProfile.setOwner(username);
registrationProfile.setTokenScope(MQTTEventAdapterConstants.TOKEN_SCOPE);
registrationProfile.setApplicationType(MQTTEventAdapterConstants.APPLICATION_TYPE);
registrationProfile.setClientName(username + "_" + tenantId);
registrationProfile.setClientName(MQTTEventAdapterConstants.APPLICATION_NAME_PREFIX
+ mqttBrokerConnectionConfiguration.getAdapterName() + "_" + tenantId);
String jsonString = registrationProfile.toJSON();
StringEntity requestEntity = new StringEntity(jsonString, ContentType.APPLICATION_JSON);
postMethod.setEntity(requestEntity);
String basicAuth = getBase64Encode(username, password);
postMethod.setHeader(new BasicHeader(MQTTEventAdapterConstants.AUTHORIZATION_HEADER_NAME,
MQTTEventAdapterConstants.AUTHORIZATION_HEADER_VALUE_PREFIX +
basicAuth));
HttpResponse httpResponse = httpClient.execute(postMethod);
if (httpResponse != null) {
String response = MQTTUtil.getResponseString(httpResponse);
@ -177,16 +183,10 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
JSONObject jsonPayload = (JSONObject) jsonParser.parse(response);
String clientId = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_ID);
String clientSecret = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_SECRET);
JWTClientManagerService jwtClientManagerService = MQTTUtil.getJWTClientManagerService();
AccessTokenInfo accessTokenInfo = jwtClientManagerService.getJWTClient().getAccessToken(
clientId, clientSecret, username, scopes);
connectionOptions.setUserName(accessTokenInfo.getAccessToken());
connectionOptions.setUserName(getToken(clientId, clientSecret));
}
} catch (ParseException e) {
String msg = "error occurred while parsing client credential payload";
log.error(msg, e);
} catch (JWTClientException e) {
String msg = "error occurred while parsing the response from JWT Client";
String msg = "error occurred while parsing generating token for the adapter";
log.error(msg, e);
}
}
@ -194,8 +194,6 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
log.error("Invalid dcrUrl : " + dcrUrlString);
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | IOException e) {
log.error("Failed to create an https connection.", e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}
@ -287,4 +285,39 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
public boolean isConnectionInitialized() {
return connectionInitialized;
}
private String getToken(String clientId, String clientSecret)
throws IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, ParseException {
URL tokenEndpoint = new URL(mqttBrokerConnectionConfiguration.getTokenUrl());
HttpClient httpClient = MQTTUtil.getHttpClient(tokenEndpoint.getProtocol());
HttpPost postMethod = new HttpPost(tokenEndpoint.toString());
List<NameValuePair> nameValuePairs = new ArrayList<>();
nameValuePairs.add(new BasicNameValuePair(MQTTEventAdapterConstants.GRANT_TYPE_PARAM_NAME,
MQTTEventAdapterConstants.PASSWORD_GRANT_TYPE));
nameValuePairs.add(new BasicNameValuePair(MQTTEventAdapterConstants.PASSWORD_GRANT_TYPE_USERNAME,
mqttBrokerConnectionConfiguration.getUsername()));
nameValuePairs.add(new BasicNameValuePair(MQTTEventAdapterConstants.PASSWORD_GRANT_TYPE_PASSWORD,
mqttBrokerConnectionConfiguration.getPassword()));
String scopes = mqttBrokerConnectionConfiguration.getBrokerScopes();
if (scopes != null && !scopes.isEmpty()) {
nameValuePairs.add(new BasicNameValuePair(MQTTEventAdapterConstants.PASSWORD_GRANT_TYPE_SCOPES, scopes));
}
postMethod.setEntity(new UrlEncodedFormEntity(nameValuePairs));
postMethod.addHeader("Authorization", "Basic " + getBase64Encode(clientId, clientSecret));
postMethod.addHeader("Content-Type", "application/x-www-form-urlencoded");
HttpResponse httpResponse = httpClient.execute(postMethod);
String response = MQTTUtil.getResponseString(httpResponse);
if (log.isDebugEnabled()) {
log.debug(response);
}
JSONParser jsonParser = new JSONParser();
JSONObject jsonObject = (JSONObject) jsonParser.parse(response);
return (String) jsonObject.get(MQTTEventAdapterConstants.ACCESS_TOKEN_GRANT_TYPE_PARAM_NAME);
}
private String getBase64Encode(String key, String value) {
return new String(Base64.encodeBase64((key + ":" + value).getBytes()));
}
}

@ -17,28 +17,38 @@
*/
package org.wso2.carbon.device.mgt.input.adapter.mqtt.util;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterException;
import java.util.Map;
/**
* This holds the configurations related to MQTT Broker.
*/
public class MQTTBrokerConnectionConfiguration {
private String brokerUsername = null;
private String username = null;
private String password = null;
private String brokerScopes = null;
private boolean cleanSession = true;
private int keepAlive;
private String brokerUrl;
private String dcrUrl;
private String tokenUrl;
private String contentValidatorClassName;
private String contentTransformerClassName;
private String adapterName;
public String getBrokerScopes() {
return brokerScopes;
}
public String getBrokerUsername() {
return brokerUsername;
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public boolean isCleanSession() {
@ -65,21 +75,44 @@ public class MQTTBrokerConnectionConfiguration {
return contentTransformerClassName;
}
public MQTTBrokerConnectionConfiguration(String brokerUrl, String brokerUsername, String brokerScopes,
String dcrUrl, String cleanSession, int keepAlive,
String contentValidatorClassName, String contentTransformerClassName) throws InputEventAdapterException {
this.brokerUsername = brokerUsername;
this.brokerScopes = brokerScopes;
public String getTokenUrl() {
return tokenUrl;
}
public String getAdapterName() {
return adapterName;
}
public MQTTBrokerConnectionConfiguration(InputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) throws InputEventAdapterException {
adapterName = eventAdapterConfiguration.getName();
this.username = eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME);
this.password = eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD);
this.brokerScopes = eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES);
if (brokerScopes == null) {
this.brokerScopes = MQTTEventAdapterConstants.EMPTY_STRING;
}
this.brokerUrl = PropertyUtils.replaceMqttProperty(brokerUrl);
this.dcrUrl = PropertyUtils.replaceMqttProperty(dcrUrl);
this.contentValidatorClassName = contentValidatorClassName;
if (cleanSession != null) {
this.cleanSession = Boolean.parseBoolean(cleanSession);
String url = eventAdapterConfiguration .getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
if (url == null || url.isEmpty()) {
url = globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
}
this.brokerUrl = PropertyUtils.replaceMqttProperty(url);
this.dcrUrl = PropertyUtils
.replaceMqttProperty(globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL));
this.tokenUrl = PropertyUtils
.replaceMqttProperty(globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_TOKEN_URL));
this.contentValidatorClassName = eventAdapterConfiguration.getProperties()
.get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME);
this.cleanSession = Boolean.parseBoolean(eventAdapterConfiguration.getProperties()
.get(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION));
//If global properties are available those will be assigned else constant values will be assigned
if (globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_KEEP_ALIVE) != null) {
keepAlive = Integer.parseInt((globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_KEEP_ALIVE)));
} else {
keepAlive = MQTTEventAdapterConstants.ADAPTER_CONF_DEFAULT_KEEP_ALIVE;
}
this.keepAlive = keepAlive;
this.contentTransformerClassName = contentTransformerClassName;
this.contentTransformerClassName = eventAdapterConfiguration.getProperties()
.get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME);
}
}

@ -27,10 +27,13 @@ public class MQTTEventAdapterConstants {
public static final String ADAPTER_CONF_URL = "url";
public static final String ADAPTER_CONF_USERNAME = "username";
public static final String ADAPTER_CONF_USERNAME_HINT = "username.hint";
public static final String ADAPTER_CONF_PASSWORD = "password";
public static final String ADAPTER_CONF_PASSWORD_HINT = "password.hint";
public static final String ADAPTER_CONF_SCOPES = "scopes";
public static final String ADAPTER_CONF_SCOPES_HINT = "scopes.hint";
public static final String ADAPTER_CONF_URL_HINT = "url.hint";
public static final String ADAPTER_CONF_DCR_URL = "dcrUrl";
public static final String ADAPTER_CONF_TOKEN_URL = "tokenUrl";
public static final String ADAPTER_CONF_DCR_URL_HINT = "dcrUrl.hint";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME = "contentValidator";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT = "contentValidator.hint";
@ -49,9 +52,10 @@ public class MQTTEventAdapterConstants {
public static final int RECONNECTION_PROGRESS_FACTOR = 2;
public static final String EMPTY_STRING = "";
public static final String GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer refresh_token";
public static final String GRANT_TYPE_PARAM_NAME = "grant_type";
public static final String GRANT_TYPE = "password refresh_token";
public static final String TOKEN_SCOPE = "production";
public static final String APPLICATION_TYPE = "device";
public static final String APPLICATION_NAME_PREFIX = "InputAdapter_";
public static final String CLIENT_ID = "client_id";
public static final String CLIENT_SECRET = "client_secret";
public static final String CLIENT_NAME = "client_name";
@ -62,4 +66,12 @@ public class MQTTEventAdapterConstants {
public static final String DEVICE_ID_JSON_PATH = "event.metaData.deviceId";
public static final String DEVICE_TYPE_JSON_PATH = "event.metaData.deviceId";
public static final int DEVICE_ID_TOPIC_HIERARCHY_INDEX = 2;
public static final String AUTHORIZATION_HEADER_NAME = "Authorization";
public static final String AUTHORIZATION_HEADER_VALUE_PREFIX = "Basic ";
public static final String PASSWORD_GRANT_TYPE = "password";
public static final String PASSWORD_GRANT_TYPE_USERNAME = "username";
public static final String PASSWORD_GRANT_TYPE_PASSWORD = "password";
public static final String PASSWORD_GRANT_TYPE_SCOPES = "scopes";
public static final String ACCESS_TOKEN_GRANT_TYPE_PARAM_NAME = "access_token";
}

@ -27,8 +27,6 @@ import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import java.io.BufferedReader;
import java.io.IOException;
@ -84,16 +82,4 @@ public class MQTTUtil {
}
}
}
public static JWTClientManagerService getJWTClientManagerService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
JWTClientManagerService jwtClientManagerService =
(JWTClientManagerService) ctx.getOSGiService(JWTClientManagerService.class, null);
if (jwtClientManagerService == null) {
String msg = "JWT management service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return jwtClientManagerService;
}
}

@ -20,9 +20,11 @@ topic=Topic
topic.hint=Topic subscribed
clientId=Client Id
clientId.hint=client identifier is used by the server to identify a client when it reconnects, It used for durable subscriptions or reliable delivery of messages is required.
url=Broker Url
url=Broker Url (Not required), If it is not provided then it will connect to the default broker.
username=Username
username.hint=Username of the broker (if required)
password=Password
password.hint=Password of the user for the broker (if required)
scopes=Scopes
scopes.hint=Scopes required to connect to broker (if required)
dcrUrl=dcrUrl

@ -61,10 +61,6 @@
<groupId>com.googlecode.json-simple.wso2</groupId>
<artifactId>json-simple</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
@ -122,7 +118,10 @@
org.osgi.framework,
org.osgi.service.component,
org.wso2.carbon.context,
org.wso2.carbon.identity.jwt.client.extension.*
org.apache.commons.codec.binary,
org.apache.http.client.entity,
org.apache.http.message,
org.apache.commons.ssl
</Import-Package>
</instructions>
</configuration>

@ -118,19 +118,7 @@ public class MQTTEventAdapter implements OutputEventAdapter {
@Override
public void connect() {
MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration =
new MQTTBrokerConnectionConfiguration(eventAdapterConfiguration.getStaticProperties()
.get(MQTTEventAdapterConstants.ADAPTER_CONF_URL),
eventAdapterConfiguration.getStaticProperties()
.get(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME),
eventAdapterConfiguration.getStaticProperties()
.get(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL),
eventAdapterConfiguration.getStaticProperties()
.get(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES),
connectionKeepAliveInterval,
eventAdapterConfiguration.getStaticProperties()
.get(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION)
);
new MQTTBrokerConnectionConfiguration(eventAdapterConfiguration, globalProperties);
String clientId = eventAdapterConfiguration.getStaticProperties().get(
MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID);
qos = eventAdapterConfiguration.getStaticProperties().get(MQTTEventAdapterConstants.ADAPTER_MESSAGE_QOS);

@ -50,7 +50,7 @@ public class MQTTEventAdapterFactory extends OutputEventAdapterFactory {
//Broker Url
Property brokerUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
brokerUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL));
brokerUrl.setRequired(true);
brokerUrl.setRequired(false);
brokerUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL_HINT));
//Broker Username
@ -59,11 +59,11 @@ public class MQTTEventAdapterFactory extends OutputEventAdapterFactory {
userName.setRequired(true);
userName.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME_HINT));
//Broker dcr URL
Property dcrUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL);
dcrUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL));
dcrUrl.setRequired(true);
dcrUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL_HINT));
//Broker Password
Property password = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD);
password.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD));
password.setRequired(true);
password.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD_HINT));
//Broker Connection Scopes
Property scopes = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES);
@ -95,10 +95,10 @@ public class MQTTEventAdapterFactory extends OutputEventAdapterFactory {
staticPropertyList.add(brokerUrl);
staticPropertyList.add(userName);
staticPropertyList.add(dcrUrl);
staticPropertyList.add(scopes);
staticPropertyList.add(clearSession);
staticPropertyList.add(qos);
staticPropertyList.add(password);
return staticPropertyList;
}

@ -19,11 +19,16 @@ package org.wso2.carbon.device.mgt.output.adapter.mqtt.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.ssl.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
@ -36,9 +41,6 @@ import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.event.output.adapter.core.exception.ConnectionUnavailableException;
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterRuntimeException;
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import java.io.IOException;
import java.net.MalformedURLException;
@ -46,6 +48,8 @@ import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
/**
* MQTT publisher related configuration initialization and publishing capabilties are implemented here.
@ -77,10 +81,8 @@ public class MQTTAdapterPublisher {
MqttConnectOptions connectionOptions = new MqttConnectOptions();
connectionOptions.setCleanSession(cleanSession);
connectionOptions.setKeepAliveInterval(keepAlive);
if (mqttBrokerConnectionConfiguration.getBrokerUsername() != null) {
connectionOptions.setUserName(getToken(mqttBrokerConnectionConfiguration.getBrokerUsername(),
mqttBrokerConnectionConfiguration.getDcrUrl(),
mqttBrokerConnectionConfiguration.getScopes()));
if (mqttBrokerConnectionConfiguration.getUsername() != null) {
connectionOptions.setUserName(getToken());
connectionOptions.setPassword(MQTTEventAdapterConstants.DEFAULT_PASSWORD.toCharArray());
}
// Construct an MQTT blocking mode client
@ -139,7 +141,11 @@ public class MQTTAdapterPublisher {
}
}
private String getToken(String username, String dcrUrlString, String scopes) {
private String getToken() {
String username = this.mqttBrokerConnectionConfiguration.getUsername();
String password = this.mqttBrokerConnectionConfiguration.getPassword();
String dcrUrlString = this.mqttBrokerConnectionConfiguration.getDcrUrl();
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
if (dcrUrlString != null && !dcrUrlString.isEmpty()) {
try {
@ -147,32 +153,34 @@ public class MQTTAdapterPublisher {
HttpClient httpClient = MQTTUtil.getHttpClient(dcrUrl.getProtocol());
HttpPost postMethod = new HttpPost(dcrUrlString);
RegistrationProfile registrationProfile = new RegistrationProfile();
registrationProfile.setCallbackUrl(MQTTEventAdapterConstants.DEFAULT_CALLBACK);
registrationProfile.setCallbackUrl(MQTTEventAdapterConstants.EMPTY_STRING);
registrationProfile.setGrantType(MQTTEventAdapterConstants.GRANT_TYPE);
registrationProfile.setOwner(username);
registrationProfile.setTokenScope(MQTTEventAdapterConstants.TOKEN_SCOPE);
registrationProfile.setApplicationType(MQTTEventAdapterConstants.APPLICATION_TYPE);
registrationProfile.setClientName(username + "_" + tenantId);
registrationProfile.setClientName(MQTTEventAdapterConstants.APPLICATION_NAME_PREFIX
+ mqttBrokerConnectionConfiguration.getAdapterName() + "_" + tenantId);
String jsonString = registrationProfile.toJSON();
StringEntity requestEntity = new StringEntity(jsonString, ContentType.APPLICATION_JSON);
postMethod.setEntity(requestEntity);
String basicAuth = getBase64Encode(username, password);
postMethod.setHeader(new BasicHeader(MQTTEventAdapterConstants.AUTHORIZATION_HEADER_NAME,
MQTTEventAdapterConstants.AUTHORIZATION_HEADER_VALUE_PREFIX +
basicAuth));
HttpResponse httpResponse = httpClient.execute(postMethod);
String response = MQTTUtil.getResponseString(httpResponse);
try {
JSONParser jsonParser = new JSONParser();
JSONObject jsonPayload = (JSONObject) jsonParser.parse(response);
String clientId = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_ID);
String clientSecret = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_SECRET);
JWTClientManagerService jwtClientManagerService = MQTTUtil.getJWTClientManagerService();
AccessTokenInfo accessTokenInfo = jwtClientManagerService.getJWTClient().getAccessToken(
clientId, clientSecret, username, scopes);
return accessTokenInfo.getAccessToken();
} catch (ParseException e) {
String msg = "error occurred while parsing client credential payload";
throw new OutputEventAdapterRuntimeException(msg, e);
} catch (JWTClientException e) {
String msg = "error occurred while parsing the response from JWT Client";
throw new OutputEventAdapterRuntimeException(msg, e);
if (httpResponse != null) {
String response = MQTTUtil.getResponseString(httpResponse);
try {
if (response != null) {
JSONParser jsonParser = new JSONParser();
JSONObject jsonPayload = (JSONObject) jsonParser.parse(response);
String clientId = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_ID);
String clientSecret = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_SECRET);
getToken(clientId, clientSecret);
}
} catch (ParseException e) {
String msg = "error occurred while parsing generating token for the adapter";
log.error(msg, e);
}
}
} catch (MalformedURLException e) {
throw new OutputEventAdapterRuntimeException("Invalid dcrUrl : " + dcrUrlString);
@ -183,4 +191,39 @@ public class MQTTAdapterPublisher {
throw new OutputEventAdapterRuntimeException("Invalid configuration for mqtt publisher");
}
private String getToken(String clientId, String clientSecret)
throws IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, ParseException {
URL tokenEndpoint = new URL(mqttBrokerConnectionConfiguration.getTokenUrl());
HttpClient httpClient = MQTTUtil.getHttpClient(tokenEndpoint.getProtocol());
HttpPost postMethod = new HttpPost(tokenEndpoint.toString());
List<NameValuePair> nameValuePairs = new ArrayList<>();
nameValuePairs.add(new BasicNameValuePair(MQTTEventAdapterConstants.GRANT_TYPE_PARAM_NAME,
MQTTEventAdapterConstants.PASSWORD_GRANT_TYPE));
nameValuePairs.add(new BasicNameValuePair(MQTTEventAdapterConstants.PASSWORD_GRANT_TYPE_USERNAME,
mqttBrokerConnectionConfiguration.getUsername()));
nameValuePairs.add(new BasicNameValuePair(MQTTEventAdapterConstants.PASSWORD_GRANT_TYPE_PASSWORD,
mqttBrokerConnectionConfiguration.getPassword()));
String scopes = mqttBrokerConnectionConfiguration.getScopes();
if (scopes != null && !scopes.isEmpty()) {
nameValuePairs.add(new BasicNameValuePair(MQTTEventAdapterConstants.PASSWORD_GRANT_TYPE_SCOPES, scopes));
}
postMethod.setEntity(new UrlEncodedFormEntity(nameValuePairs));
postMethod.addHeader("Authorization", "Basic " + getBase64Encode(clientId, clientSecret));
postMethod.addHeader("Content-Type", "application/x-www-form-urlencoded");
HttpResponse httpResponse = httpClient.execute(postMethod);
String response = MQTTUtil.getResponseString(httpResponse);
if (log.isDebugEnabled()) {
log.debug(response);
}
JSONParser jsonParser = new JSONParser();
JSONObject jsonObject = (JSONObject) jsonParser.parse(response);
return (String) jsonObject.get(MQTTEventAdapterConstants.ACCESS_TOKEN_GRANT_TYPE_PARAM_NAME);
}
private String getBase64Encode(String key, String value) {
return new String(Base64.encodeBase64((key + ":" + value).getBytes()));
}
}

@ -17,14 +17,25 @@
*/
package org.wso2.carbon.device.mgt.output.adapter.mqtt.util;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterConfiguration;
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
import java.util.Map;
public class MQTTBrokerConnectionConfiguration {
private String brokerUsername;
private String adapterName;
private String username;
private String password;
private String dcrUrl;
private String scopes;
private String brokerUrl;
private String tokenUrl;
private boolean cleanSession = true;
private int keepAlive;
public String getTokenUrl() {
return tokenUrl;
}
public String getDcrUrl() {
return dcrUrl;
@ -34,8 +45,12 @@ public class MQTTBrokerConnectionConfiguration {
return scopes;
}
public String getBrokerUsername() {
return brokerUsername;
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public boolean isCleanSession() {
@ -50,15 +65,35 @@ public class MQTTBrokerConnectionConfiguration {
return keepAlive;
}
public MQTTBrokerConnectionConfiguration(String brokerUrl, String brokerUsername,
String dcrUrl, String scopes, int keepAlive, String cleanSession) {
this.brokerUsername = brokerUsername;
this.dcrUrl = dcrUrl;
this.scopes = scopes;
this.brokerUrl = brokerUrl;
this.keepAlive = keepAlive;
if (cleanSession != null) {
this.cleanSession = Boolean.parseBoolean(cleanSession);
public String getAdapterName() {
return adapterName;
}
public MQTTBrokerConnectionConfiguration(OutputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
adapterName = eventAdapterConfiguration.getName();
this.username = eventAdapterConfiguration.getStaticProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME);
this.password = eventAdapterConfiguration.getStaticProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD);
String url = eventAdapterConfiguration .getStaticProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
if (url == null || url.isEmpty()) {
url = globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
}
this.brokerUrl = PropertyUtils.replaceMqttProperty(url);
this.dcrUrl = PropertyUtils
.replaceMqttProperty(globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL));
this.tokenUrl = PropertyUtils
.replaceMqttProperty(globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_TOKEN_URL));
this.scopes = eventAdapterConfiguration.getStaticProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES);
if (scopes == null) {
this.scopes = MQTTEventAdapterConstants.EMPTY_STRING;
}
this.cleanSession = Boolean.parseBoolean(eventAdapterConfiguration.getStaticProperties()
.get(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION));
//If global properties are available those will be assigned else constant values will be assigned
if (globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_KEEP_ALIVE) != null) {
keepAlive = Integer.parseInt((globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_KEEP_ALIVE)));
} else {
keepAlive = MQTTEventAdapterConstants.ADAPTER_CONF_DEFAULT_KEEP_ALIVE;
}
}

@ -27,8 +27,10 @@ public final class MQTTEventAdapterConstants {
public static final String ADAPTER_CONF_URL = "url";
public static final String ADAPTER_CONF_USERNAME = "username";
public static final String ADAPTER_CONF_USERNAME_HINT = "username.hint";
public static final String ADAPTER_CONF_PASSWORD = "password";
public static final String ADAPTER_CONF_PASSWORD_HINT = "password.hint";
public static final String ADAPTER_CONF_DCR_URL = "dcrUrl";
public static final String ADAPTER_CONF_DCR_URL_HINT = "dcrUrl.hint";
public static final String ADAPTER_CONF_TOKEN_URL = "keymanagerUrl";
public static final String ADAPTER_CONF_SCOPES = "scopes";
public static final String ADAPTER_CONF_SCOPES_HINT = "scopes.hint";
public static final String ADAPTER_CONF_URL_HINT = "url.hint";
@ -41,6 +43,9 @@ public final class MQTTEventAdapterConstants {
public static final String ADAPTER_TEMP_DIRECTORY_NAME = "java.io.tmpdir";
public static final String ADAPTER_CONF_CLIENTID = "clientId";
public static final String ADAPTER_CONF_CLIENTID_HINT = "clientId.hint";
public static final String EMPTY_STRING = "";
public static final String ADAPTER_CONF_KEEP_ALIVE = "keepAlive";
public static final int ADAPTER_CONF_DEFAULT_KEEP_ALIVE = 60000;
public static final int DEFAULT_MIN_THREAD_POOL_SIZE = 8;
public static final int DEFAULT_MAX_THREAD_POOL_SIZE = 100;
@ -53,9 +58,19 @@ public final class MQTTEventAdapterConstants {
public static final String DEFAULT_CALLBACK = "";
public static final String DEFAULT_PASSWORD = "";
public static final String GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer refresh_token";
public static final String GRANT_TYPE = "grant_type";
public static final String TOKEN_SCOPE = "production";
public static final String APPLICATION_TYPE = "device";
public static final String APPLICATION_NAME_PREFIX = "OutputAdapter_";
public static final String CLIENT_ID = "client_id";
public static final String CLIENT_SECRET = "client_secret";
public static final String AUTHORIZATION_HEADER_NAME = "Authorization";
public static final String AUTHORIZATION_HEADER_VALUE_PREFIX = "Basic ";
public static final String PASSWORD_GRANT_TYPE = "password";
public static final String PASSWORD_GRANT_TYPE_USERNAME = "username";
public static final String PASSWORD_GRANT_TYPE_PASSWORD = "password";
public static final String PASSWORD_GRANT_TYPE_SCOPES = "scopes";
public static final String ACCESS_TOKEN_GRANT_TYPE_PARAM_NAME = "access_token";
public static final String GRANT_TYPE_PARAM_NAME = "grant_type";
}

@ -28,7 +28,6 @@ import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import java.io.BufferedReader;
import java.io.IOException;
@ -85,15 +84,4 @@ public class MQTTUtil {
}
}
public static JWTClientManagerService getJWTClientManagerService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
JWTClientManagerService jwtClientManagerService =
(JWTClientManagerService) ctx.getOSGiService(JWTClientManagerService.class, null);
if (jwtClientManagerService == null) {
String msg = "JWT management service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return jwtClientManagerService;
}
}

@ -0,0 +1,40 @@
/*
* 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.output.adapter.mqtt.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class PropertyUtils {
//This method is only used if the mb features are within DAS.
static String replaceMqttProperty(String urlWithPlaceholders) {
String regex = "\\$\\{(.*?)\\}";
Pattern pattern = Pattern.compile(regex);
Matcher matchPattern = pattern.matcher(urlWithPlaceholders);
while (matchPattern.find()) {
String sysPropertyName = matchPattern.group(1);
String sysPropertyValue = System.getProperty(sysPropertyName);
if (sysPropertyValue != null && !sysPropertyName.isEmpty()) {
urlWithPlaceholders = urlWithPlaceholders.replaceAll("\\$\\{(" + sysPropertyName + ")\\}", sysPropertyValue);
}
}
return urlWithPlaceholders;
}
}

@ -18,13 +18,13 @@
topic=Topic
url=Broker Url
url.hint=MQTT broker url
username=Username
username.hint=Username of the broker
dcrUrl=dcrUrl
dcrUrl.hint=Dynamic Client Registration Url
password=Password
password.hint=Password to connect to the server.
scopes=scopes
scopes.hint=Scopes that required to connect with the broker.
url.hint=MQTT broker url
cleanSession=Clean Session
cleanSession.hint=Persist topic subscriptions and ack positions across client sessions
keepAlive=Keep Alive (In seconds)

@ -18,6 +18,13 @@
*/
package org.wso2.carbon.device.mgt.output.adapter.websocket;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authentication.Authenticator;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.Authorizer;
import org.wso2.carbon.device.mgt.output.adapter.websocket.service.WebsocketValidationService;
import org.wso2.carbon.device.mgt.output.adapter.websocket.service.WebsocketValidationServiceImpl;
import org.wso2.carbon.device.mgt.output.adapter.websocket.util.UIEventAdapterConstants;
import org.wso2.carbon.event.output.adapter.core.MessageType;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapter;
@ -38,6 +45,9 @@ public class UIEventAdapterFactory extends OutputEventAdapterFactory {
private ResourceBundle resourceBundle = ResourceBundle.getBundle("org.wso2.carbon.device.mgt.output.adapter.websocket.i18n" +
".Resources", Locale.getDefault());
private BundleContext bundleContext;
private boolean isAuthInitialized = false;
private static final Log log = LogFactory.getLog(UIEventAdapter.class);
public UIEventAdapterFactory() {
}
@ -74,7 +84,53 @@ public class UIEventAdapterFactory extends OutputEventAdapterFactory {
@Override
public OutputEventAdapter createEventAdapter(OutputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
if (!isAuthInitialized) {
initializeAuthenticatorAndAuthorizor(globalProperties);
}
return new UIEventAdapter(eventAdapterConfiguration, globalProperties);
}
public BundleContext getBundleContext() {
return bundleContext;
}
public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
private void initializeAuthenticatorAndAuthorizor (Map<String, String> globalProperties) {
if (!isAuthInitialized) {
synchronized (UIEventAdapterFactory.class) {
if (!isAuthInitialized) {
try {
WebsocketValidationServiceImpl websocketValidationService =
new WebsocketValidationServiceImpl();
String authenticatorClassName = globalProperties.get(
UIEventAdapterConstants.AUTHENTICATOR_CLASS);
String authorizerClassName = globalProperties.get(UIEventAdapterConstants.AUTHORIZER_CLASS);
if (authenticatorClassName != null && !authenticatorClassName.isEmpty()) {
Class<? extends Authenticator> authenticatorClass = Class.forName(authenticatorClassName)
.asSubclass(Authenticator.class);
Authenticator authenticator = authenticatorClass.newInstance();
websocketValidationService.setAuthenticator(authenticator);
}
if (authorizerClassName != null && !authorizerClassName.isEmpty()) {
Class<? extends Authorizer> authorizerClass = Class.forName(authorizerClassName)
.asSubclass(Authorizer.class);
Authorizer authorizer = authorizerClass.newInstance();
websocketValidationService.setAuthorizer(authorizer);
}
bundleContext.registerService(
WebsocketValidationService.class.getName(), websocketValidationService, null);
isAuthInitialized = true;
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
log.error("Failed to initialize the class authentication and authorization given " +
"in the websocket validation configuration.", e);
}
}
}
}
}
}

@ -22,9 +22,14 @@ import java.util.Map;
*/
public interface Authenticator {
/**
* This is used to initialize the authenticator
* @param globalProperties related to the output adapter
*/
void init(Map<String, String> globalProperties);
/**
* Check whether the client is authenticated to connect.
* @param session user object.
* @return AuthenticationInfo which contains authentication client information.
*/
AuthenticationInfo isAuthenticated(Map<String, List<String>> webSocketConnectionProperties);

@ -20,8 +20,13 @@ import java.util.List;
import java.util.Map;
public class OAuthAuthenticator implements Authenticator {
OAuthTokenValdiator oAuthTokenValdiator;
@Override
public void init(Map<String, String> globalProperties) {
oAuthTokenValdiator = new OAuthTokenValdiator(globalProperties);
}
public AuthenticationInfo isAuthenticated(Map<String, List<String>> webSocketConnectionProperties) {
return OAuthTokenValdiator.getInstance().validateToken(webSocketConnectionProperties);
return oAuthTokenValdiator.validateToken(webSocketConnectionProperties);
}
}

@ -20,24 +20,18 @@ 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.output.adapter.websocket.authentication.AuthenticationInfo;
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.Property;
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.WebsocketConfig;
import org.wso2.carbon.device.mgt.output.adapter.websocket.constants.WebsocketConstants;
import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO;
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO_OAuth2AccessToken;
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationResponseDTO;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.utils.CarbonUtils;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import java.io.File;
import java.io.IOException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* This acts as a contract point for OAuth token validation.
@ -47,8 +41,6 @@ public class OAuthTokenValdiator {
private static String cookie;
private GenericObjectPool stubs;
private static Log log = LogFactory.getLog(OAuthTokenValdiator.class);
private static final String WEBSOCKET_CONFIG_LOCATION =
CarbonUtils.getEtcCarbonConfigDirPath() + File.separator + "websocket-validation.properties";
private static final String COOKIE_KEY_VALUE_SEPERATOR = "=";
private static final String COOKIE_KEYPAIR_SEPERATOR = ";";
private static final String COOKIE = "cookie";
@ -56,25 +48,9 @@ public class OAuthTokenValdiator {
private static final String TOKEN_IDENTIFIER = "websocket-token";
private static OAuthTokenValdiator oAuthTokenValdiator;
public static OAuthTokenValdiator getInstance() {
if (oAuthTokenValdiator == null) {
synchronized (OAuthTokenValdiator.class) {
if (oAuthTokenValdiator == null) {
oAuthTokenValdiator = new OAuthTokenValdiator();
}
}
}
return oAuthTokenValdiator;
}
private OAuthTokenValdiator() {
try {
Properties properties = getWebSocketConfig();
this.stubs = new GenericObjectPool(new OAuthTokenValidaterStubFactory(properties));
} catch (IOException e) {
log.error("Failed to parse the web socket org.wso2.carbon.device.mgt.output.adapter.websocket.config file " +
WEBSOCKET_CONFIG_LOCATION, e);
}
public OAuthTokenValdiator(Map<String, String> globalProperties) {
this.stubs = new GenericObjectPool(new OAuthTokenValidaterStubFactory(globalProperties));
}
/**
@ -174,19 +150,6 @@ public class OAuthTokenValdiator {
return authenticationInfo;
}
/**
* Retrieve JWT configs from registry.
*/
private Properties getWebSocketConfig() throws IOException {
Properties properties = new Properties();
List<Property> propertyList = WebsocketConfig.getInstance().getWebsocketValidationConfigs().getAuthenticator()
.getProperties().getProperty();
for (Property property : propertyList) {
properties.put(property.getName(), property.getValue());
}
return properties;
}
/**
* Retrieving the token from the http header
* @param webSocketConnectionProperties WebSocket connection information including http headers

@ -35,13 +35,15 @@ import org.apache.commons.logging.LogFactory;
import org.apache.commons.pool.BasePoolableObjectFactory;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authentication.oauth.exception.OAuthTokenValidationException;
import org.wso2.carbon.device.mgt.output.adapter.websocket.constants.WebsocketConstants;
import org.wso2.carbon.device.mgt.output.adapter.websocket.util.PropertyUtils;
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
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.Properties;
import java.util.Map;
/**
* This follows object pool pattern to manage the stub for oauth validation service.
@ -49,11 +51,11 @@ import java.util.Properties;
public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
private static final Log log = LogFactory.getLog(OAuthTokenValidaterStubFactory.class);
private HttpClient httpClient;
Properties tokenValidationProperties;
Map<String, String> tokenValidationProperties;
public OAuthTokenValidaterStubFactory(Properties tokenValidationProperties) {
this.tokenValidationProperties = tokenValidationProperties;
public OAuthTokenValidaterStubFactory(Map<String, String> globalProperties) {
this.tokenValidationProperties = globalProperties;
this.httpClient = createHttpClient();
}
@ -91,51 +93,46 @@ public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
*/
private OAuth2TokenValidationServiceStub generateStub() throws OAuthTokenValidationException {
OAuth2TokenValidationServiceStub stub;
try {
URL hostURL = new URL(tokenValidationProperties.getProperty((WebsocketConstants.TOKEN_VALIDATION_ENDPOINT_URL)));
if (hostURL != null) {
stub = new OAuth2TokenValidationServiceStub(hostURL.toString());
if (stub != null) {
ServiceClient client = stub._getServiceClient();
client.getServiceContext().getConfigurationContext().setProperty(
HTTPConstants.CACHED_HTTP_CLIENT, httpClient);
try {
URL hostURL = new URL(PropertyUtils.replaceMqttProperty(tokenValidationProperties.get(
(WebsocketConstants.TOKEN_VALIDATION_ENDPOINT_URL)))
+ WebsocketConstants.TOKEN_VALIDATION_CONTEXT);
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.getProperty(WebsocketConstants.USERNAME);
String password = tokenValidationProperties.getProperty(WebsocketConstants.PASSWORD);
auth.setPassword(username);
auth.setUsername(password);
Options options = client.getOptions();
options.setProperty(HTTPConstants.AUTHENTICATE, auth);
options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Constants.VALUE_TRUE);
client.setOptions(options);
if (hostURL.getProtocol().equals("https")) {
// set up ssl factory since axis2 https transport is used.
EasySSLProtocolSocketFactory sslProtocolSocketFactory = createProtocolSocketFactory();
Protocol authhttps = new Protocol(hostURL.getProtocol()
, (ProtocolSocketFactory) sslProtocolSocketFactory, hostURL.getPort());
Protocol.registerProtocol(hostURL.getProtocol(), authhttps);
options.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, authhttps);
}
} else {
String errorMsg = "OAuth Validation instanization failed.";
throw new OAuthTokenValidationException(errorMsg);
}
} else {
String errorMsg = "host url is invalid";
throw new OAuthTokenValidationException(errorMsg);
}
} catch (AxisFault axisFault) {
throw new OAuthTokenValidationException(
"Error occurred while creating the OAuth2TokenValidationServiceStub.", axisFault);
} catch (MalformedURLException e) {
throw new OAuthTokenValidationException(
"Error occurred while parsing token endpoint URL", e);
}
HttpTransportProperties.Authenticator auth =
new HttpTransportProperties.Authenticator();
auth.setPreemptiveAuthentication(true);
String username = tokenValidationProperties.get(WebsocketConstants.USERNAME);
String password = tokenValidationProperties.get(WebsocketConstants.PASSWORD);
auth.setPassword(username);
auth.setUsername(password);
Options options = client.getOptions();
options.setProperty(HTTPConstants.AUTHENTICATE, auth);
options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Constants.VALUE_TRUE);
client.setOptions(options);
if (hostURL.getProtocol().equals("https")) {
// set up ssl factory since axis2 https transport is used.
EasySSLProtocolSocketFactory sslProtocolSocketFactory = createProtocolSocketFactory();
Protocol authhttps = new Protocol(hostURL.getProtocol()
, (ProtocolSocketFactory) sslProtocolSocketFactory, hostURL.getPort());
Protocol.registerProtocol(hostURL.getProtocol(), authhttps);
options.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, authhttps);
}
} 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 (OutputEventAdapterException e) {
throw new OAuthTokenValidationException("Invalid token endpoint url", e);
}
return stub;
return stub;
}
/**
@ -165,9 +162,9 @@ public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
*/
private HttpClient createHttpClient() {
HttpConnectionManagerParams params = new HttpConnectionManagerParams();
params.setDefaultMaxConnectionsPerHost(Integer.parseInt(tokenValidationProperties.getProperty(
WebsocketConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST)));
params.setMaxTotalConnections(Integer.parseInt(tokenValidationProperties.getProperty(
params.setDefaultMaxConnectionsPerHost(Integer.parseInt(tokenValidationProperties.get(
WebsocketConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST)));
params.setMaxTotalConnections(Integer.parseInt(tokenValidationProperties.get(
WebsocketConstants.MAXIMUM_TOTAL_HTTP_CONNECTION)));
HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
connectionManager.setParams(params);

@ -21,12 +21,19 @@ package org.wso2.carbon.device.mgt.output.adapter.websocket.authorization;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authentication.AuthenticationInfo;
import javax.websocket.Session;
import java.util.Map;
/**
* Check whether the client is authorized to connect.
*/
public interface Authorizer {
/**
* This is used to initialize the authenticator
* @param globalProperties related to the output adapter
*/
void init(Map<String, String> globalProperties);
/**
* Check whether the client is authorized to connect with the stream.
* @param authenticationInfo authenticated client information.

@ -31,13 +31,13 @@ import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.
.DeviceAccessAuthorizationAdminService;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.DeviceAuthorizationResult;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.DeviceIdentifier;
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.Properties;
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.Property;
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.WebsocketConfig;
import org.wso2.carbon.device.mgt.output.adapter.websocket.util.PropertyUtils;
import org.wso2.carbon.device.mgt.output.adapter.websocket.util.WebSocketSessionRequest;
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
import javax.websocket.Session;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@ -50,26 +50,34 @@ public class DeviceAuthorizer implements Authorizer {
private static final String CDMF_SERVER_BASE_CONTEXT = "/api/device-mgt/v1.0";
private static final String DEVICE_MGT_SERVER_URL = "deviceMgtServerUrl";
private static final String STAT_PERMISSION = "statsPermission";
private static final String DEVICE_ID = "deviceId";
private static final String DEVICE_TYPE = "deviceType";
private static Log logger = LogFactory.getLog(DeviceAuthorizer.class);
private static List<String> statPermissions;
public DeviceAuthorizer() {
Properties properties =
WebsocketConfig.getInstance().getWebsocketValidationConfigs().getAuthorizer().getProperties();
statPermissions = getPermissions(properties);
deviceAccessAuthorizationAdminService = Feign.builder()
.requestInterceptor(new OAuthRequestInterceptor())
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder())
.target(DeviceAccessAuthorizationAdminService.class, getDeviceMgtServerUrl(properties)
+ CDMF_SERVER_BASE_CONTEXT);
}
@Override
public void init(Map<String, String> globalProperties) {
statPermissions = getPermissions(globalProperties);
try {
deviceAccessAuthorizationAdminService = Feign.builder()
.requestInterceptor(new OAuthRequestInterceptor(globalProperties))
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder())
.target(DeviceAccessAuthorizationAdminService.class, getDeviceMgtServerUrl(globalProperties)
+ CDMF_SERVER_BASE_CONTEXT);
} catch (OutputEventAdapterException e) {
logger.error("Invalid value for deviceMgtServerUrl in globalProperties.");
}
}
@Override
public boolean isAuthorized(AuthenticationInfo authenticationInfo, Session session, String stream) {
WebSocketSessionRequest webSocketSessionRequest = new WebSocketSessionRequest(session);
Map<String, String> queryParams = webSocketSessionRequest.getQueryParamValuePairs();
String deviceId = queryParams.get("deviceId");
String deviceType = queryParams.get("deviceType");
String deviceId = queryParams.get(DEVICE_ID);
String deviceType = queryParams.get(DEVICE_TYPE);
if (deviceId != null && !deviceId.isEmpty() && deviceType != null && !deviceType.isEmpty()) {
@ -102,27 +110,19 @@ public class DeviceAuthorizer implements Authorizer {
return false;
}
private String getDeviceMgtServerUrl(Properties properties) {
String deviceMgtServerUrl = null;
for (Property property : properties.getProperty()) {
if (property.getName().equals(DEVICE_MGT_SERVER_URL)) {
deviceMgtServerUrl = property.getValue();
break;
}
}
private String getDeviceMgtServerUrl(Map<String, String> properties) throws OutputEventAdapterException {
String deviceMgtServerUrl = PropertyUtils.replaceMqttProperty(properties.get(DEVICE_MGT_SERVER_URL));
if (deviceMgtServerUrl == null || deviceMgtServerUrl.isEmpty()) {
logger.error("deviceMgtServerUrl can't be empty ");
}
return deviceMgtServerUrl;
}
private List<String> getPermissions(Properties properties) {
List<String> permission = new ArrayList<>();
for (Property property : properties.getProperty()) {
if (property.getName().equals(STAT_PERMISSION)) {
permission.add(property.getValue());
}
private List<String> getPermissions(Map<String, String> properties) {
String stats = properties.get(STAT_PERMISSION);
if (stats != null && !stats.isEmpty()) {
return Arrays.asList(stats.replace("\n", "").split(" "));
}
return permission;
return null;
}
}

@ -28,9 +28,8 @@ import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.ApiApplicationRegistrationService;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.ApiRegistrationProfile;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.TokenIssuerService;
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.Properties;
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.Property;
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.WebsocketConfig;
import java.util.Map;
/**
* This is a request interceptor to add oauth token header.
@ -51,25 +50,27 @@ public class OAuthRequestInterceptor implements RequestInterceptor {
private static final String CONNECTION_USERNAME = "username";
private static final String CONNECTION_PASSWORD = "password";
private static final String TOKEN_ENDPOINT = "tokenEndpoint";
private static final String TOKEN_ENDPOINT = "keymanagerUrl";
private static final String TOKEN_REFRESH_TIME_OFFSET = "tokenRefreshTimeOffset";
private static final String DEVICE_MGT_SERVER_URL = "deviceMgtServerUrl";
private static final String TOKEN_ENDPOINT_CONTEXT = "tokenEndpointContext";
private static String username;
private static String password;
private static String tokenEndpoint;
private static String deviceMgtServerUrl;
private static Map<String, String> globalProperties;
/**
* Creates an interceptor that authenticates all requests.
*/
public OAuthRequestInterceptor() {
Properties properties =
WebsocketConfig.getInstance().getWebsocketValidationConfigs().getAuthorizer().getProperties();
deviceMgtServerUrl = getDeviceMgtServerUrl(properties);
refreshTimeOffset = getRefreshTimeOffset(properties);
username = getUsername(properties);
password = getPassword(properties);
tokenEndpoint = getTokenEndpoint(properties);
public OAuthRequestInterceptor(Map<String, String> globalProperties) {
this.globalProperties = globalProperties;
deviceMgtServerUrl = getDeviceMgtServerUrl(globalProperties);
refreshTimeOffset = getRefreshTimeOffset(globalProperties);
username = getUsername(globalProperties);
password = getPassword(globalProperties);
tokenEndpoint = getTokenEndpoint(globalProperties);
apiApplicationRegistrationService = Feign.builder().requestInterceptor(
new BasicAuthRequestInterceptor(username, password))
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder())
@ -106,71 +107,42 @@ public class OAuthRequestInterceptor implements RequestInterceptor {
template.header("Authorization", headerValue);
}
private String getUsername(Properties properties) {
String username = null;
for (Property property : properties.getProperty()) {
if (property.getName().equals(CONNECTION_USERNAME)) {
username = property.getValue();
break;
}
}
private String getUsername(Map<String, String> globalProperties) {
String username = globalProperties.get(CONNECTION_USERNAME);
if (username == null || username.isEmpty()) {
logger.error("username can't be empty ");
}
return username;
}
private String getPassword(Properties properties) {
String password = null;
for (Property property : properties.getProperty()) {
if (property.getName().equals(CONNECTION_PASSWORD)) {
password = property.getValue();
break;
}
}
private String getPassword(Map<String, String> globalProperties) {
String password = globalProperties.get(CONNECTION_PASSWORD);;
if (password == null || password.isEmpty()) {
logger.error("password can't be empty ");
}
return password;
}
private String getDeviceMgtServerUrl(Properties properties) {
String deviceMgtServerUrl = null;
for (Property property : properties.getProperty()) {
if (property.getName().equals(DEVICE_MGT_SERVER_URL)) {
deviceMgtServerUrl = property.getValue();
break;
}
}
private String getDeviceMgtServerUrl(Map<String, String> globalProperties) {
String deviceMgtServerUrl = globalProperties.get(DEVICE_MGT_SERVER_URL);
if (deviceMgtServerUrl == null || deviceMgtServerUrl.isEmpty()) {
logger.error("deviceMgtServerUrl can't be empty ");
}
return deviceMgtServerUrl;
}
private String getTokenEndpoint(Properties properties) {
String tokenEndpoint = null;
for (Property property : properties.getProperty()) {
if (property.getName().equals(TOKEN_ENDPOINT)) {
tokenEndpoint = property.getValue();
break;
}
}
if (tokenEndpoint == null || tokenEndpoint.isEmpty()) {
private String getTokenEndpoint(Map<String, String> globalProperties) {
String tokenEndpoint = globalProperties.get(TOKEN_ENDPOINT) + globalProperties.get(TOKEN_ENDPOINT_CONTEXT);
if ( tokenEndpoint.isEmpty()) {
logger.error("tokenEndpoint can't be empty ");
}
return tokenEndpoint;
}
private long getRefreshTimeOffset(Properties properties) {
long refreshTimeOffset = 0;
private long getRefreshTimeOffset(Map<String, String> globalProperties) {
long refreshTimeOffset = 100;
try {
for (Property property : properties.getProperty()) {
if (property.getName().equals(TOKEN_REFRESH_TIME_OFFSET)) {
refreshTimeOffset = Long.parseLong(property.getValue());
break;
}
}
refreshTimeOffset = Long.parseLong(globalProperties.get(TOKEN_REFRESH_TIME_OFFSET));
} catch (NumberFormatException e) {
logger.error("refreshTimeOffset should be a number", e);
}

@ -1,107 +0,0 @@
/*
* 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.output.adapter.websocket.config;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for Authenticator complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* &lt;complexType name="Authenticator">
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;sequence>
* &lt;element name="Properties" type="{}Properties"/>
* &lt;/sequence>
* &lt;attribute name="class" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Authenticator", propOrder = {
"properties"
})
public class Authenticator {
@XmlElement(name = "Properties", required = false)
protected Properties properties;
@XmlAttribute(name = "class")
protected String clazz;
/**
* Gets the value of the properties property.
*
* @return
* possible object is
* {@link Properties }
*
*/
public Properties getProperties() {
return properties;
}
/**
* Sets the value of the properties property.
*
* @param value
* allowed object is
* {@link Properties }
*
*/
public void setProperties(Properties value) {
this.properties = value;
}
/**
* Gets the value of the clazz property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getClazz() {
return clazz;
}
/**
* Sets the value of the clazz property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setClazz(String value) {
this.clazz = value;
}
}

@ -1,107 +0,0 @@
/*
* 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.output.adapter.websocket.config;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for Authorizer complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* &lt;complexType name="Authorizer">
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;sequence>
* &lt;element name="Properties" type="{}Properties"/>
* &lt;/sequence>
* &lt;attribute name="class" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Authorizer", propOrder = {
"properties"
})
public class Authorizer {
@XmlElement(name = "Properties", required = false)
protected Properties properties;
@XmlAttribute(name = "class")
protected String clazz;
/**
* Gets the value of the properties property.
*
* @return
* possible object is
* {@link Properties }
*
*/
public Properties getProperties() {
return properties;
}
/**
* Sets the value of the properties property.
*
* @param value
* allowed object is
* {@link Properties }
*
*/
public void setProperties(Properties value) {
this.properties = value;
}
/**
* Gets the value of the clazz property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getClazz() {
return clazz;
}
/**
* Sets the value of the clazz property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setClazz(String value) {
this.clazz = value;
}
}

@ -1,86 +0,0 @@
/*
* 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.output.adapter.websocket.config;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
import java.util.ArrayList;
import java.util.List;
/**
* <p>Java class for Properties complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* &lt;complexType name="Properties">
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;sequence>
* &lt;element name="Property" type="{}Property" maxOccurs="unbounded" minOccurs="0"/>
* &lt;/sequence>
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Properties", propOrder = {
"property"
})
public class Properties {
@XmlElement(name = "Property")
protected List<Property> property;
/**
* Gets the value of the property property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the property property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getProperty().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link Property }
*
*
*/
public List<Property> getProperty() {
if (property == null) {
property = new ArrayList<Property>();
}
return this.property;
}
}

@ -1,104 +0,0 @@
/*
* 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.output.adapter.websocket.config;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlValue;
/**
* <p>Java class for Property complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* &lt;complexType name="Property">
* &lt;simpleContent>
* &lt;extension base="&lt;http://www.w3.org/2001/XMLSchema>string">
* &lt;attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;/extension>
* &lt;/simpleContent>
* &lt;/complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Property", propOrder = {
"value"
})
public class Property {
@XmlValue
protected String value;
@XmlAttribute(name = "name")
protected String name;
/**
* Gets the value of the value property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getValue() {
return value;
}
/**
* Sets the value of the value property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setValue(String value) {
this.value = value;
}
/**
* Gets the value of the name property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getName() {
return name;
}
/**
* Sets the value of the name property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setName(String value) {
this.name = value;
}
}

@ -1,81 +0,0 @@
/*
* 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.output.adapter.websocket.config;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.wso2.carbon.device.mgt.output.adapter.websocket.util.WebsocketUtils;
import org.wso2.carbon.utils.CarbonUtils;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.File;
/**
* This class represents the configuration that are needed for scopes to permission map.
*/
public class WebsocketConfig {
private static WebsocketConfig config = new WebsocketConfig();
private WebsocketValidationConfigs websocketValidationConfigs;
private static final Log log = LogFactory.getLog(WebsocketConfig.class);
private static final String WEBSOCKET_VALIDATION_CONFIG_PATH =
CarbonUtils.getEtcCarbonConfigDirPath() + File.separator + "websocket-validation.xml";
private WebsocketConfig() {
}
public static WebsocketConfig getInstance() {
return config;
}
public void init() throws WebsocketValidationConfigurationFailedException {
try {
File deviceMgtConfig = new File(WEBSOCKET_VALIDATION_CONFIG_PATH);
Document doc = WebsocketUtils.convertToDocument(deviceMgtConfig);
/* Un-marshaling DeviceMGtScope configuration */
JAXBContext ctx = JAXBContext.newInstance(WebsocketValidationConfigs.class);
Unmarshaller unmarshaller = ctx.createUnmarshaller();
//unmarshaller.setSchema(getSchema());
websocketValidationConfigs = (WebsocketValidationConfigs) unmarshaller.unmarshal(doc);
} catch (JAXBException e) {
throw new WebsocketValidationConfigurationFailedException("Error occurred while un-marshalling Websocket" +
" Config", e);
}
}
public WebsocketValidationConfigs getWebsocketValidationConfigs() {
if (websocketValidationConfigs == null) {
try {
init();
} catch (WebsocketValidationConfigurationFailedException e) {
log.error("failed to initialize the config", e);
}
}
return websocketValidationConfigs;
}
public void setWebsocketValidationConfigs(WebsocketValidationConfigs websocketValidationConfigs) {
websocketValidationConfigs = websocketValidationConfigs;
}
}

@ -1,105 +0,0 @@
/*
* 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.output.adapter.websocket.config;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* <p>Java class for WebsocketValidationConfigs complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* &lt;complexType name="WebsocketValidationConfigs">
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;sequence>
* &lt;element name="Authenticator" type="{}Authenticator"/>
* &lt;element name="Authorizer" type="{}Authorizer"/>
* &lt;/sequence>
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*
*
*/
@XmlRootElement(name = "WebsocketValidationConfigs")
@XmlAccessorType(XmlAccessType.FIELD)
public class WebsocketValidationConfigs {
@XmlElement(name = "Authenticator", required = true)
protected Authenticator authenticator;
@XmlElement(name = "Authorizer", required = true)
protected Authorizer authorizer;
/**
* Gets the value of the authenticator property.
*
* @return
* possible object is
* {@link Authenticator }
*
*/
public Authenticator getAuthenticator() {
return authenticator;
}
/**
* Sets the value of the authenticator property.
*
* @param value
* allowed object is
* {@link Authenticator }
*
*/
public void setAuthenticator(Authenticator value) {
this.authenticator = value;
}
/**
* Gets the value of the authorizer property.
*
* @return
* possible object is
* {@link Authorizer }
*
*/
public Authorizer getAuthorizer() {
return authorizer;
}
/**
* Sets the value of the authorizer property.
*
* @param value
* allowed object is
* {@link Authorizer }
*
*/
public void setAuthorizer(Authorizer value) {
this.authorizer = value;
}
}

@ -1,44 +0,0 @@
/*
* 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.output.adapter.websocket.config;
public class WebsocketValidationConfigurationFailedException extends Exception {
private static final long serialVersionUID = -3151279329290703928L;
public WebsocketValidationConfigurationFailedException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
public WebsocketValidationConfigurationFailedException(String message, Throwable cause) {
super(message, cause);
}
public WebsocketValidationConfigurationFailedException(String msg) {
super(msg);
}
public WebsocketValidationConfigurationFailedException() {
super();
}
public WebsocketValidationConfigurationFailedException(Throwable cause) {
super(cause);
}
}

@ -29,7 +29,8 @@ public class WebsocketConstants {
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 = "tokenValidationEndpoint";
public static final String TOKEN_VALIDATION_ENDPOINT_URL = "keymanagerUrl";
public static final String TOKEN_VALIDATION_CONTEXT = "/services/OAuth2TokenValidationService";
public static final String USERNAME = "username";
public static final String PASSWORD = "password";
public static final String TOKEN_PARAM = "token";

@ -23,12 +23,6 @@ import org.apache.commons.logging.LogFactory;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.device.mgt.output.adapter.websocket.UIEventAdapterFactory;
import org.wso2.carbon.device.mgt.output.adapter.websocket.UIOutputCallbackControllerServiceImpl;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authentication.Authenticator;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.Authorizer;
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.WebsocketConfig;
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.WebsocketValidationConfigurationFailedException;
import org.wso2.carbon.device.mgt.output.adapter.websocket.service.WebsocketValidationService;
import org.wso2.carbon.device.mgt.output.adapter.websocket.service.WebsocketValidationServiceImpl;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterFactory;
import org.wso2.carbon.device.mgt.output.adapter.websocket.UIOutputCallbackControllerService;
import org.wso2.carbon.event.stream.core.EventStreamService;
@ -51,45 +45,20 @@ public class UILocalEventAdapterServiceComponent {
protected void activate(ComponentContext context) {
try {
OutputEventAdapterFactory uiEventAdapterFactory = new UIEventAdapterFactory();
UIEventAdapterFactory uiEventAdapterFactory = new UIEventAdapterFactory();
context.getBundleContext().registerService(OutputEventAdapterFactory.class.getName(), uiEventAdapterFactory, null);
UIOutputCallbackControllerServiceImpl UIOutputCallbackRegisterServiceImpl =
new UIOutputCallbackControllerServiceImpl();
context.getBundleContext().registerService(UIOutputCallbackControllerService.class.getName(),
UIOutputCallbackRegisterServiceImpl, null);
uiEventAdapterFactory.setBundleContext(context.getBundleContext());
UIEventAdaptorServiceDataHolder.registerUIOutputCallbackRegisterServiceInternal(
UIOutputCallbackRegisterServiceImpl);
if (log.isDebugEnabled()) {
log.debug("Successfully deployed the output websocket adapter service");
}
try {
WebsocketConfig.getInstance().init();
WebsocketValidationServiceImpl websocketValidationService = new WebsocketValidationServiceImpl();
String authenticatorClassName = WebsocketConfig.getInstance().getWebsocketValidationConfigs()
.getAuthenticator().getClazz();
String authorizerClassName = WebsocketConfig.getInstance().getWebsocketValidationConfigs()
.getAuthorizer().getClazz();
if (authenticatorClassName != null && !authenticatorClassName.isEmpty()) {
Class<? extends Authenticator> authenticatorClass = Class.forName(authenticatorClassName)
.asSubclass(Authenticator.class);
Authenticator authenticator = authenticatorClass.newInstance();
websocketValidationService.setAuthenticator(authenticator);
}
if (authorizerClassName != null && !authorizerClassName.isEmpty()) {
Class<? extends Authorizer> authorizerClass = Class.forName(authorizerClassName)
.asSubclass(Authorizer.class);
Authorizer authorizer = authorizerClass.newInstance();
websocketValidationService.setAuthorizer(authorizer);
}
context.getBundleContext().registerService(
WebsocketValidationService.class.getName(), websocketValidationService, null);
} catch (WebsocketValidationConfigurationFailedException e) {
log.error("Failed to initialize configuration for websocket.", e);
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
log.error("Failed to initialize the class authentication and authorization given " +
"in the websocket validation configuration.", e);
}
} catch (RuntimeException e) {
log.error("Can not create the output websocket adapter service ", e);
} catch (Throwable e) {

@ -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.output.adapter.websocket.util;
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PropertyUtils {
//This method is only used if the mb features are within DAS.
public static String replaceMqttProperty(String urlWithPlaceholders) throws OutputEventAdapterException {
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 OutputEventAdapterException("System property - " + sysPropertyName
+ " is not defined, hence cannot resolve : " + urlWithPlaceholders);
}
}
return urlWithPlaceholders;
}
}

@ -46,5 +46,7 @@ public class UIEventAdapterConstants {
public static final String ADAPTER_EVENT_QUEUE_SIZE_NAME = "eventQueueSize";
public static final int EVENTS_QUEUE_SIZE = 30;
public static final String AUTHENTICATOR_CLASS = "authenticator";
public static final String AUTHORIZER_CLASS = "authorizer";
}

@ -1,45 +0,0 @@
/*
* 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.output.adapter.websocket.util;
import org.w3c.dom.Document;
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.WebsocketValidationConfigurationFailedException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
/**
* This class holds util methods used by OAuth extension bundle.
*/
public class WebsocketUtils {
public static Document convertToDocument(File file) throws WebsocketValidationConfigurationFailedException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
DocumentBuilder docBuilder = factory.newDocumentBuilder();
return docBuilder.parse(file);
} catch (Exception e) {
throw new WebsocketValidationConfigurationFailedException("Error occurred while parsing file, while converting " +
"to a org.w3c.dom.Document", e);
}
}
}

@ -56,10 +56,9 @@
<FileBasedProperties>true</FileBasedProperties>
<!--if file based properties is set to false then the configuration will be picked from platform configuration-->
<ConfigProperties>
<Property Name="mqtt.adapter.name">androidsense.mqtt.adapter</Property>
<Property Name="url">tcp://localhost:1886</Property>
<Property Name="mqttAdapterName">androidsense.mqtt.adapter</Property>
<Property Name="username">admin</Property>
<Property Name="dcrUrl">https://localhost:9443/dynamic-client-web/register</Property>
<Property Name="password">admin</Property>
<Property Name="qos">0</Property>
<Property Name="scopes"/>
<Property Name="clearSession">true</Property>

@ -38,10 +38,9 @@
<FileBasedProperties>true</FileBasedProperties>
<!--if file based properties is set to false then the configuration will be picked from platform configuration-->
<ConfigProperties>
<Property Name="mqtt.adapter.name">raspberrypi.mqtt.adapter</Property>
<Property Name="url">tcp://localhost:1886</Property>
<Property Name="mqttAdapterName">raspberrypi.mqtt.adapter</Property>
<Property Name="username">admin</Property>
<Property Name="dcrUrl">https://localhost:9443/dynamic-client-web/register</Property>
<Property Name="password">admin</Property>
<Property Name="qos">0</Property>
<Property Name="scopes"/>
<Property Name="clearSession">true</Property>

@ -22,10 +22,9 @@
<!--MQTT Config-->
<EventListenerProvider>MQTT</EventListenerProvider>
<Properties>
<Property Name="mqtt.adapter.name">virtualfirealarm.mqtt.adapter</Property>
<Property Name="url">tcp://localhost:1886</Property>
<Property Name="mqttAdapterName">virtualfirealarm.mqtt.adapter</Property>
<Property Name="username">admin</Property>
<Property Name="dcrUrl">https://localhost:9443/dynamic-client-web/register</Property>
<Property Name="password">admin</Property>
<Property Name="qos">0</Property>
<Property Name="scopes"/>
<Property Name="clearSession">true</Property>

@ -38,10 +38,9 @@
<FileBasedProperties>true</FileBasedProperties>
<!--if file based properties is set to false then the configuration will be picked from platform configuration-->
<ConfigProperties>
<Property Name="mqtt.adapter.name">virtualfirealarm.mqtt.adapter</Property>
<Property Name="url">tcp://localhost:1886</Property>
<Property Name="mqttAdapterName">virtualfirealarm.mqtt.adapter</Property>
<Property Name="username">admin</Property>
<Property Name="dcrUrl">https://localhost:9443/dynamic-client-web/register</Property>
<Property Name="password">admin</Property>
<Property Name="qos">0</Property>
<Property Name="scopes"/>
<Property Name="clearSession">true</Property>

Loading…
Cancel
Save