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"> <from eventAdapterType="oauth-mqtt">
<property name="topic">carbon.super/android_sense/+/data</property> <property name="topic">carbon.super/android_sense/+/data</property>
<property name="username">admin</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="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> <property name="cleanSession">true</property>
</from> </from>
<mapping customMapping="disable" type="json"/> <mapping customMapping="disable" type="json"/>

@ -18,14 +18,7 @@
--> -->
<eventReceiver name="arduino_receiver" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver"> <eventReceiver name="arduino_receiver" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver">
<from eventAdapterType="oauth-http"> <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="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> </from>
<mapping customMapping="disable" type="json"/> <mapping customMapping="disable" type="json"/>
<to streamName="org.wso2.iot.arduino" version="1.0.0"/> <to streamName="org.wso2.iot.arduino" version="1.0.0"/>

@ -20,10 +20,8 @@
<from eventAdapterType="oauth-mqtt"> <from eventAdapterType="oauth-mqtt">
<property name="topic">carbon.super/raspberrypi/+/temperature</property> <property name="topic">carbon.super/raspberrypi/+/temperature</property>
<property name="username">admin</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="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> <property name="cleanSession">true</property>
</from> </from>
<mapping customMapping="disable" type="json"/> <mapping customMapping="disable" type="json"/>

@ -20,10 +20,8 @@
<from eventAdapterType="oauth-mqtt"> <from eventAdapterType="oauth-mqtt">
<property name="topic">carbon.super/virtual_firealarm/+/temperature</property> <property name="topic">carbon.super/virtual_firealarm/+/temperature</property>
<property name="username">admin</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="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> <property name="cleanSession">true</property>
</from> </from>
<mapping customMapping="disable" type="json"/> <mapping customMapping="disable" type="json"/>

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

@ -75,45 +75,6 @@ public class HTTPEventAdapterFactory extends InputEventAdapterFactory {
exposedTransportsProperty.setDefaultValue(HTTPEventAdapterConstants.ALL); exposedTransportsProperty.setDefaultValue(HTTPEventAdapterConstants.ALL);
propertyList.add(exposedTransportsProperty); 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 //Content Validator details
Property contentValidator = new Property(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME); Property contentValidator = new Property(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME);
contentValidator.setDisplayName( contentValidator.setDisplayName(

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

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

@ -34,7 +34,6 @@ import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.wso2.carbon.core.util.Utils; import org.wso2.carbon.core.util.Utils;
import org.wso2.carbon.device.mgt.input.adapter.http.oauth.exception.OAuthTokenValidationException; 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.device.mgt.input.adapter.http.util.HTTPEventAdapterConstants;
import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub; import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
@ -42,6 +41,7 @@ import java.io.IOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.Map;
/** /**
* This follows object pool pattern to manage the stub for oauth validation service. * 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 { public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
private static final Logger log = Logger.getLogger(OAuthTokenValidaterStubFactory.class); private static final Logger log = Logger.getLogger(OAuthTokenValidaterStubFactory.class);
private HttpClient httpClient; private HttpClient httpClient;
InputEventAdapterConfiguration eventAdapterConfiguration; Map<String, String> globalProperties;
public OAuthTokenValidaterStubFactory(InputEventAdapterConfiguration eventAdapterConfiguration) { public OAuthTokenValidaterStubFactory(Map<String, String> globalProperties) {
this.eventAdapterConfiguration = eventAdapterConfiguration; this.globalProperties = globalProperties;
this.httpClient = createHttpClient(); this.httpClient = createHttpClient();
} }
@ -92,9 +92,10 @@ public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
private OAuth2TokenValidationServiceStub generateStub() throws OAuthTokenValidationException { private OAuth2TokenValidationServiceStub generateStub() throws OAuthTokenValidationException {
OAuth2TokenValidationServiceStub stub; OAuth2TokenValidationServiceStub stub;
try { try {
URL hostURL = new URL(Utils.replaceSystemProperty(eventAdapterConfiguration.getProperties().get( URL hostURL = new URL(Utils.replaceSystemProperty(globalProperties.get(
HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL))); HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL)
if (hostURL != null) { + HTTPEventAdapterConstants.TOKEN_VALIDATION_POST_FIX));
if (hostURL != null) {
stub = new OAuth2TokenValidationServiceStub(hostURL.toString()); stub = new OAuth2TokenValidationServiceStub(hostURL.toString());
if (stub != null) { if (stub != null) {
ServiceClient client = stub._getServiceClient(); ServiceClient client = stub._getServiceClient();
@ -104,10 +105,8 @@ public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
HttpTransportProperties.Authenticator auth = HttpTransportProperties.Authenticator auth =
new HttpTransportProperties.Authenticator(); new HttpTransportProperties.Authenticator();
auth.setPreemptiveAuthentication(true); auth.setPreemptiveAuthentication(true);
String username = eventAdapterConfiguration.getProperties().get(HTTPEventAdapterConstants String username = globalProperties.get(HTTPEventAdapterConstants.USERNAME);
.USERNAME); String password = globalProperties.get(HTTPEventAdapterConstants.PASSWORD);
String password = eventAdapterConfiguration.getProperties().get(HTTPEventAdapterConstants
.PASSWORD);
auth.setPassword(username); auth.setPassword(username);
auth.setUsername(password); auth.setUsername(password);
Options options = client.getOptions(); Options options = client.getOptions();
@ -151,8 +150,7 @@ public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
*/ */
private EasySSLProtocolSocketFactory createProtocolSocketFactory() throws OAuthTokenValidationException { private EasySSLProtocolSocketFactory createProtocolSocketFactory() throws OAuthTokenValidationException {
try { try {
EasySSLProtocolSocketFactory easySSLPSFactory = new EasySSLProtocolSocketFactory(); return new EasySSLProtocolSocketFactory();
return easySSLPSFactory;
} catch (IOException e) { } catch (IOException e) {
String errorMsg = "Failed to initiate EasySSLProtocolSocketFactory."; String errorMsg = "Failed to initiate EasySSLProtocolSocketFactory.";
throw new OAuthTokenValidationException(errorMsg, e); throw new OAuthTokenValidationException(errorMsg, e);
@ -170,9 +168,9 @@ public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
*/ */
private HttpClient createHttpClient() { private HttpClient createHttpClient() {
HttpConnectionManagerParams params = new HttpConnectionManagerParams(); HttpConnectionManagerParams params = new HttpConnectionManagerParams();
params.setDefaultMaxConnectionsPerHost(Integer.parseInt(eventAdapterConfiguration.getProperties().get( params.setDefaultMaxConnectionsPerHost(Integer.parseInt(globalProperties.get(
HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST))); HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST)));
params.setMaxTotalConnections(Integer.parseInt(eventAdapterConfiguration.getProperties().get( params.setMaxTotalConnections(Integer.parseInt(globalProperties.get(
HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION))); HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION)));
HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
connectionManager.setParams(params); 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_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 = "maximumHttpConnectionPerHost";
public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST_HINT = "maximumHttpConnectionPerHost.hint"; 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 = "keymanagerUrl";
public static final String TOKEN_VALIDATION_ENDPOINT_URL_HINT = "tokenValidationEndpointUrl.hint"; public static final String TOKEN_VALIDATION_POST_FIX = "/services/OAuth2TokenValidationService";
public static final String USERNAME = "username"; public static final String USERNAME = "username";
public static final String USERNAME_HINT = "username.hint"; public static final String USERNAME_HINT = "username.hint";
public static final String PASSWORD = "password"; 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_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_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> 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=contentValidator
contentValidator.hint=Class Name of the content Validation or 'default' to set default class, required to implement (if required) contentValidator.hint=Class Name of the content Validation or 'default' to set default class, required to implement (if required)
contentTransformer=contentTransformer contentTransformer=contentTransformer

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

@ -53,29 +53,13 @@ public class MQTTEventAdapter implements InputEventAdapter {
public void init(InputEventAdapterListener eventAdapterListener) throws InputEventAdapterException { public void init(InputEventAdapterListener eventAdapterListener) throws InputEventAdapterException {
this.eventAdapterListener = eventAdapterListener; this.eventAdapterListener = eventAdapterListener;
try { 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) { } catch (Throwable t) {
throw new InputEventAdapterException(t.getMessage(), t); throw new InputEventAdapterException(t.getMessage(), t);
} }

@ -59,16 +59,10 @@ public class MQTTEventAdapterFactory extends InputEventAdapterFactory {
//Broker Url //Broker Url
Property brokerUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_URL); Property brokerUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
brokerUrl.setDisplayName(resourceBundle.getString(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)); brokerUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL_HINT));
propertyList.add(brokerUrl); 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 //Content Validator details
Property contentValidator = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME); 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); Property userName = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME);
userName.setDisplayName( userName.setDisplayName(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME)); resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME));
userName.setRequired(false); userName.setRequired(true);
userName.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME_HINT)); userName.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME_HINT));
propertyList.add(userName); 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. //Broker Required Scopes.
Property scopes = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES); Property scopes = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES);
scopes.setDisplayName( scopes.setDisplayName(

@ -23,13 +23,9 @@ import org.osgi.service.component.ComponentContext;
import org.osgi.service.http.HttpService; import org.osgi.service.http.HttpService;
import org.wso2.carbon.device.mgt.input.adapter.mqtt.MQTTEventAdapterFactory; import org.wso2.carbon.device.mgt.input.adapter.mqtt.MQTTEventAdapterFactory;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterFactory; 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.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 { 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) { protected void setHttpService(HttpService httpService) {
InputAdapterServiceDataHolder.registerHTTPService(httpService); InputAdapterServiceDataHolder.registerHTTPService(httpService);
} }

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

@ -17,13 +17,18 @@
*/ */
package org.wso2.carbon.device.mgt.input.adapter.mqtt.util; 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.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType; import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity; 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.*;
import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence; import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence;
import org.json.simple.JSONObject; 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.InputEventAdapterListener;
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterRuntimeException; 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.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.io.IOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
@ -49,7 +51,9 @@ import java.net.URL;
import java.security.KeyManagementException; import java.security.KeyManagementException;
import java.security.KeyStoreException; import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
public class MQTTAdapterListener implements MqttCallback, Runnable { public class MQTTAdapterListener implements MqttCallback, Runnable {
@ -144,16 +148,14 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
} }
public void startListener() throws MqttException { public void startListener() throws MqttException {
if (this.mqttBrokerConnectionConfiguration.getBrokerUsername() != null && if (this.mqttBrokerConnectionConfiguration.getUsername() != null &&
this.mqttBrokerConnectionConfiguration.getDcrUrl() != 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 dcrUrlString = this.mqttBrokerConnectionConfiguration.getDcrUrl();
String scopes = this.mqttBrokerConnectionConfiguration.getBrokerScopes(); String scopes = this.mqttBrokerConnectionConfiguration.getBrokerScopes();
//getJWT Client Parameters. //getJWT Client Parameters.
if (dcrUrlString != null && !dcrUrlString.isEmpty()) { if (dcrUrlString != null && !dcrUrlString.isEmpty()) {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true);
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(username);
try { try {
URL dcrUrl = new URL(dcrUrlString); URL dcrUrl = new URL(dcrUrlString);
HttpClient httpClient = MQTTUtil.getHttpClient(dcrUrl.getProtocol()); HttpClient httpClient = MQTTUtil.getHttpClient(dcrUrl.getProtocol());
@ -163,11 +165,15 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
registrationProfile.setGrantType(MQTTEventAdapterConstants.GRANT_TYPE); registrationProfile.setGrantType(MQTTEventAdapterConstants.GRANT_TYPE);
registrationProfile.setOwner(username); registrationProfile.setOwner(username);
registrationProfile.setTokenScope(MQTTEventAdapterConstants.TOKEN_SCOPE); registrationProfile.setTokenScope(MQTTEventAdapterConstants.TOKEN_SCOPE);
registrationProfile.setApplicationType(MQTTEventAdapterConstants.APPLICATION_TYPE); registrationProfile.setClientName(MQTTEventAdapterConstants.APPLICATION_NAME_PREFIX
registrationProfile.setClientName(username + "_" + tenantId); + mqttBrokerConnectionConfiguration.getAdapterName() + "_" + tenantId);
String jsonString = registrationProfile.toJSON(); String jsonString = registrationProfile.toJSON();
StringEntity requestEntity = new StringEntity(jsonString, ContentType.APPLICATION_JSON); StringEntity requestEntity = new StringEntity(jsonString, ContentType.APPLICATION_JSON);
postMethod.setEntity(requestEntity); 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); HttpResponse httpResponse = httpClient.execute(postMethod);
if (httpResponse != null) { if (httpResponse != null) {
String response = MQTTUtil.getResponseString(httpResponse); String response = MQTTUtil.getResponseString(httpResponse);
@ -177,16 +183,10 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
JSONObject jsonPayload = (JSONObject) jsonParser.parse(response); JSONObject jsonPayload = (JSONObject) jsonParser.parse(response);
String clientId = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_ID); String clientId = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_ID);
String clientSecret = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_SECRET); String clientSecret = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_SECRET);
JWTClientManagerService jwtClientManagerService = MQTTUtil.getJWTClientManagerService(); connectionOptions.setUserName(getToken(clientId, clientSecret));
AccessTokenInfo accessTokenInfo = jwtClientManagerService.getJWTClient().getAccessToken(
clientId, clientSecret, username, scopes);
connectionOptions.setUserName(accessTokenInfo.getAccessToken());
} }
} catch (ParseException e) { } catch (ParseException e) {
String msg = "error occurred while parsing client credential payload"; String msg = "error occurred while parsing generating token for the adapter";
log.error(msg, e);
} catch (JWTClientException e) {
String msg = "error occurred while parsing the response from JWT Client";
log.error(msg, e); log.error(msg, e);
} }
} }
@ -194,8 +194,6 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
log.error("Invalid dcrUrl : " + dcrUrlString); log.error("Invalid dcrUrl : " + dcrUrlString);
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | IOException e) { } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | IOException e) {
log.error("Failed to create an https connection.", 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() { public boolean isConnectionInitialized() {
return connectionInitialized; 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; 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 org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterException;
import java.util.Map;
/** /**
* This holds the configurations related to MQTT Broker. * This holds the configurations related to MQTT Broker.
*/ */
public class MQTTBrokerConnectionConfiguration { public class MQTTBrokerConnectionConfiguration {
private String brokerUsername = null; private String username = null;
private String password = null;
private String brokerScopes = null; private String brokerScopes = null;
private boolean cleanSession = true; private boolean cleanSession = true;
private int keepAlive; private int keepAlive;
private String brokerUrl; private String brokerUrl;
private String dcrUrl; private String dcrUrl;
private String tokenUrl;
private String contentValidatorClassName; private String contentValidatorClassName;
private String contentTransformerClassName; private String contentTransformerClassName;
private String adapterName;
public String getBrokerScopes() { public String getBrokerScopes() {
return brokerScopes; return brokerScopes;
} }
public String getBrokerUsername() { public String getUsername() {
return brokerUsername; return username;
}
public String getPassword() {
return password;
} }
public boolean isCleanSession() { public boolean isCleanSession() {
@ -65,21 +75,44 @@ public class MQTTBrokerConnectionConfiguration {
return contentTransformerClassName; return contentTransformerClassName;
} }
public MQTTBrokerConnectionConfiguration(String brokerUrl, String brokerUsername, String brokerScopes, public String getTokenUrl() {
String dcrUrl, String cleanSession, int keepAlive, return tokenUrl;
String contentValidatorClassName, String contentTransformerClassName) throws InputEventAdapterException { }
this.brokerUsername = brokerUsername;
this.brokerScopes = brokerScopes; 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) { if (brokerScopes == null) {
this.brokerScopes = MQTTEventAdapterConstants.EMPTY_STRING; this.brokerScopes = MQTTEventAdapterConstants.EMPTY_STRING;
} }
this.brokerUrl = PropertyUtils.replaceMqttProperty(brokerUrl); String url = eventAdapterConfiguration .getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
this.dcrUrl = PropertyUtils.replaceMqttProperty(dcrUrl); if (url == null || url.isEmpty()) {
this.contentValidatorClassName = contentValidatorClassName; url = globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
if (cleanSession != null) { }
this.cleanSession = Boolean.parseBoolean(cleanSession); 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 = eventAdapterConfiguration.getProperties()
this.contentTransformerClassName = contentTransformerClassName; .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_URL = "url";
public static final String ADAPTER_CONF_USERNAME = "username"; public static final String ADAPTER_CONF_USERNAME = "username";
public static final String ADAPTER_CONF_USERNAME_HINT = "username.hint"; 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 = "scopes";
public static final String ADAPTER_CONF_SCOPES_HINT = "scopes.hint"; 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_URL_HINT = "url.hint";
public static final String ADAPTER_CONF_DCR_URL = "dcrUrl"; 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_DCR_URL_HINT = "dcrUrl.hint";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME = "contentValidator"; public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME = "contentValidator";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT = "contentValidator.hint"; 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 int RECONNECTION_PROGRESS_FACTOR = 2;
public static final String EMPTY_STRING = ""; 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 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_ID = "client_id";
public static final String CLIENT_SECRET = "client_secret"; public static final String CLIENT_SECRET = "client_secret";
public static final String CLIENT_NAME = "client_name"; 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_ID_JSON_PATH = "event.metaData.deviceId";
public static final String DEVICE_TYPE_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 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.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils; 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.BufferedReader;
import java.io.IOException; 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 topic.hint=Topic subscribed
clientId=Client Id 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. 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=Username
username.hint=Username of the broker (if required) username.hint=Username of the broker (if required)
password=Password
password.hint=Password of the user for the broker (if required)
scopes=Scopes scopes=Scopes
scopes.hint=Scopes required to connect to broker (if required) scopes.hint=Scopes required to connect to broker (if required)
dcrUrl=dcrUrl dcrUrl=dcrUrl

@ -61,10 +61,6 @@
<groupId>com.googlecode.json-simple.wso2</groupId> <groupId>com.googlecode.json-simple.wso2</groupId>
<artifactId>json-simple</artifactId> <artifactId>json-simple</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
@ -122,7 +118,10 @@
org.osgi.framework, org.osgi.framework,
org.osgi.service.component, org.osgi.service.component,
org.wso2.carbon.context, 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> </Import-Package>
</instructions> </instructions>
</configuration> </configuration>

@ -118,19 +118,7 @@ public class MQTTEventAdapter implements OutputEventAdapter {
@Override @Override
public void connect() { public void connect() {
MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration = MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration =
new MQTTBrokerConnectionConfiguration(eventAdapterConfiguration.getStaticProperties() new MQTTBrokerConnectionConfiguration(eventAdapterConfiguration, globalProperties);
.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)
);
String clientId = eventAdapterConfiguration.getStaticProperties().get( String clientId = eventAdapterConfiguration.getStaticProperties().get(
MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID); MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID);
qos = eventAdapterConfiguration.getStaticProperties().get(MQTTEventAdapterConstants.ADAPTER_MESSAGE_QOS); qos = eventAdapterConfiguration.getStaticProperties().get(MQTTEventAdapterConstants.ADAPTER_MESSAGE_QOS);

@ -50,7 +50,7 @@ public class MQTTEventAdapterFactory extends OutputEventAdapterFactory {
//Broker Url //Broker Url
Property brokerUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_URL); Property brokerUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
brokerUrl.setDisplayName(resourceBundle.getString(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)); brokerUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL_HINT));
//Broker Username //Broker Username
@ -59,11 +59,11 @@ public class MQTTEventAdapterFactory extends OutputEventAdapterFactory {
userName.setRequired(true); userName.setRequired(true);
userName.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME_HINT)); userName.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME_HINT));
//Broker dcr URL //Broker Password
Property dcrUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL); Property password = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD);
dcrUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL)); password.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD));
dcrUrl.setRequired(true); password.setRequired(true);
dcrUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL_HINT)); password.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_PASSWORD_HINT));
//Broker Connection Scopes //Broker Connection Scopes
Property scopes = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES); Property scopes = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES);
@ -95,10 +95,10 @@ public class MQTTEventAdapterFactory extends OutputEventAdapterFactory {
staticPropertyList.add(brokerUrl); staticPropertyList.add(brokerUrl);
staticPropertyList.add(userName); staticPropertyList.add(userName);
staticPropertyList.add(dcrUrl);
staticPropertyList.add(scopes); staticPropertyList.add(scopes);
staticPropertyList.add(clearSession); staticPropertyList.add(clearSession);
staticPropertyList.add(qos); staticPropertyList.add(qos);
staticPropertyList.add(password);
return staticPropertyList; 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.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.commons.ssl.Base64;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType; import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity; 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.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException; 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.ConnectionUnavailableException;
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException; import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterRuntimeException; import org.wso2.carbon.event.output.adapter.core.exception.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.io.IOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
@ -46,6 +48,8 @@ import java.net.URL;
import java.security.KeyManagementException; import java.security.KeyManagementException;
import java.security.KeyStoreException; import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
/** /**
* MQTT publisher related configuration initialization and publishing capabilties are implemented here. * MQTT publisher related configuration initialization and publishing capabilties are implemented here.
@ -77,10 +81,8 @@ public class MQTTAdapterPublisher {
MqttConnectOptions connectionOptions = new MqttConnectOptions(); MqttConnectOptions connectionOptions = new MqttConnectOptions();
connectionOptions.setCleanSession(cleanSession); connectionOptions.setCleanSession(cleanSession);
connectionOptions.setKeepAliveInterval(keepAlive); connectionOptions.setKeepAliveInterval(keepAlive);
if (mqttBrokerConnectionConfiguration.getBrokerUsername() != null) { if (mqttBrokerConnectionConfiguration.getUsername() != null) {
connectionOptions.setUserName(getToken(mqttBrokerConnectionConfiguration.getBrokerUsername(), connectionOptions.setUserName(getToken());
mqttBrokerConnectionConfiguration.getDcrUrl(),
mqttBrokerConnectionConfiguration.getScopes()));
connectionOptions.setPassword(MQTTEventAdapterConstants.DEFAULT_PASSWORD.toCharArray()); connectionOptions.setPassword(MQTTEventAdapterConstants.DEFAULT_PASSWORD.toCharArray());
} }
// Construct an MQTT blocking mode client // 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); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
if (dcrUrlString != null && !dcrUrlString.isEmpty()) { if (dcrUrlString != null && !dcrUrlString.isEmpty()) {
try { try {
@ -147,32 +153,34 @@ public class MQTTAdapterPublisher {
HttpClient httpClient = MQTTUtil.getHttpClient(dcrUrl.getProtocol()); HttpClient httpClient = MQTTUtil.getHttpClient(dcrUrl.getProtocol());
HttpPost postMethod = new HttpPost(dcrUrlString); HttpPost postMethod = new HttpPost(dcrUrlString);
RegistrationProfile registrationProfile = new RegistrationProfile(); RegistrationProfile registrationProfile = new RegistrationProfile();
registrationProfile.setCallbackUrl(MQTTEventAdapterConstants.DEFAULT_CALLBACK); registrationProfile.setCallbackUrl(MQTTEventAdapterConstants.EMPTY_STRING);
registrationProfile.setGrantType(MQTTEventAdapterConstants.GRANT_TYPE); registrationProfile.setGrantType(MQTTEventAdapterConstants.GRANT_TYPE);
registrationProfile.setOwner(username); registrationProfile.setOwner(username);
registrationProfile.setTokenScope(MQTTEventAdapterConstants.TOKEN_SCOPE); registrationProfile.setTokenScope(MQTTEventAdapterConstants.TOKEN_SCOPE);
registrationProfile.setApplicationType(MQTTEventAdapterConstants.APPLICATION_TYPE); registrationProfile.setClientName(MQTTEventAdapterConstants.APPLICATION_NAME_PREFIX
registrationProfile.setClientName(username + "_" + tenantId); + mqttBrokerConnectionConfiguration.getAdapterName() + "_" + tenantId);
String jsonString = registrationProfile.toJSON(); String jsonString = registrationProfile.toJSON();
StringEntity requestEntity = new StringEntity(jsonString, ContentType.APPLICATION_JSON); StringEntity requestEntity = new StringEntity(jsonString, ContentType.APPLICATION_JSON);
postMethod.setEntity(requestEntity); 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); HttpResponse httpResponse = httpClient.execute(postMethod);
String response = MQTTUtil.getResponseString(httpResponse); if (httpResponse != null) {
try { String response = MQTTUtil.getResponseString(httpResponse);
JSONParser jsonParser = new JSONParser(); try {
JSONObject jsonPayload = (JSONObject) jsonParser.parse(response); if (response != null) {
String clientId = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_ID); JSONParser jsonParser = new JSONParser();
String clientSecret = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_SECRET); JSONObject jsonPayload = (JSONObject) jsonParser.parse(response);
JWTClientManagerService jwtClientManagerService = MQTTUtil.getJWTClientManagerService(); String clientId = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_ID);
AccessTokenInfo accessTokenInfo = jwtClientManagerService.getJWTClient().getAccessToken( String clientSecret = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_SECRET);
clientId, clientSecret, username, scopes); getToken(clientId, clientSecret);
return accessTokenInfo.getAccessToken(); }
} catch (ParseException e) { } catch (ParseException e) {
String msg = "error occurred while parsing client credential payload"; String msg = "error occurred while parsing generating token for the adapter";
throw new OutputEventAdapterRuntimeException(msg, e); log.error(msg, e);
} catch (JWTClientException e) { }
String msg = "error occurred while parsing the response from JWT Client";
throw new OutputEventAdapterRuntimeException(msg, e);
} }
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
throw new OutputEventAdapterRuntimeException("Invalid dcrUrl : " + dcrUrlString); throw new OutputEventAdapterRuntimeException("Invalid dcrUrl : " + dcrUrlString);
@ -183,4 +191,39 @@ public class MQTTAdapterPublisher {
throw new OutputEventAdapterRuntimeException("Invalid configuration for mqtt publisher"); 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; 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 { public class MQTTBrokerConnectionConfiguration {
private String brokerUsername; private String adapterName;
private String username;
private String password;
private String dcrUrl; private String dcrUrl;
private String scopes; private String scopes;
private String brokerUrl; private String brokerUrl;
private String tokenUrl;
private boolean cleanSession = true; private boolean cleanSession = true;
private int keepAlive; private int keepAlive;
public String getTokenUrl() {
return tokenUrl;
}
public String getDcrUrl() { public String getDcrUrl() {
return dcrUrl; return dcrUrl;
@ -34,8 +45,12 @@ public class MQTTBrokerConnectionConfiguration {
return scopes; return scopes;
} }
public String getBrokerUsername() { public String getUsername() {
return brokerUsername; return username;
}
public String getPassword() {
return password;
} }
public boolean isCleanSession() { public boolean isCleanSession() {
@ -50,15 +65,35 @@ public class MQTTBrokerConnectionConfiguration {
return keepAlive; return keepAlive;
} }
public MQTTBrokerConnectionConfiguration(String brokerUrl, String brokerUsername, public String getAdapterName() {
String dcrUrl, String scopes, int keepAlive, String cleanSession) { return adapterName;
this.brokerUsername = brokerUsername; }
this.dcrUrl = dcrUrl;
this.scopes = scopes; public MQTTBrokerConnectionConfiguration(OutputEventAdapterConfiguration eventAdapterConfiguration,
this.brokerUrl = brokerUrl; Map<String, String> globalProperties) {
this.keepAlive = keepAlive; adapterName = eventAdapterConfiguration.getName();
if (cleanSession != null) { this.username = eventAdapterConfiguration.getStaticProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME);
this.cleanSession = Boolean.parseBoolean(cleanSession); 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_URL = "url";
public static final String ADAPTER_CONF_USERNAME = "username"; public static final String ADAPTER_CONF_USERNAME = "username";
public static final String ADAPTER_CONF_USERNAME_HINT = "username.hint"; 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 = "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 = "scopes";
public static final String ADAPTER_CONF_SCOPES_HINT = "scopes.hint"; 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_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_TEMP_DIRECTORY_NAME = "java.io.tmpdir";
public static final String ADAPTER_CONF_CLIENTID = "clientId"; public static final String ADAPTER_CONF_CLIENTID = "clientId";
public static final String ADAPTER_CONF_CLIENTID_HINT = "clientId.hint"; 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_MIN_THREAD_POOL_SIZE = 8;
public static final int DEFAULT_MAX_THREAD_POOL_SIZE = 100; 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_CALLBACK = "";
public static final String DEFAULT_PASSWORD = ""; 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 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_ID = "client_id";
public static final String CLIENT_SECRET = "client_secret"; 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.impl.client.HttpClients;
import org.apache.http.util.EntityUtils; import org.apache.http.util.EntityUtils;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; 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 topic=Topic
url=Broker Url url=Broker Url
url.hint=MQTT broker url
username=Username username=Username
username.hint=Username of the broker username.hint=Username of the broker
dcrUrl=dcrUrl password=Password
dcrUrl.hint=Dynamic Client Registration Url password.hint=Password to connect to the server.
scopes=scopes scopes=scopes
scopes.hint=Scopes that required to connect with the broker. scopes.hint=Scopes that required to connect with the broker.
url.hint=MQTT broker url
cleanSession=Clean Session cleanSession=Clean Session
cleanSession.hint=Persist topic subscriptions and ack positions across client sessions cleanSession.hint=Persist topic subscriptions and ack positions across client sessions
keepAlive=Keep Alive (In seconds) keepAlive=Keep Alive (In seconds)

@ -18,6 +18,13 @@
*/ */
package org.wso2.carbon.device.mgt.output.adapter.websocket; 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.device.mgt.output.adapter.websocket.util.UIEventAdapterConstants;
import org.wso2.carbon.event.output.adapter.core.MessageType; import org.wso2.carbon.event.output.adapter.core.MessageType;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapter; import org.wso2.carbon.event.output.adapter.core.OutputEventAdapter;
@ -38,6 +45,9 @@ public class UIEventAdapterFactory extends OutputEventAdapterFactory {
private ResourceBundle resourceBundle = ResourceBundle.getBundle("org.wso2.carbon.device.mgt.output.adapter.websocket.i18n" + private ResourceBundle resourceBundle = ResourceBundle.getBundle("org.wso2.carbon.device.mgt.output.adapter.websocket.i18n" +
".Resources", Locale.getDefault()); ".Resources", Locale.getDefault());
private BundleContext bundleContext;
private boolean isAuthInitialized = false;
private static final Log log = LogFactory.getLog(UIEventAdapter.class);
public UIEventAdapterFactory() { public UIEventAdapterFactory() {
} }
@ -74,7 +84,53 @@ public class UIEventAdapterFactory extends OutputEventAdapterFactory {
@Override @Override
public OutputEventAdapter createEventAdapter(OutputEventAdapterConfiguration eventAdapterConfiguration, public OutputEventAdapter createEventAdapter(OutputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) { Map<String, String> globalProperties) {
if (!isAuthInitialized) {
initializeAuthenticatorAndAuthorizor(globalProperties);
}
return new UIEventAdapter(eventAdapterConfiguration, 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 { 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. * Check whether the client is authenticated to connect.
* @param session user object.
* @return AuthenticationInfo which contains authentication client information. * @return AuthenticationInfo which contains authentication client information.
*/ */
AuthenticationInfo isAuthenticated(Map<String, List<String>> webSocketConnectionProperties); AuthenticationInfo isAuthenticated(Map<String, List<String>> webSocketConnectionProperties);

@ -20,8 +20,13 @@ import java.util.List;
import java.util.Map; import java.util.Map;
public class OAuthAuthenticator implements Authenticator { 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) { 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.logging.LogFactory;
import org.apache.commons.pool.impl.GenericObjectPool; 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.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.device.mgt.output.adapter.websocket.constants.WebsocketConstants;
import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub; 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;
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO_OAuth2AccessToken; import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO_OAuth2AccessToken;
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationResponseDTO; import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationResponseDTO;
import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.utils.CarbonUtils;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils; import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import java.io.File;
import java.io.IOException;
import java.rmi.RemoteException; import java.rmi.RemoteException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties;
/** /**
* This acts as a contract point for OAuth token validation. * This acts as a contract point for OAuth token validation.
@ -47,8 +41,6 @@ public class OAuthTokenValdiator {
private static String cookie; private static String cookie;
private GenericObjectPool stubs; private GenericObjectPool stubs;
private static Log log = LogFactory.getLog(OAuthTokenValdiator.class); 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_KEY_VALUE_SEPERATOR = "=";
private static final String COOKIE_KEYPAIR_SEPERATOR = ";"; private static final String COOKIE_KEYPAIR_SEPERATOR = ";";
private static final String COOKIE = "cookie"; private static final String COOKIE = "cookie";
@ -56,25 +48,9 @@ public class OAuthTokenValdiator {
private static final String TOKEN_IDENTIFIER = "websocket-token"; private static final String TOKEN_IDENTIFIER = "websocket-token";
private static OAuthTokenValdiator oAuthTokenValdiator; private static OAuthTokenValdiator oAuthTokenValdiator;
public static OAuthTokenValdiator getInstance() {
if (oAuthTokenValdiator == null) {
synchronized (OAuthTokenValdiator.class) {
if (oAuthTokenValdiator == null) {
oAuthTokenValdiator = new OAuthTokenValdiator();
}
}
}
return oAuthTokenValdiator;
}
private OAuthTokenValdiator() { public OAuthTokenValdiator(Map<String, String> globalProperties) {
try { this.stubs = new GenericObjectPool(new OAuthTokenValidaterStubFactory(globalProperties));
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);
}
} }
/** /**
@ -174,19 +150,6 @@ public class OAuthTokenValdiator {
return authenticationInfo; 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 * Retrieving the token from the http header
* @param webSocketConnectionProperties WebSocket connection information including http headers * @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.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.authentication.oauth.exception.OAuthTokenValidationException;
import org.wso2.carbon.device.mgt.output.adapter.websocket.constants.WebsocketConstants; 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 org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
import java.io.IOException; import java.io.IOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.security.GeneralSecurityException; 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. * 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 { public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
private static final Log log = LogFactory.getLog(OAuthTokenValidaterStubFactory.class); private static final Log log = LogFactory.getLog(OAuthTokenValidaterStubFactory.class);
private HttpClient httpClient; private HttpClient httpClient;
Properties tokenValidationProperties; Map<String, String> tokenValidationProperties;
public OAuthTokenValidaterStubFactory(Properties tokenValidationProperties) { public OAuthTokenValidaterStubFactory(Map<String, String> globalProperties) {
this.tokenValidationProperties = tokenValidationProperties; this.tokenValidationProperties = globalProperties;
this.httpClient = createHttpClient(); this.httpClient = createHttpClient();
} }
@ -91,51 +93,46 @@ public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
*/ */
private OAuth2TokenValidationServiceStub generateStub() throws OAuthTokenValidationException { private OAuth2TokenValidationServiceStub generateStub() throws OAuthTokenValidationException {
OAuth2TokenValidationServiceStub stub; OAuth2TokenValidationServiceStub stub;
try { try {
URL hostURL = new URL(tokenValidationProperties.getProperty((WebsocketConstants.TOKEN_VALIDATION_ENDPOINT_URL))); URL hostURL = new URL(PropertyUtils.replaceMqttProperty(tokenValidationProperties.get(
if (hostURL != null) { (WebsocketConstants.TOKEN_VALIDATION_ENDPOINT_URL)))
stub = new OAuth2TokenValidationServiceStub(hostURL.toString()); + WebsocketConstants.TOKEN_VALIDATION_CONTEXT);
if (stub != null) { stub = new OAuth2TokenValidationServiceStub(hostURL.toString());
ServiceClient client = stub._getServiceClient(); ServiceClient client = stub._getServiceClient();
client.getServiceContext().getConfigurationContext().setProperty( client.getServiceContext().getConfigurationContext().setProperty(
HTTPConstants.CACHED_HTTP_CLIENT, httpClient); HTTPConstants.CACHED_HTTP_CLIENT, httpClient);
HttpTransportProperties.Authenticator auth = HttpTransportProperties.Authenticator auth =
new HttpTransportProperties.Authenticator(); new HttpTransportProperties.Authenticator();
auth.setPreemptiveAuthentication(true); auth.setPreemptiveAuthentication(true);
String username = tokenValidationProperties.getProperty(WebsocketConstants.USERNAME); String username = tokenValidationProperties.get(WebsocketConstants.USERNAME);
String password = tokenValidationProperties.getProperty(WebsocketConstants.PASSWORD); String password = tokenValidationProperties.get(WebsocketConstants.PASSWORD);
auth.setPassword(username); auth.setPassword(username);
auth.setUsername(password); auth.setUsername(password);
Options options = client.getOptions(); Options options = client.getOptions();
options.setProperty(HTTPConstants.AUTHENTICATE, auth); options.setProperty(HTTPConstants.AUTHENTICATE, auth);
options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Constants.VALUE_TRUE); options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Constants.VALUE_TRUE);
client.setOptions(options); client.setOptions(options);
if (hostURL.getProtocol().equals("https")) { if (hostURL.getProtocol().equals("https")) {
// set up ssl factory since axis2 https transport is used. // set up ssl factory since axis2 https transport is used.
EasySSLProtocolSocketFactory sslProtocolSocketFactory = createProtocolSocketFactory(); EasySSLProtocolSocketFactory sslProtocolSocketFactory = createProtocolSocketFactory();
Protocol authhttps = new Protocol(hostURL.getProtocol() Protocol authhttps = new Protocol(hostURL.getProtocol()
, (ProtocolSocketFactory) sslProtocolSocketFactory, hostURL.getPort()); , (ProtocolSocketFactory) sslProtocolSocketFactory, hostURL.getPort());
Protocol.registerProtocol(hostURL.getProtocol(), authhttps); Protocol.registerProtocol(hostURL.getProtocol(), authhttps);
options.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, authhttps); options.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, authhttps);
} }
} else {
String errorMsg = "OAuth Validation instanization failed."; } catch (AxisFault axisFault) {
throw new OAuthTokenValidationException(errorMsg); throw new OAuthTokenValidationException(
} "Error occurred while creating the OAuth2TokenValidationServiceStub.", axisFault);
} else { } catch (MalformedURLException e) {
String errorMsg = "host url is invalid"; throw new OAuthTokenValidationException(
throw new OAuthTokenValidationException(errorMsg); "Error occurred while parsing token endpoint URL", e);
} } catch (OutputEventAdapterException e) {
} catch (AxisFault axisFault) { throw new OAuthTokenValidationException("Invalid token endpoint url", e);
throw new OAuthTokenValidationException( }
"Error occurred while creating the OAuth2TokenValidationServiceStub.", axisFault);
} catch (MalformedURLException e) {
throw new OAuthTokenValidationException(
"Error occurred while parsing token endpoint URL", e);
}
return stub; return stub;
} }
/** /**
@ -165,9 +162,9 @@ public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
*/ */
private HttpClient createHttpClient() { private HttpClient createHttpClient() {
HttpConnectionManagerParams params = new HttpConnectionManagerParams(); HttpConnectionManagerParams params = new HttpConnectionManagerParams();
params.setDefaultMaxConnectionsPerHost(Integer.parseInt(tokenValidationProperties.getProperty( params.setDefaultMaxConnectionsPerHost(Integer.parseInt(tokenValidationProperties.get(
WebsocketConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST))); WebsocketConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST)));
params.setMaxTotalConnections(Integer.parseInt(tokenValidationProperties.getProperty( params.setMaxTotalConnections(Integer.parseInt(tokenValidationProperties.get(
WebsocketConstants.MAXIMUM_TOTAL_HTTP_CONNECTION))); WebsocketConstants.MAXIMUM_TOTAL_HTTP_CONNECTION)));
HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
connectionManager.setParams(params); 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 org.wso2.carbon.device.mgt.output.adapter.websocket.authentication.AuthenticationInfo;
import javax.websocket.Session; import javax.websocket.Session;
import java.util.Map;
/** /**
* Check whether the client is authorized to connect. * Check whether the client is authorized to connect.
*/ */
public interface Authorizer { 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. * Check whether the client is authorized to connect with the stream.
* @param authenticationInfo authenticated client information. * @param authenticationInfo authenticated client information.

@ -31,13 +31,13 @@ import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.
.DeviceAccessAuthorizationAdminService; .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.DeviceAuthorizationResult;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.DeviceIdentifier; 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.util.PropertyUtils;
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.WebSocketSessionRequest; 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 javax.websocket.Session;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; 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 CDMF_SERVER_BASE_CONTEXT = "/api/device-mgt/v1.0";
private static final String DEVICE_MGT_SERVER_URL = "deviceMgtServerUrl"; private static final String DEVICE_MGT_SERVER_URL = "deviceMgtServerUrl";
private static final String STAT_PERMISSION = "statsPermission"; 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 Log logger = LogFactory.getLog(DeviceAuthorizer.class);
private static List<String> statPermissions; private static List<String> statPermissions;
public DeviceAuthorizer() { public DeviceAuthorizer() {
Properties properties = }
WebsocketConfig.getInstance().getWebsocketValidationConfigs().getAuthorizer().getProperties();
statPermissions = getPermissions(properties); @Override
deviceAccessAuthorizationAdminService = Feign.builder() public void init(Map<String, String> globalProperties) {
.requestInterceptor(new OAuthRequestInterceptor()) statPermissions = getPermissions(globalProperties);
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder()) try {
.target(DeviceAccessAuthorizationAdminService.class, getDeviceMgtServerUrl(properties) deviceAccessAuthorizationAdminService = Feign.builder()
+ CDMF_SERVER_BASE_CONTEXT); .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 @Override
public boolean isAuthorized(AuthenticationInfo authenticationInfo, Session session, String stream) { public boolean isAuthorized(AuthenticationInfo authenticationInfo, Session session, String stream) {
WebSocketSessionRequest webSocketSessionRequest = new WebSocketSessionRequest(session); WebSocketSessionRequest webSocketSessionRequest = new WebSocketSessionRequest(session);
Map<String, String> queryParams = webSocketSessionRequest.getQueryParamValuePairs(); Map<String, String> queryParams = webSocketSessionRequest.getQueryParamValuePairs();
String deviceId = queryParams.get("deviceId"); String deviceId = queryParams.get(DEVICE_ID);
String deviceType = queryParams.get("deviceType"); String deviceType = queryParams.get(DEVICE_TYPE);
if (deviceId != null && !deviceId.isEmpty() && deviceType != null && !deviceType.isEmpty()) { if (deviceId != null && !deviceId.isEmpty() && deviceType != null && !deviceType.isEmpty()) {
@ -102,27 +110,19 @@ public class DeviceAuthorizer implements Authorizer {
return false; return false;
} }
private String getDeviceMgtServerUrl(Properties properties) { private String getDeviceMgtServerUrl(Map<String, String> properties) throws OutputEventAdapterException {
String deviceMgtServerUrl = null; String deviceMgtServerUrl = PropertyUtils.replaceMqttProperty(properties.get(DEVICE_MGT_SERVER_URL));
for (Property property : properties.getProperty()) {
if (property.getName().equals(DEVICE_MGT_SERVER_URL)) {
deviceMgtServerUrl = property.getValue();
break;
}
}
if (deviceMgtServerUrl == null || deviceMgtServerUrl.isEmpty()) { if (deviceMgtServerUrl == null || deviceMgtServerUrl.isEmpty()) {
logger.error("deviceMgtServerUrl can't be empty "); logger.error("deviceMgtServerUrl can't be empty ");
} }
return deviceMgtServerUrl; return deviceMgtServerUrl;
} }
private List<String> getPermissions(Properties properties) { private List<String> getPermissions(Map<String, String> properties) {
List<String> permission = new ArrayList<>(); String stats = properties.get(STAT_PERMISSION);
for (Property property : properties.getProperty()) { if (stats != null && !stats.isEmpty()) {
if (property.getName().equals(STAT_PERMISSION)) { return Arrays.asList(stats.replace("\n", "").split(" "));
permission.add(property.getValue());
}
} }
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.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.ApiRegistrationProfile;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.TokenIssuerService; 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 java.util.Map;
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.WebsocketConfig;
/** /**
* This is a request interceptor to add oauth token header. * 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_USERNAME = "username";
private static final String CONNECTION_PASSWORD = "password"; 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 TOKEN_REFRESH_TIME_OFFSET = "tokenRefreshTimeOffset";
private static final String DEVICE_MGT_SERVER_URL = "deviceMgtServerUrl"; private static final String DEVICE_MGT_SERVER_URL = "deviceMgtServerUrl";
private static final String TOKEN_ENDPOINT_CONTEXT = "tokenEndpointContext";
private static String username; private static String username;
private static String password; private static String password;
private static String tokenEndpoint; private static String tokenEndpoint;
private static String deviceMgtServerUrl; private static String deviceMgtServerUrl;
private static Map<String, String> globalProperties;
/** /**
* Creates an interceptor that authenticates all requests. * Creates an interceptor that authenticates all requests.
*/ */
public OAuthRequestInterceptor() { public OAuthRequestInterceptor(Map<String, String> globalProperties) {
Properties properties = this.globalProperties = globalProperties;
WebsocketConfig.getInstance().getWebsocketValidationConfigs().getAuthorizer().getProperties(); deviceMgtServerUrl = getDeviceMgtServerUrl(globalProperties);
deviceMgtServerUrl = getDeviceMgtServerUrl(properties); refreshTimeOffset = getRefreshTimeOffset(globalProperties);
refreshTimeOffset = getRefreshTimeOffset(properties); username = getUsername(globalProperties);
username = getUsername(properties); password = getPassword(globalProperties);
password = getPassword(properties); tokenEndpoint = getTokenEndpoint(globalProperties);
tokenEndpoint = getTokenEndpoint(properties);
apiApplicationRegistrationService = Feign.builder().requestInterceptor( apiApplicationRegistrationService = Feign.builder().requestInterceptor(
new BasicAuthRequestInterceptor(username, password)) new BasicAuthRequestInterceptor(username, password))
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder()) .contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder())
@ -106,71 +107,42 @@ public class OAuthRequestInterceptor implements RequestInterceptor {
template.header("Authorization", headerValue); template.header("Authorization", headerValue);
} }
private String getUsername(Properties properties) { private String getUsername(Map<String, String> globalProperties) {
String username = null; String username = globalProperties.get(CONNECTION_USERNAME);
for (Property property : properties.getProperty()) {
if (property.getName().equals(CONNECTION_USERNAME)) {
username = property.getValue();
break;
}
}
if (username == null || username.isEmpty()) { if (username == null || username.isEmpty()) {
logger.error("username can't be empty "); logger.error("username can't be empty ");
} }
return username; return username;
} }
private String getPassword(Properties properties) { private String getPassword(Map<String, String> globalProperties) {
String password = null; String password = globalProperties.get(CONNECTION_PASSWORD);;
for (Property property : properties.getProperty()) {
if (property.getName().equals(CONNECTION_PASSWORD)) {
password = property.getValue();
break;
}
}
if (password == null || password.isEmpty()) { if (password == null || password.isEmpty()) {
logger.error("password can't be empty "); logger.error("password can't be empty ");
} }
return password; return password;
} }
private String getDeviceMgtServerUrl(Properties properties) { private String getDeviceMgtServerUrl(Map<String, String> globalProperties) {
String deviceMgtServerUrl = null; String deviceMgtServerUrl = globalProperties.get(DEVICE_MGT_SERVER_URL);
for (Property property : properties.getProperty()) {
if (property.getName().equals(DEVICE_MGT_SERVER_URL)) {
deviceMgtServerUrl = property.getValue();
break;
}
}
if (deviceMgtServerUrl == null || deviceMgtServerUrl.isEmpty()) { if (deviceMgtServerUrl == null || deviceMgtServerUrl.isEmpty()) {
logger.error("deviceMgtServerUrl can't be empty "); logger.error("deviceMgtServerUrl can't be empty ");
} }
return deviceMgtServerUrl; return deviceMgtServerUrl;
} }
private String getTokenEndpoint(Properties properties) { private String getTokenEndpoint(Map<String, String> globalProperties) {
String tokenEndpoint = null; String tokenEndpoint = globalProperties.get(TOKEN_ENDPOINT) + globalProperties.get(TOKEN_ENDPOINT_CONTEXT);
for (Property property : properties.getProperty()) { if ( tokenEndpoint.isEmpty()) {
if (property.getName().equals(TOKEN_ENDPOINT)) {
tokenEndpoint = property.getValue();
break;
}
}
if (tokenEndpoint == null || tokenEndpoint.isEmpty()) {
logger.error("tokenEndpoint can't be empty "); logger.error("tokenEndpoint can't be empty ");
} }
return tokenEndpoint; return tokenEndpoint;
} }
private long getRefreshTimeOffset(Properties properties) { private long getRefreshTimeOffset(Map<String, String> globalProperties) {
long refreshTimeOffset = 0; long refreshTimeOffset = 100;
try { try {
for (Property property : properties.getProperty()) { refreshTimeOffset = Long.parseLong(globalProperties.get(TOKEN_REFRESH_TIME_OFFSET));
if (property.getName().equals(TOKEN_REFRESH_TIME_OFFSET)) {
refreshTimeOffset = Long.parseLong(property.getValue());
break;
}
}
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
logger.error("refreshTimeOffset should be a number", 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 SCOPE_IDENTIFIER = "scopes";
public static final String MAXIMUM_TOTAL_HTTP_CONNECTION = "maximumTotalHttpConnection"; public static final String MAXIMUM_TOTAL_HTTP_CONNECTION = "maximumTotalHttpConnection";
public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST = "maximumHttpConnectionPerHost"; 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 USERNAME = "username";
public static final String PASSWORD = "password"; public static final String PASSWORD = "password";
public static final String TOKEN_PARAM = "token"; 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.osgi.service.component.ComponentContext;
import org.wso2.carbon.device.mgt.output.adapter.websocket.UIEventAdapterFactory; 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.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.event.output.adapter.core.OutputEventAdapterFactory;
import org.wso2.carbon.device.mgt.output.adapter.websocket.UIOutputCallbackControllerService; import org.wso2.carbon.device.mgt.output.adapter.websocket.UIOutputCallbackControllerService;
import org.wso2.carbon.event.stream.core.EventStreamService; import org.wso2.carbon.event.stream.core.EventStreamService;
@ -51,45 +45,20 @@ public class UILocalEventAdapterServiceComponent {
protected void activate(ComponentContext context) { protected void activate(ComponentContext context) {
try { try {
OutputEventAdapterFactory uiEventAdapterFactory = new UIEventAdapterFactory(); UIEventAdapterFactory uiEventAdapterFactory = new UIEventAdapterFactory();
context.getBundleContext().registerService(OutputEventAdapterFactory.class.getName(), uiEventAdapterFactory, null); context.getBundleContext().registerService(OutputEventAdapterFactory.class.getName(), uiEventAdapterFactory, null);
UIOutputCallbackControllerServiceImpl UIOutputCallbackRegisterServiceImpl = UIOutputCallbackControllerServiceImpl UIOutputCallbackRegisterServiceImpl =
new UIOutputCallbackControllerServiceImpl(); new UIOutputCallbackControllerServiceImpl();
context.getBundleContext().registerService(UIOutputCallbackControllerService.class.getName(), context.getBundleContext().registerService(UIOutputCallbackControllerService.class.getName(),
UIOutputCallbackRegisterServiceImpl, null); UIOutputCallbackRegisterServiceImpl, null);
uiEventAdapterFactory.setBundleContext(context.getBundleContext());
UIEventAdaptorServiceDataHolder.registerUIOutputCallbackRegisterServiceInternal( UIEventAdaptorServiceDataHolder.registerUIOutputCallbackRegisterServiceInternal(
UIOutputCallbackRegisterServiceImpl); UIOutputCallbackRegisterServiceImpl);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Successfully deployed the output websocket adapter service"); 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) { } catch (RuntimeException e) {
log.error("Can not create the output websocket adapter service ", e); log.error("Can not create the output websocket adapter service ", e);
} catch (Throwable 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 String ADAPTER_EVENT_QUEUE_SIZE_NAME = "eventQueueSize";
public static final int EVENTS_QUEUE_SIZE = 30; 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> <FileBasedProperties>true</FileBasedProperties>
<!--if file based properties is set to false then the configuration will be picked from platform configuration--> <!--if file based properties is set to false then the configuration will be picked from platform configuration-->
<ConfigProperties> <ConfigProperties>
<Property Name="mqtt.adapter.name">androidsense.mqtt.adapter</Property> <Property Name="mqttAdapterName">androidsense.mqtt.adapter</Property>
<Property Name="url">tcp://localhost:1886</Property>
<Property Name="username">admin</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="qos">0</Property>
<Property Name="scopes"/> <Property Name="scopes"/>
<Property Name="clearSession">true</Property> <Property Name="clearSession">true</Property>

@ -38,10 +38,9 @@
<FileBasedProperties>true</FileBasedProperties> <FileBasedProperties>true</FileBasedProperties>
<!--if file based properties is set to false then the configuration will be picked from platform configuration--> <!--if file based properties is set to false then the configuration will be picked from platform configuration-->
<ConfigProperties> <ConfigProperties>
<Property Name="mqtt.adapter.name">raspberrypi.mqtt.adapter</Property> <Property Name="mqttAdapterName">raspberrypi.mqtt.adapter</Property>
<Property Name="url">tcp://localhost:1886</Property>
<Property Name="username">admin</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="qos">0</Property>
<Property Name="scopes"/> <Property Name="scopes"/>
<Property Name="clearSession">true</Property> <Property Name="clearSession">true</Property>

@ -22,10 +22,9 @@
<!--MQTT Config--> <!--MQTT Config-->
<EventListenerProvider>MQTT</EventListenerProvider> <EventListenerProvider>MQTT</EventListenerProvider>
<Properties> <Properties>
<Property Name="mqtt.adapter.name">virtualfirealarm.mqtt.adapter</Property> <Property Name="mqttAdapterName">virtualfirealarm.mqtt.adapter</Property>
<Property Name="url">tcp://localhost:1886</Property>
<Property Name="username">admin</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="qos">0</Property>
<Property Name="scopes"/> <Property Name="scopes"/>
<Property Name="clearSession">true</Property> <Property Name="clearSession">true</Property>

@ -38,10 +38,9 @@
<FileBasedProperties>true</FileBasedProperties> <FileBasedProperties>true</FileBasedProperties>
<!--if file based properties is set to false then the configuration will be picked from platform configuration--> <!--if file based properties is set to false then the configuration will be picked from platform configuration-->
<ConfigProperties> <ConfigProperties>
<Property Name="mqtt.adapter.name">virtualfirealarm.mqtt.adapter</Property> <Property Name="mqttAdapterName">virtualfirealarm.mqtt.adapter</Property>
<Property Name="url">tcp://localhost:1886</Property>
<Property Name="username">admin</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="qos">0</Property>
<Property Name="scopes"/> <Property Name="scopes"/>
<Property Name="clearSession">true</Property> <Property Name="clearSession">true</Property>

Loading…
Cancel
Save