Merge pull request #133 from ayyoob/das-ext

cleaned up unnecessary configurations and added mqtt authorization
application-manager-new
Milan Perera 9 years ago
commit 016c51474f

@ -1,164 +1,234 @@
<!--
~ Copyright 2005-2010 WSO2, Inc. (http://wso2.com)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<html>
<head>
<meta http-equiv="content-type" content=""/>
<title>WSO2 Enterprise Mobility Manager ${product.version} Release Notes</title>
<link href="./tools/cmd/css/gs-dist-doc.css" rel="stylesheet"
type="text/css" media="all"/>
</head>
<body>
<h1>Enterprise Mobility Manager ${product.version} Release Notes</h1>
<p>
WSO2 Enterprise Mobility Manager (EMM) is a unique solution designed to specifically address the mobile enterprise needs. EMM includes of two key aspects:
Mobile Device Management (MDM) and Mobile Application Management (MAM). WSO2 EMM also supports single sign-on (SSO) and multi-tenancy.
</p>
<p>
EMM enables organizations to secure, manage and monitor Android and iOS powered devices (i.e., smart phones, ipod touch devices and tablet PCs), irrespective of the mobile operator, service provider, or the organization. Users need to accept the Policy agreement, which states all the actions that can be carried out on the device when enrolling with EMM. EMM only controls the corporate data that is present on the devices, while the personal data is left untouched.
</p>
<h3>
What is new in this release
</h3>
<p>
<b>First user experience</b>
</p>
<p>
In the previous WSO2 EMM releases it was mandatory for the users to fully configure WSO2 EMM before being able to run the product. Now, WSO2 EMM 1.1.0
binary pack comprises of a default Android Agent. Thereby, enabling users to seamlessly download and run EMM without any prior configurations. This will
allow users to use Android devices to get a better understanding of WSO2 EMM.
</p>
<p>
<b>Local notification method for Android devices</b>
</p>
<p>
The GCM server has a limitation on the number of messages that can be sent to the GCM server. However, this new Local notification method for Android
devices does not make use of the GCM server. Thereby, the number of messages sent via the GCM will be minimized. Furthermore, the Local notification method
does not send the messages via the payload, as it did in previous EMM versions. Thereby, this will minimize the MDM command loss.
</p>
<p>
<b>Tenant based configuration</b>
</p>
<p>
The tenant admin will be able to use the Configuration Manager wizard to setup the tenant's general, Android and iOS configuration details. Thereby, this
allows each tenant to customize their settings based on their requirements. For more information, see Tenant Based Settings.
</p>
<p>
<b>Ability to change password</b>
</p>
<p>
Previously, users were not allowed to change the default password that was assigned by WSO2 EMM. However, now users are allowed to change their password.
Thereby, users will be able to change their default password to a password of their choice.
</p>
<p>
<b>Removal of devices from WSO2 EMM</b>
</p>
<p>
Previously, administrators were not allowed to remove devices from WSO2 EMM after they were enrolled. However, now the administrators can use the
Enterprise Wipe feature to remove enrolled devices from WSO2 EMM. Thereby, this will enable the administrators to maintain WSO2 EMM efficiently.
</p>
<p>
<b>Improved API security</b>
</p>
<p>
The APIs that are exposed to the devices have been secured in WSO2 EMM using OAuth.
</p>
<p>
<b>Improved compliance monitoring</b>
</p>
<p>
When the system is clustered, then using the nTask Component, only one node will be allowed to perform the compliance monitoring that will dispatch
messages to the GCM or APNS.
</p>
<h2>Features</h2>
<ul>
<li>Self-service device enrollment and management with end-user MDM console</li>
<li>Policy-driven device management for security, data, and device features (Camera, Password Policy)</li>
<li>Deploy policies over-the-air</li>
<li>Compliance monitoring for reporting, alerting, and device deprovisioning</li>
<li>Role based permissions for device management</li>
<li>Provisioning and deprovisioning applications to enrolled devices</li>
<li>Blacklisting of applications for Android</li>
<li>Supports App management</li>
<li>App approval process through a lifecycle</li>
<li>Discover mobile apps through an Enterprise App Store</li>
<li>Self-provisioning of mobile apps to devices</li>
</ul>
<p>
<b>Bug Fixes / Improvements</b>
</p>
<p>
For the list of fixed issues, go to <a href="https://wso2.org/jira/issues/?filter=11896">WSO2 EMM 1.1.0 - Fixed Issues</a>.
</p>
<p>
<b>Known Issues</b>
</p>
<p>
For the list of known issues, go to <a href="https://wso2.org/jira/issues/?filter=11894">WSO2 EMM 1.1.0 - Known Issues</a>.
</p>
<p>
<b>Reporting Problems</b>
</p>
<p>
Issues can be reported using the <a href="https://wso2.org/jira/browse/EMM"> public JIRA</a>.
</p>
<p>
<b>Engaging with Community</b>
</p>
<p>
<b>Mailing Lists</b>
</p>
<p>
Join our mailing list and correspond with the developers directly.
</p>
<p>
Developer List : dev@wso2.org | Subscribe |<a href="http://wso2.org/mailarchive/dev/"> Mail Archive</a>
</p>
<p>
<b>Reporting Issues</b>
</p>
<p>
WSO2 encourages you to report issues, enhancements and feature requests for WSO2 EMM. Use the <a href="https://wso2.org/jira/browse/EMM">issue tracker</a>
for reporting issues.
</p>
<p>
<b>Discussion Forums</b>
</p>
<p>
We encourage to use <a href="http://stackoverflow.com/tags/wso2/">stackoverflow</a> to engage with developers as well as other users.
</p>
<p>
<b>Support</b>
</p>
<p>
We are committed to ensuring that your enterprise middleware deployment is completely supported from evaluation to production. Our unique approach ensures
that all support leverages our open development methodology and is provided by the very same engineers who build the technology.
</p>
<p>
For additional support information please refer to <a href="http://wso2.com/support/">http://wso2.com/support/</a>
</p>
<p>
We welcome your feedback and would love to hear your thoughts on this release of WSO2 EMM.
</p>
<p>
--WSO2 EMM Development Team--
</p>
<body lang=EN-US link=blue vlink=purple style='tab-interval:36.0pt'>
<div class=WordSection1>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph'><b><u><span
style='font-family:Arial;mso-fareast-font-family:"Times New Roman";mso-bidi-font-family:
"Times New Roman";color:#333333'>WSO2 <span class=SpellE>IoT</span> Server
1.0.0&nbsp;Alpha&nbsp;Released</span></u></b><span style='font-family:Arial;
mso-fareast-font-family:"Times New Roman";mso-bidi-font-family:"Times New Roman";
color:#222222'><o:p></o:p></span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph'><span
style='font-family:Arial;mso-fareast-font-family:"Times New Roman";mso-bidi-font-family:
"Times New Roman";color:#222222'>We are pleased to announce WSO2 <span
class=SpellE>IoT</span> Server 1.0.0&nbsp;alpha&nbsp;release. It can be
downloaded from<a
href="https://github.com/wso2-incubator/product-iot-server/releases/tag/IoTS-1.0.0-M3"><span
style='color:#1155CC'>https://github.com/wso2-incubator/product-iot-server/releases/tag/IoTS-1.0.0-</span></a>alpha<o:p></o:p></span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph'><span
style='font-family:Arial;mso-fareast-font-family:"Times New Roman";mso-bidi-font-family:
"Times New Roman";color:#222222'><o:p>&nbsp;</o:p></span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph'><span
style='font-family:Arial;mso-bidi-font-family:"Times New Roman";color:black'>WSO2
<span class=SpellE>IoT</span> Server is an extensible, open-source, multi
tenant, Internet of Things Platform for implementing server-side of <span
class=SpellE>IoT</span> Reference Architecture. It comes with a few reference
implementations for the device layer.</span><span style='font-family:Arial;
mso-bidi-font-family:"Times New Roman";color:#222222'><o:p></o:p></span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph'><span
style='font-family:Arial;mso-bidi-font-family:"Times New Roman";color:black'><br
style='mso-special-character:line-break'>
</p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph'><span
style='font-family:Arial;mso-bidi-font-family:"Times New Roman";color:black'>WSO2
<span class=SpellE>IoT</span> Server supports:</span><span style='font-family:
Arial;mso-bidi-font-family:"Times New Roman";color:#222222'><o:p></o:p></span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph'><span
style='font-family:Arial;mso-bidi-font-family:"Times New Roman";color:#222222'><o:p>&nbsp;</o:p></span></p>
<p class=MsoNormal style='margin-left:18.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l1 level1 lfo1;tab-stops:list 6.75pt;
vertical-align:baseline'><b><span
style='font-family:Arial;mso-bidi-font-family:"Times New Roman";color:black'>Device
Management<o:p></o:p></span></b></p>
<p class=MsoNormal style='margin-left:54.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l1 level2 lfo1;tab-stops:list 72.0pt;
vertical-align:baseline'><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Extensions for registering device types<o:p></o:p></span></p>
<p class=MsoNormal style='margin-left:54.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l1 level2 lfo1;tab-stops:list 72.0pt;
vertical-align:baseline'><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Self-service enrolment and management of
connected devices<o:p></o:p></span></p>
<p class=MsoNormal style='margin-left:54.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l1 level2 lfo1;tab-stops:list 72.0pt;
vertical-align:baseline'><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Group, manage and monitor connected devices<o:p></o:p></span></p>
<p class=MsoNormal style='margin-left:54.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l1 level2 lfo1;tab-stops:list 72.0pt;
vertical-align:baseline'><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Share device operations / data with other users<o:p></o:p></span></p>
<p class=MsoNormal style='margin-left:54.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l1 level2 lfo1;tab-stops:list 72.0pt;
vertical-align:baseline'><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Distribution and management of applications and
firmware to devices<o:p></o:p></span></p>
<p class=MsoNormal style='margin-left:54.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l1 level2 lfo1;tab-stops:list 72.0pt;
vertical-align:baseline'><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Edge computing powered by WSO2 CEP streaming
engine (Siddhi - <a href="https://github.com/wso2/siddhi"><span
style='color:#1155CC'>https://github.com/wso2/siddhi</span></a>)<o:p></o:p></span></p>
<p class=MsoNormal style='margin-left:54.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l1 level2 lfo1;tab-stops:list 72.0pt;
vertical-align:baseline'><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>OOTB support for some known device types such as
Raspberry Pi, <span class=SpellE>Arduino</span> Uno, Android<o:p></o:p></span></p>
<p class=MsoNormal style='margin-left:18.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l0 level1 lfo2;tab-stops:list 36.0pt;
vertical-align:baseline'><span class=SpellE><b><span style='font-family:
Arial;mso-bidi-font-family:"Times New Roman";color:black'>IoT</span></b></span><b><span
style='font-family:Arial;mso-bidi-font-family:"Times New Roman";color:black'>
Protocol Support<o:p></o:p></span></b></p>
<p class=MsoNormal style='margin-left:54.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l0 level2 lfo2;tab-stops:list 72.0pt;
vertical-align:baseline'><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Leverage MQTT, HTTP, <span class=SpellE>Websockets</span>
and XMPP protocols for device communications with <span class=SpellE>IoT</span>
Server<o:p></o:p></span></p>
<p class=MsoNormal style='margin-left:54.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l0 level2 lfo2;tab-stops:list 72.0pt;
vertical-align:baseline'><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Framework extension for adding more protocols
and data formats<o:p></o:p></span></p>
<p class=MsoNormal style='margin-left:18.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l0 level1 lfo2;tab-stops:list 36.0pt;
vertical-align:baseline'><b><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Analytics<o:p></o:p></span></b></p>
<p class=MsoNormal style='margin-left:54.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l0 level2 lfo2;tab-stops:list 72.0pt;
vertical-align:baseline'><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Support for batch, interactive, real-time and
predictive analytics through WSO2 DAS<o:p></o:p></span></p>
<p class=MsoNormal style='margin-left:18.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l0 level1 lfo2;tab-stops:list 36.0pt;
vertical-align:baseline'><b><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Pre-built <span class=SpellE>visualisation</span>
support for sensor readings<o:p></o:p></span></b></p>
<p class=MsoNormal style='margin-left:54.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l0 level2 lfo2;tab-stops:list 72.0pt;
vertical-align:baseline'><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>View instant, <span class=SpellE>visualised</span>
statistics of individual or multiple devices<o:p></o:p></span></p>
<p class=MsoNormal style='margin-left:54.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l0 level2 lfo2;tab-stops:list 72.0pt;
vertical-align:baseline'><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Traverse through, <span class=SpellE>analyse</span>
and zoom in/out of filtered data<o:p></o:p></span></p>
<p class=MsoNormal style='margin-left:54.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l0 level2 lfo2;tab-stops:list 72.0pt;
vertical-align:baseline'><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Stats-API to write your own <span class=SpellE>visualisation</span><o:p></o:p></span></p>
<p class=MsoNormal style='margin-left:54.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l0 level2 lfo2;tab-stops:list 72.0pt;
vertical-align:baseline'><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Pre-built graphs for common sensor reading types
like temperature, velocity<o:p></o:p></span></p>
<p class=MsoNormal style='margin-left:18.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l0 level1 lfo2;tab-stops:list 36.0pt;
vertical-align:baseline'><b><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>API Management for App Development<o:p></o:p></span></b></p>
<p class=MsoNormal style='margin-left:54.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l0 level2 lfo2;tab-stops:list 72.0pt;
vertical-align:baseline'><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Devices are represented as REST APIs<o:p></o:p></span></p>
<p class=MsoNormal style='margin-left:54.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l0 level2 lfo2;tab-stops:list 72.0pt;
vertical-align:baseline'><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Develop applications using Device APIs<o:p></o:p></span></p>
<p class=MsoNormal style='margin-left:18.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l0 level1 lfo2;tab-stops:list 36.0pt;
vertical-align:baseline'><b><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Identity and Access Management<o:p></o:p></span></b></p>
<p class=MsoNormal style='margin-left:54.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l0 level2 lfo2;tab-stops:list 72.0pt;
vertical-align:baseline'><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Identity Management for devices<o:p></o:p></span></p>
<p class=MsoNormal style='margin-left:54.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:-18.0pt;mso-list:l0 level2 lfo2;tab-stops:list 72.0pt;
vertical-align:baseline'><span style='font-family:Arial;mso-bidi-font-family:
"Times New Roman";color:black'>Token based access control for devices &amp;
operations (protect back end services via exposing device type APIs)<o:p></o:p></span></p>
<p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;
margin-left:54.0pt;text-align:justify;text-justify:inter-ideograph;text-indent:
-18.0pt;mso-list:l0 level2 lfo2;tab-stops:list 72.0pt;vertical-align:baseline'><span style='font-family:Arial;mso-fareast-font-family:
"Times New Roman";mso-bidi-font-family:"Times New Roman";color:black'>Support
for SCEP protocol (encryption and authenticity)<o:p></o:p></span></p>
<p class=MsoNormal><span style='font-family:Arial;mso-fareast-font-family:"Times New Roman";
mso-bidi-font-family:"Times New Roman";color:black'><br>
</span><span style='font-family:Arial;mso-fareast-font-family:"Times New Roman";
mso-bidi-font-family:"Times New Roman";color:#333333'>List of known issues</span><span
style='font-family:Arial;mso-fareast-font-family:"Times New Roman";mso-bidi-font-family:
"Times New Roman";color:#222222'><br style='mso-special-character:line-break'>
<o:p></o:p></span></p>
<p class=MsoNormal><span style='font-family:Symbol;mso-ascii-font-family:Arial;
mso-fareast-font-family:"Times New Roman";mso-bidi-font-family:"Times New Roman";
color:#222222'>á</span><span style='font-family:Arial;mso-fareast-font-family:
"Times New Roman";mso-bidi-font-family:"Times New Roman";color:#222222'><span
style="mso-spacerun:yes">&nbsp; </span><a
href="https://wso2.org/jira/issues/?filter=13055"><span style='color:#1155CC'>https://wso2.org/jira/issues/?filter=13055</span></a><o:p></o:p></span></p>
<p class=MsoNormal><span style='font-family:Arial;mso-fareast-font-family:"Times New Roman";
mso-bidi-font-family:"Times New Roman";color:#222222'><o:p>&nbsp;</o:p></span></p>
<p class=MsoNormal><span style='font-family:Arial;mso-fareast-font-family:"Times New Roman";
mso-bidi-font-family:"Times New Roman";color:#222222'><o:p>&nbsp;</o:p></span></p>
<p class=MsoNormal><span style='font-family:Arial;mso-fareast-font-family:"Times New Roman";
mso-bidi-font-family:"Times New Roman";color:black'>Thanks and Regards,</span><span
style='font-family:Arial;mso-fareast-font-family:"Times New Roman";mso-bidi-font-family:
"Times New Roman";color:#222222'><o:p></o:p></span></p>
<p class=MsoNormal><span style='font-family:Arial;mso-fareast-font-family:"Times New Roman";
mso-bidi-font-family:"Times New Roman";color:#222222'><o:p>&nbsp;</o:p></span></p>
<p class=MsoNormal><b><span style='font-family:Arial;mso-fareast-font-family:
"Times New Roman";mso-bidi-font-family:"Times New Roman";color:black'>~ EMM / <span
class=SpellE>IoTS</span> Team ~</span></b><span style='font-family:Arial;
mso-fareast-font-family:"Times New Roman";mso-bidi-font-family:"Times New Roman";
color:#222222'><o:p></o:p></span></p>
<p class=MsoNormal><o:p>&nbsp;</o:p></p>
</div>
</body>
</html>

@ -1257,17 +1257,17 @@
</file>
<file>
<source>
../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/iot/devicemgt-config.xml
../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/etc/mqtt.properties
</source>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf/iot</outputDirectory>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf/etc</outputDirectory>
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<file>
<source>
../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/iot/devicemgt-config.xsd
../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/etc/xmpp.properties
</source>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf/iot</outputDirectory>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf/etc</outputDirectory>
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
@ -1313,5 +1313,14 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!-- Copying remote-appmanager-config.xml -->
<file>
<source>
../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/etc/remote-appmanager-config.xml
</source>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf/etc</outputDirectory>
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
</files>
</assembly>

@ -136,15 +136,14 @@ This file is ciphertool compliant. Refer PRODUCT_HOME/repository/conf/security/c
REQUIRED: Clients will authorized before publishing. this will execute the class given in authorzier
Note: authentication should be REQUIRED for authorization to be REQUIRED.
-->
<authorization>NOT_REQUIRED</authorization>
<authorization>REQUIRED</authorization>
<!--Class name of the authorizer to use. class should
inherit from org.dna.mqtt.moquette.server.IAutherizer
Note: default implementation authorizes against carbon permission with the topic.
-->
<!--connectionPermission is required for a user to connect to broker-->
<authorizer class="org.wso2.carbon.andes.authorization.andes.CarbonPermissionBasedMQTTAuthorizer">
<property name="connectionPermission">/permission/admin/mqtt/connect</property>
<authorizer class="org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.DeviceAccessBasedMQTTAuthorizer">
</authorizer>
</security>
</mqtt>

@ -107,114 +107,20 @@
</definition>
</datasource>
<!--<datasource>-->
<!--<name>WSO2_IDENTITY_DB</name>-->
<!--<description>The datasource used for Identity configurations</description>-->
<!--<jndiConfig>-->
<!--<name>jdbc/WSO2IdentityDB</name>-->
<!--</jndiConfig>-->
<!--<definition type="RDBMS">-->
<!--<configuration>-->
<!--<url>jdbc:h2:repository/database/WSO2IDENTITY_DB;DB_CLOSE_ON_EXIT=FALSE</url>-->
<!--<username>wso2carbon</username>-->
<!--<password>wso2carbon</password>-->
<!--<driverClassName>org.h2.Driver</driverClassName>-->
<!--<maxActive>50</maxActive>-->
<!--<maxWait>60000</maxWait>-->
<!--<testOnBorrow>true</testOnBorrow>-->
<!--<validationQuery>SELECT 1</validationQuery>-->
<!--<validationInterval>30000</validationInterval>-->
<!--</configuration>-->
<!--</definition>-->
<!--</datasource>-->
<!--<datasource>-->
<!--<name>SOCIAL_CACHE</name>-->
<!--<description>The datasource used for storing the cached social objects.</description>-->
<!--<jndiConfig>-->
<!--<name>jdbc/test</name>-->
<!--</jndiConfig>-->
<!--<definition type="RDBMS">-->
<!--<configuration>-->
<!--<url>jdbc:h2:repository/database/WSO2SOCIAL_CACHE_DB;DB_CLOSE_ON_EXIT=FALSE</url>-->
<!--<username>wso2carbon</username>-->
<!--<password>wso2carbon</password>-->
<!--<driverClassName>org.h2.Driver</driverClassName>-->
<!--<maxActive>50</maxActive>-->
<!--<maxWait>60000</maxWait>-->
<!--</configuration>-->
<!--</definition>-->
<!--</datasource>-->
<!--<datasource>-->
<!--<name>SOCIAL_CASSANDRA_DB</name>-->
<!--<description>The cassandra datasource used for storing social activities</description>-->
<!--<definition type="RDBMS">-->
<!--<configuration>-->
<!--<url>jdbc:cassandra://localhost:9160/EVENT_KS</url>-->
<!--<username>admin@admin.com</username>-->
<!--<password>admin</password>-->
<!--<driverClassName>org.apache.cassandra.cql.jdbc.CassandraDriver</driverClassName>-->
<!--</configuration>-->
<!--</definition>-->
<!--</datasource>-->
<!--<datasource>-->
<!--<name>JAGH2</name>-->
<!--<description>The datasource used for by the Jaggery Storage Manager</description>-->
<!--<jndiConfig>-->
<!--<name>jdbc/test</name>-->
<!--</jndiConfig>-->
<!--<definition type="RDBMS">-->
<!--<configuration>-->
<!--<url>jdbc:h2:~/test;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=60000</url>-->
<!--<username>sa</username>-->
<!--<password></password>-->
<!--<driverClassName>org.h2.Driver</driverClassName>-->
<!--<maxActive>50</maxActive>-->
<!--<maxWait>60000</maxWait>-->
<!--</configuration>-->
<!--</definition>-->
<!--</datasource>-->
<datasource>
<name>JAGH2</name>
<description>The datasource used for by the Jaggery Storage Manager</description>
<jndiConfig>
<name>jdbc/test</name>
</jndiConfig>
<definition type="RDBMS">
<configuration>
<url>jdbc:h2:~/test;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=60000</url>
<username>sa</username>
<password></password>
<driverClassName>org.h2.Driver</driverClassName>
<maxActive>50</maxActive>
<maxWait>60000</maxWait>
</configuration>
</definition>
</datasource>
<!-- *****Replace ${BAM_HOME} in `url` element with your WSO2 BAM home directory.***** -->
<datasource>
<name>WSO2IOT_STATS_DB</name>
<jndiConfig>
<name>jdbc/WSO2IOT_STATS_DB</name>
<name>jdbc/ES_Storage</name>
</jndiConfig>
<description>The datasource used for analyzer data</description>
<definition type="RDBMS">
<configuration>
<url>jdbc:h2:$/repository/database/IOT_STATS_DB;AUTO_SERVER=TRUE</url>
<!--url>jdbc:h2:${BAM_HOME}/repository/database/IOT_STATS_DB;AUTO_SERVER=TRUE</url-->
<url>jdbc:h2:repository/database/ES_STORAGE;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=60000</url>
<username>wso2carbon</username>
<password>wso2carbon</password>
<driverClassName>org.h2.Driver</driverClassName>
<maxActive>50</maxActive>
<maxWait>60000</maxWait>
<testOnBorrow>true</testOnBorrow>
<validationQuery>SELECT 1</validationQuery>
<validationInterval>30000</validationInterval>
</configuration>
</definition>
</datasource>

@ -175,4 +175,42 @@ log4j.appender.ATOMIKOS.layout.ConversionPattern=%p %t %c - %m%n
handlers=java.util.logging.ConsoleHandler
# Replacing default INFO level with SEVERE
java.util.logging.ConsoleHandler.level=SEVERE
java.util.logging.ConsoleHandler.level=SEVERE
#andes specific
log4j.logger.org.wso2.andes.server.handler.ConnectionStartOkMethodHandler=WARN
log4j.logger.org.wso2.andes.server.handler.ChannelOpenHandler=WARN
log4j.logger.org.wso2.andes.server.handler.ChannelCloseHandler=WARN
log4j.logger.org.wso2.andes.server.AMQChannel=WARN
log4j.logger.org.wso2.andes.server.handler.ConnectionCloseMethodHandler=WARN
log4j.logger.org.wso2.andes.server.handler.QueueDeclareHandler=WARN
log4j.logger.org.wso2.andes.server.handler.QueueBindHandler=WARN
log4j.logger.org.wso2.andes.server.virtualhost.VirtualHostConfigRecoveryHandler=WARN
log4j.logger.org.wso2.andes.amqp.QpidAndesBridge=WARN
# moquette-log properties
log4j.logger.org.dna.mqtt=INFO
log4j.logger.org.dna.mqtt.moquette.messaging.spi.impl.ProtocolProcessor=INFO
log4j.logger.org.dna.mqtt.moquette.messaging.spi.impl.SimpleMessaging=WARN
#Protocol parsing
log4j.logger.org.dna.mqtt.moquette.server.netty.NettyMQTTHandler=WARN
#log4j.logger.org.dna.mqtt.moquette.server.netty.NettyMQTTHandler=DEBUG
log4j.logger.org.dna.mqtt.moquette.parser.netty=WARN
# The event trace logger dumps enough information @INFO level, but maybe pushed upto TRACE.
# Writes only run-time/event processing time tracing/debug messages for event passing through trace
# enabled transport adapters event formatters, builders and processors. Enabling event tracing on these has a performance impact
log4j.category.EVENT_TRACE_LOGGER=INFO, EVENT_TRACE_APPENDER, EVENT_TRACE_MEMORYAPPENDER
log4j.additivity.EVENT_TRACE_LOGGER=false
log4j.appender.EVENT_TRACE_APPENDER=org.apache.log4j.DailyRollingFileAppender
log4j.appender.EVENT_TRACE_APPENDER.File=${carbon.home}/repository/logs/${instance.log}/wso2-das-trace${instance.log}.log
log4j.appender.EVENT_TRACE_APPENDER.Append=true
log4j.appender.EVENT_TRACE_APPENDER.layout=org.apache.log4j.PatternLayout
log4j.appender.EVENT_TRACE_APPENDER.layout.ConversionPattern=%d{HH:mm:ss,SSS} [%X{ip}-%X{host}] [%t] %5p %c{1} %m%n
# The memory appender for trace logger
log4j.appender.EVENT_TRACE_MEMORYAPPENDER=org.wso2.carbon.utils.logging.appenders.MemoryAppender
log4j.appender.EVENT_TRACE_MEMORYAPPENDER.bufferSize=2000
log4j.appender.EVENT_TRACE_MEMORYAPPENDER.layout=org.apache.log4j.PatternLayout
log4j.appender.EVENT_TRACE_MEMORYAPPENDER.layout.ConversionPattern=%d{HH:mm:ss,SSS} [%X{ip}-%X{host}] [%t] %5p %m%n

@ -1,167 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
~
~ WSO2 Inc. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>das-extensions</artifactId>
<groupId>org.wso2.iot</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.event.input.adapter.extensions</artifactId>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Event Input MQTT Adapter Module</name>
<description>This provides the capability of connecting to existing broker that supports OAUTH</description>
<url>http://wso2.org</url>
<dependencies>
<dependency>
<groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.input.adapter.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.logging</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.core</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.wso2</groupId>
<artifactId>httpcore</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.orbit.org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple.wso2</groupId>
<artifactId>json-simple</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity</groupId>
<artifactId>org.wso2.carbon.identity.oauth.stub</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<executions>
<execution>
<id>generate-scr-descriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Private-Package>
org.wso2.carbon.event.input.adapter.extensions.internal,
org.wso2.carbon.event.input.adapter.extensions.internal.*
</Private-Package>
<Export-Package>
!org.wso2.carbon.event.input.adapter.extensions.internal,
!org.wso2.carbon.event.input.adapter.extensions.internal.*,
org.wso2.carbon.event.input.adapter.extensions.*
</Export-Package>
<Import-Package>
org.wso2.carbon.event.input.adapter.core,
org.wso2.carbon.event.input.adapter.core.*,
javax.xml.namespace; version=0.0.0,
org.eclipse.paho.client.mqttv3.*,
org.apache.http;version="${httpclient.version.range}",
org.apache.http.message;version="${httpclient.version.range}",
org.apache.http.client;version="${httpclient.version.range}",
org.apache.http.impl;version="${httpclient.version.range}",
org.apache.http.conn.*;version="${httpclient.version.range}",
org.apache.http.util;version="${httpclient.version.range}",
org.apache.http.client.entity;version="${httpclient.version.range}",
org.apache.http.client.methods;version="${httpclient.version.range}",
org.apache.http.impl.client;version="${httpclient.version.range}",
org.json.simple.*,
org.wso2.carbon.identity.jwt.client.extension.*,
com.jayway.jsonpath.*,
javax.net.ssl,
org.apache.commons.logging,
org.apache.http.entity,
org.osgi.framework,
org.osgi.service.component,
org.wso2.carbon.context,
org.wso2.carbon.core,
javax.servlet,
javax.servlet.http,
org.apache.axiom.om.util,
org.osgi.service.http,
org.wso2.carbon.user.api,
org.wso2.carbon.user.core.service,
org.wso2.carbon.user.core.tenant,
org.wso2.carbon.utils,
org.wso2.carbon.utils.multitenancy,
org.wso2.carbon.identity.oauth2.stub;version="${carbon.identity.version.range}",
org.wso2.carbon.identity.oauth2.stub.dto;version="${carbon.identity.version.range}",
org.apache.axis2,
org.apache.axis2.client,
org.apache.axis2.context,
org.apache.axis2.transport.http,
org.apache.commons.httpclient,
org.apache.commons.httpclient.contrib.ssl,
org.apache.commons.httpclient.params,
org.apache.commons.httpclient.protocol,
org.apache.commons.pool,
org.apache.commons.pool.impl,
org.apache.log4j,
org.wso2.carbon.base,
org.wso2.carbon.core.util
</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -1,55 +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.event.input.adapter.extensions;
/**
* This is the return type of the ContentValidator.
*/
public class ContentInfo {
/**
* true if the content is valid if not when false then content will not be published.
*/
private boolean isValidContent;
/**
* msgText to be returned. eg: if the content is encrypted then we can decrypt the content and then validate and
* return it.
*/
private String msgText;
public ContentInfo(boolean isValidContent, String msgText) {
this.isValidContent = isValidContent;
this.msgText = msgText;
}
public boolean isValidContent() {
return isValidContent;
}
public void setIsValidContent(boolean isValidContent) {
this.isValidContent = isValidContent;
}
public String getMsgText() {
return msgText;
}
public void setMsgText(String msgText) {
this.msgText = msgText;
}
}

@ -1,33 +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.event.input.adapter.extensions;
import java.util.Map;
/**
* This interface will be triggered to validate the stream content before publishing.
*/
public interface ContentValidator {
/**
*
* @param params that related to input adapter to identify the client and the content
* @return
*/
ContentInfo validate(String msgPayload, Map<String, String> params);
}

@ -1,213 +0,0 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.wso2.carbon.event.input.adapter.extensions.http;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapter;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterListener;
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterException;
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterRuntimeException;
import org.wso2.carbon.event.input.adapter.core.exception.TestConnectionNotSupportedException;
import org.wso2.carbon.event.input.adapter.extensions.http.util.HTTPEventAdapterConstants;
import org.wso2.carbon.event.input.adapter.extensions.internal.EventAdapterServiceDataHolder;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import javax.servlet.ServletException;
import java.util.Hashtable;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public final class HTTPEventAdapter implements InputEventAdapter {
private final InputEventAdapterConfiguration eventAdapterConfiguration;
private final Map<String, String> globalProperties;
private InputEventAdapterListener eventAdaptorListener;
private final String id = UUID.randomUUID().toString();
public static ExecutorService executorService;
private static final Log log = LogFactory.getLog(HTTPEventAdapter.class);
private boolean isConnected = false;
public HTTPEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
this.eventAdapterConfiguration = eventAdapterConfiguration;
this.globalProperties = globalProperties;
}
@Override
public void init(InputEventAdapterListener eventAdaptorListener) throws InputEventAdapterException {
this.eventAdaptorListener = eventAdaptorListener;
//ThreadPoolExecutor will be assigned if it is null
if (executorService == null) {
int minThread;
int maxThread;
long defaultKeepAliveTime;
int jobQueueSize;
//If global properties are available those will be assigned else constant values will be assigned
if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME) != null) {
minThread = Integer
.parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME));
} else {
minThread = HTTPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE;
}
if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME) != null) {
maxThread = Integer
.parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME));
} else {
maxThread = HTTPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE;
}
if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME) != null) {
defaultKeepAliveTime = Integer
.parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME));
} else {
defaultKeepAliveTime = HTTPEventAdapterConstants.DEFAULT_KEEP_ALIVE_TIME_IN_MILLS;
}
if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME) != null) {
jobQueueSize = Integer
.parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME));
} else {
jobQueueSize = HTTPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE;
}
RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
executor.getQueue().put(r);
} catch (InterruptedException e) {
log.error("Exception while adding event to executor queue : " + e.getMessage(), e);
}
}
};
executorService = new ThreadPoolExecutor(minThread, maxThread, defaultKeepAliveTime, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(jobQueueSize), rejectedExecutionHandler);
}
}
@Override
public void testConnect() throws TestConnectionNotSupportedException {
throw new TestConnectionNotSupportedException("not-supported");
}
@Override
public void connect() {
registerDynamicEndpoint(eventAdapterConfiguration.getName());
isConnected = true;
}
@Override
public void disconnect() {
if (isConnected){
isConnected = false;
unregisterDynamicEndpoint(eventAdapterConfiguration.getName());
}
}
@Override
public void destroy() {
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof HTTPEventAdapter))
return false;
HTTPEventAdapter that = (HTTPEventAdapter) o;
return id.equals(that.id);
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public boolean isEventDuplicatedInCluster() {
return false;
}
@Override
public boolean isPolling() {
return false;
}
private void registerDynamicEndpoint(String adapterName) {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
String endpoint;
if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
endpoint = HTTPEventAdapterConstants.ENDPOINT_PREFIX + adapterName;
} else {
endpoint = HTTPEventAdapterConstants.ENDPOINT_PREFIX + HTTPEventAdapterConstants.ENDPOINT_TENANT_KEY
+ HTTPEventAdapterConstants.ENDPOINT_URL_SEPARATOR + tenantDomain
+ HTTPEventAdapterConstants.ENDPOINT_URL_SEPARATOR + adapterName;
}
try {
HttpService httpService = EventAdapterServiceDataHolder.getHTTPService();
if (httpService == null) {
throw new InputEventAdapterRuntimeException(
"HttpService not available, Error in registering endpoint " + endpoint);
}
httpService.registerServlet(endpoint, new HTTPMessageServlet(eventAdaptorListener, tenantId,
eventAdapterConfiguration),
new Hashtable(), httpService.createDefaultHttpContext());
} catch (ServletException | NamespaceException e) {
throw new InputEventAdapterRuntimeException("Error in registering endpoint " + endpoint, e);
}
}
private void unregisterDynamicEndpoint(String adapterName) {
HttpService httpService = EventAdapterServiceDataHolder.getHTTPService();
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
String endpoint;
if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
endpoint = HTTPEventAdapterConstants.ENDPOINT_PREFIX + adapterName;
} else {
endpoint = HTTPEventAdapterConstants.ENDPOINT_PREFIX + HTTPEventAdapterConstants.ENDPOINT_TENANT_KEY
+ HTTPEventAdapterConstants.ENDPOINT_URL_SEPARATOR + tenantDomain
+ HTTPEventAdapterConstants.ENDPOINT_URL_SEPARATOR + adapterName;
}
if (httpService != null) {
httpService.unregister(endpoint);
}
}
}

@ -1,156 +0,0 @@
/*
* Copyright (c) 2005 - 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.wso2.carbon.event.input.adapter.extensions.http;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapter;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterFactory;
import org.wso2.carbon.event.input.adapter.core.MessageType;
import org.wso2.carbon.event.input.adapter.core.Property;
import org.wso2.carbon.event.input.adapter.extensions.http.util.HTTPEventAdapterConstants;
import org.wso2.carbon.utils.CarbonUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
/**
* The http event adapter factory class to create a http input adapter
*/
public class HTTPEventAdapterFactory extends InputEventAdapterFactory {
private ResourceBundle resourceBundle =
ResourceBundle.getBundle("org.wso2.carbon.event.input.adapter.extensions.http.i18n.Resources", Locale.getDefault());
private int httpPort;
private int httpsPort;
private int portOffset;
public HTTPEventAdapterFactory() {
portOffset = getPortOffset();
httpPort = HTTPEventAdapterConstants.DEFAULT_HTTP_PORT + portOffset;
httpsPort = HTTPEventAdapterConstants.DEFAULT_HTTPS_PORT + portOffset;
}
@Override
public String getType() {
return HTTPEventAdapterConstants.ADAPTER_TYPE_HTTP;
}
@Override
public List<String> getSupportedMessageFormats() {
List<String> supportInputMessageTypes = new ArrayList<String>();
supportInputMessageTypes.add(MessageType.JSON);
return supportInputMessageTypes;
}
@Override
public List<Property> getPropertyList() {
List<Property> propertyList = new ArrayList<Property>();
// Transport Exposed
Property exposedTransportsProperty = new Property(HTTPEventAdapterConstants.EXPOSED_TRANSPORTS);
exposedTransportsProperty.setRequired(true);
exposedTransportsProperty.setDisplayName(
resourceBundle.getString(HTTPEventAdapterConstants.EXPOSED_TRANSPORTS));
exposedTransportsProperty.setOptions(
new String[]{HTTPEventAdapterConstants.HTTPS, HTTPEventAdapterConstants.HTTP,
HTTPEventAdapterConstants.LOCAL, HTTPEventAdapterConstants.ALL});
exposedTransportsProperty.setDefaultValue(HTTPEventAdapterConstants.ALL);
propertyList.add(exposedTransportsProperty);
// OAUTH validation endpoint admin service username
Property username = new Property(HTTPEventAdapterConstants.USERNAME);
username.setRequired(true);
username.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.USERNAME));
username.setHint(resourceBundle.getString(HTTPEventAdapterConstants.USERNAME_HINT));
propertyList.add(username);
// OAUTH validation endpoint admin service password
Property password = new Property(HTTPEventAdapterConstants.PASSWORD);
password.setRequired(true);
password.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.PASSWORD));
password.setHint(resourceBundle.getString(HTTPEventAdapterConstants.PASSWORD_HINT));
propertyList.add(password);
// OAUTH validation endpoint
Property tokenValidationEndpoint = new Property(HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL);
tokenValidationEndpoint.setRequired(true);
tokenValidationEndpoint.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL));
tokenValidationEndpoint.setHint(resourceBundle.getString(HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL_HINT));
propertyList.add(tokenValidationEndpoint);
Property maximumHttpConnectionPerHost = new Property(HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST);
maximumHttpConnectionPerHost.setRequired(true);
maximumHttpConnectionPerHost.setDisplayName(resourceBundle.getString(
HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST));
maximumHttpConnectionPerHost.setHint(resourceBundle.getString(
HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST_HINT));
maximumHttpConnectionPerHost.setDefaultValue(HTTPEventAdapterConstants.MAX_HTTP_CONNECTION);
propertyList.add(maximumHttpConnectionPerHost);
Property maxTotalHttpConnection = new Property(HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION);
maxTotalHttpConnection.setRequired(true);
maxTotalHttpConnection.setDisplayName(resourceBundle.getString(
HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION));
maxTotalHttpConnection.setHint(resourceBundle.getString(
HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION_HINT));
maxTotalHttpConnection.setDefaultValue(HTTPEventAdapterConstants.MAX_TOTAL_HTTP_CONNECTION);
propertyList.add(maxTotalHttpConnection);
//Content Validator details
Property contentValidator = new Property(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME);
contentValidator.setDisplayName(
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME));
contentValidator.setRequired(false);
contentValidator.setHint(
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT));
contentValidator.setDefaultValue(HTTPEventAdapterConstants.DEFAULT);
propertyList.add(contentValidator);
//Content Validator Params details
Property contentValidatorParams = new Property(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
contentValidatorParams.setDisplayName(
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS));
contentValidatorParams.setRequired(false);
contentValidatorParams.setHint(
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT));
contentValidatorParams.setDefaultValue(HTTPEventAdapterConstants.MQTT_CONTENT_VALIDATION_DEFAULT_PARAMETERS);
propertyList.add(contentValidatorParams);
return propertyList;
}
@Override
public String getUsageTips() {
return resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_USAGE_TIPS_PREFIX) + httpPort +
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_USAGE_TIPS_MID1) + httpsPort +
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_USAGE_TIPS_MID2) + httpPort +
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_USAGE_TIPS_MID3) + httpsPort +
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_USAGE_TIPS_POSTFIX);
}
@Override
public InputEventAdapter createEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
return new HTTPEventAdapter(eventAdapterConfiguration, globalProperties);
}
private int getPortOffset() {
return CarbonUtils.getPortFromServerConfig(HTTPEventAdapterConstants.CARBON_CONFIG_PORT_OFFSET_NODE) + 1;
}
}

@ -1,372 +0,0 @@
/*
* Copyright (c) 2005 - 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.wso2.carbon.event.input.adapter.extensions.http;
import org.apache.axis2.context.ServiceContext;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterListener;
import org.wso2.carbon.event.input.adapter.extensions.ContentInfo;
import org.wso2.carbon.event.input.adapter.extensions.ContentValidator;
import org.wso2.carbon.event.input.adapter.extensions.http.oauth.OAuthTokenValidaterStubFactory;
import org.wso2.carbon.event.input.adapter.extensions.http.util.AuthenticationInfo;
import org.wso2.carbon.event.input.adapter.extensions.http.util.HTTPContentValidator;
import org.wso2.carbon.event.input.adapter.extensions.http.util.HTTPEventAdapterConstants;
import org.wso2.carbon.event.input.adapter.extensions.internal.EventAdapterServiceDataHolder;
import org.wso2.carbon.event.input.adapter.extensions.mqtt.exception.MQTTContentValidatorInitializationException;
import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO;
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO_OAuth2AccessToken;
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationResponseDTO;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.rmi.RemoteException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* This will act as the event reciver.
*/
public class HTTPMessageServlet extends HttpServlet {
private static final String AUTHORIZATION_HEADER = "Authorization";
private static final String AUTH_MESSAGE_STORE_AUTHENTICATION_INFO = "AUTH_MESSAGE_STORE_AUTHENTICATION_INFO";
private static final String AUTH_FAILURE_RESPONSE = "_AUTH_FAILURE_";
private static final Pattern PATTERN = Pattern.compile("[B|b]earer\\s");
private static final String TOKEN_TYPE = "bearer";
private static String cookie;
private static Log log = LogFactory.getLog(HTTPMessageServlet.class);
private GenericObjectPool stubs;
private static Map<String, String> contentValidationProperties;
private static ContentValidator contentValidator;
private InputEventAdapterListener eventAdaptorListener;
private int tenantId;
private String exposedTransports;
public HTTPMessageServlet(InputEventAdapterListener eventAdaptorListener, int tenantId,
InputEventAdapterConfiguration eventAdapterConfiguration) {
this.eventAdaptorListener = eventAdaptorListener;
this.tenantId = tenantId;
this.exposedTransports = eventAdapterConfiguration.getProperties().get(
HTTPEventAdapterConstants.EXPOSED_TRANSPORTS);
this.stubs = new GenericObjectPool(new OAuthTokenValidaterStubFactory(eventAdapterConfiguration));
this.contentValidationProperties = new HashMap<String, String>();
String contentValidationParams = eventAdapterConfiguration.getProperties().get(
HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
if (contentValidationParams != null && !contentValidationParams.isEmpty()) {
String validationParams[] = contentValidationParams.split(",");
for (String validationParam : validationParams) {
String[] validationProperty = validationParam.split(":");
if (validationProperty.length == 2) {
contentValidationProperties.put(validationProperty[0], validationProperty[1]);
}
}
}
String className = eventAdapterConfiguration.getProperties().get(
HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME);
if (HTTPEventAdapterConstants.DEFAULT.equals(className)) {
contentValidator = new HTTPContentValidator();
} else {
try {
Class<? extends ContentValidator> contentValidatorClass = Class.forName(className)
.asSubclass(ContentValidator.class);
contentValidator = contentValidatorClass.newInstance();
} catch (ClassNotFoundException e) {
throw new MQTTContentValidatorInitializationException(
"Unable to find the class authorizer: " + className, e);
} catch (InstantiationException e) {
throw new MQTTContentValidatorInitializationException(
"Unable to create an instance of :" + className, e);
} catch (IllegalAccessException e) {
throw new MQTTContentValidatorInitializationException("Access of the instance in not allowed.", e);
}
}
}
private String getBearerToken(HttpServletRequest request) {
String authorizationHeader = request.getHeader(AUTHORIZATION_HEADER);
if (authorizationHeader != null) {
Matcher matcher = PATTERN.matcher(authorizationHeader);
if (matcher.find()) {
authorizationHeader = authorizationHeader.substring(matcher.end());
}
}
return authorizationHeader;
}
private AuthenticationInfo checkAuthentication(HttpServletRequest req) {
AuthenticationInfo authenticationInfo = (AuthenticationInfo) req.getSession().getAttribute(
AUTH_MESSAGE_STORE_AUTHENTICATION_INFO);
if (authenticationInfo != null) {
return authenticationInfo;
}
String bearerToken = getBearerToken(req);
if (bearerToken == null) {
return authenticationInfo;
}
RealmService realmService = EventAdapterServiceDataHolder.getRealmService();
try {
authenticationInfo = validateToken(bearerToken);
boolean success = authenticationInfo.isAuthenticated();
if (success) {
req.getSession().setAttribute(AUTH_MESSAGE_STORE_AUTHENTICATION_INFO, authenticationInfo);
}
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug("checkAuthentication() fail: " + e.getMessage(), e);
}
}
return authenticationInfo;
}
/**
* This method gets a string accessToken and validates it
*
* @param token which need to be validated.
* @return AuthenticationInfo with the validated results.
*/
private AuthenticationInfo validateToken(String token) {
OAuth2TokenValidationServiceStub tokenValidationServiceStub = null;
try {
Object stub = this.stubs.borrowObject();
if (stub != null) {
tokenValidationServiceStub = (OAuth2TokenValidationServiceStub) stub;
if (cookie != null) {
tokenValidationServiceStub._getServiceClient().getOptions().setProperty(
HTTPConstants.COOKIE_STRING, cookie);
}
return getAuthenticationInfo(token, tokenValidationServiceStub);
} else {
log.warn("Stub initialization failed.");
}
} catch (RemoteException e) {
log.error("Error on connecting with the validation endpoint.", e);
} catch (Exception e) {
log.error("Error occurred in borrowing an validation stub from the pool.", e);
} finally {
try {
if (tokenValidationServiceStub != null) {
this.stubs.returnObject(tokenValidationServiceStub);
}
} catch (Exception e) {
log.warn("Error occurred while returning the object back to the oauth token validation service " +
"stub pool.", e);
}
}
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
authenticationInfo.setAuthenticated(false);
authenticationInfo.setTenantId(-1);
return authenticationInfo;
}
/**
* This creates an AuthenticationInfo object that is used for authorization. This method will validate the token
* and
* sets the required parameters to the object.
*
* @param token that needs to be validated.
* @param tokenValidationServiceStub stub that is used to call the external service.
* @return AuthenticationInfo This contains the information related to authenticated client.
* @throws RemoteException that triggers when failing to call the external service..
*/
private AuthenticationInfo getAuthenticationInfo(String token,
OAuth2TokenValidationServiceStub tokenValidationServiceStub)
throws RemoteException, UserStoreException {
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
OAuth2TokenValidationRequestDTO validationRequest = new OAuth2TokenValidationRequestDTO();
OAuth2TokenValidationRequestDTO_OAuth2AccessToken accessToken =
new OAuth2TokenValidationRequestDTO_OAuth2AccessToken();
accessToken.setTokenType(TOKEN_TYPE);
accessToken.setIdentifier(token);
validationRequest.setAccessToken(accessToken);
boolean authenticated;
OAuth2TokenValidationResponseDTO tokenValidationResponse;
tokenValidationResponse = tokenValidationServiceStub.validate(validationRequest);
if (tokenValidationResponse == null) {
authenticationInfo.setAuthenticated(false);
return authenticationInfo;
}
authenticated = tokenValidationResponse.getValid();
if (authenticated) {
String authorizedUser = tokenValidationResponse.getAuthorizedUser();
String username = MultitenantUtils.getTenantAwareUsername(authorizedUser);
String tenantDomain = MultitenantUtils.getTenantDomain(authorizedUser);
authenticationInfo.setUsername(username);
authenticationInfo.setTenantDomain(tenantDomain);
RealmService realmService = EventAdapterServiceDataHolder.getRealmService();
int tenantId = realmService.getTenantManager().getTenantId(authenticationInfo.getTenantDomain());
authenticationInfo.setTenantId(tenantId);
} else {
if (log.isDebugEnabled()) {
log.debug("Token validation failed for token: " + token);
}
}
ServiceContext serviceContext = tokenValidationServiceStub._getServiceClient()
.getLastOperationContext().getServiceContext();
cookie = (String) serviceContext.getProperty(HTTPConstants.COOKIE_STRING);
authenticationInfo.setAuthenticated(authenticated);
return authenticationInfo;
}
private String inputStreamToString(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buff = new byte[1024];
int i;
while ((i = in.read(buff)) > 0) {
out.write(buff, 0, i);
}
out.close();
return out.toString();
}
@Override
protected void doPost(HttpServletRequest req,
HttpServletResponse res) throws IOException {
String data = this.inputStreamToString(req.getInputStream());
if (data == null) {
log.warn("Event Object is empty/null");
return;
}
AuthenticationInfo authenticationInfo = null;
if (exposedTransports.equalsIgnoreCase(HTTPEventAdapterConstants.HTTPS)) {
if (!req.isSecure()) {
res.setStatus(403);
log.error("Only Secured endpoint is enabled for requests");
return;
} else {
authenticationInfo = this.checkAuthentication(req);
int tenantId = authenticationInfo != null ? authenticationInfo.getTenantId() : -1;
if (tenantId == -1) {
res.getOutputStream().write(AUTH_FAILURE_RESPONSE.getBytes());
res.setStatus(401);
log.error("Authentication failed for the request");
return;
} else if (tenantId != this.tenantId) {
res.getOutputStream().write(AUTH_FAILURE_RESPONSE.getBytes());
res.setStatus(401);
log.error("Authentication failed for the request");
return;
}
}
} else if (exposedTransports.equalsIgnoreCase(HTTPEventAdapterConstants.HTTP)) {
if (req.isSecure()) {
res.setStatus(403);
log.error("Only unsecured endpoint is enabled for requests");
return;
}
} else {
authenticationInfo = this.checkAuthentication(req);
int tenantId = authenticationInfo != null ? authenticationInfo.getTenantId() : -1;
if (tenantId == -1) {
res.getOutputStream().write(AUTH_FAILURE_RESPONSE.getBytes());
res.setStatus(401);
log.error("Authentication failed for the request");
return;
} else if (tenantId != this.tenantId) {
res.getOutputStream().write(AUTH_FAILURE_RESPONSE.getBytes());
res.setStatus(401);
log.error("Authentication failed for the request");
return;
}
}
if (log.isDebugEnabled()) {
log.debug("Message : " + data);
}
if (authenticationInfo != null) {
Map<String, String> paramMap = new HashMap<>();
paramMap.putAll(contentValidationProperties);
Enumeration<String> reqParameterNames = req.getParameterNames();
while (reqParameterNames.hasMoreElements()) {
String paramterName = reqParameterNames.nextElement();
paramMap.put(paramterName, req.getParameter(paramterName));
}
paramMap.put(HTTPEventAdapterConstants.USERNAME_TAG, authenticationInfo.getUsername());
paramMap.put(HTTPEventAdapterConstants.TENANT_DOMAIN_TAG, authenticationInfo.getTenantDomain());
if (contentValidator != null) {
ContentInfo contentInfo = contentValidator.validate(data, paramMap);
if (contentInfo != null && contentInfo.isValidContent()) {
HTTPEventAdapter.executorService.submit(new HTTPRequestProcessor(eventAdaptorListener,
contentInfo.getMsgText(), tenantId));
}
}
}
}
@Override
protected void doGet(HttpServletRequest req,
HttpServletResponse res) throws IOException {
doPost(req, res);
}
public class HTTPRequestProcessor implements Runnable {
private InputEventAdapterListener inputEventAdapterListener;
private String payload;
private int tenantId;
public HTTPRequestProcessor(InputEventAdapterListener inputEventAdapterListener,
String payload, int tenantId) {
this.inputEventAdapterListener = inputEventAdapterListener;
this.payload = payload;
this.tenantId = tenantId;
}
public void run() {
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId);
if (log.isDebugEnabled()) {
log.debug("Event received in HTTP Event Adapter - " + payload);
}
if (payload.trim() != null) {
inputEventAdapterListener.onEvent(payload);
} else {
log.warn("Dropping the empty/null event received through http adapter");
}
} catch (Exception e) {
log.error("Error while parsing http request for processing: " + e.getMessage(), e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}
}

@ -1,181 +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.event.input.adapter.extensions.http.oauth;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.transport.http.HttpTransportProperties;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.log4j.Logger;
import org.wso2.carbon.core.util.Utils;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.event.input.adapter.extensions.http.oauth.exception.OAuthTokenValidationException;
import org.wso2.carbon.event.input.adapter.extensions.http.util.HTTPEventAdapterConstants;
import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.GeneralSecurityException;
/**
* This follows object pool pattern to manage the stub for oauth validation service.
*/
public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
private static final Logger log = Logger.getLogger(OAuthTokenValidaterStubFactory.class);
private HttpClient httpClient;
InputEventAdapterConfiguration eventAdapterConfiguration;
public OAuthTokenValidaterStubFactory(InputEventAdapterConfiguration eventAdapterConfiguration) {
this.eventAdapterConfiguration = eventAdapterConfiguration;
this.httpClient = createHttpClient();
}
/**
* This creates a OAuth2TokenValidationServiceStub object to the pool.
*
* @return an OAuthValidationStub object
* @throws Exception thrown when creating the object.
*/
@Override
public Object makeObject() throws Exception {
return this.generateStub();
}
/**
* This is used to clean up the OAuth validation stub and releases to the object pool.
*
* @param o object that needs to be released.
* @throws Exception throws when failed to release to the pool
*/
@Override
public void passivateObject(Object o) throws Exception {
if (o instanceof OAuth2TokenValidationServiceStub) {
OAuth2TokenValidationServiceStub stub = (OAuth2TokenValidationServiceStub) o;
stub._getServiceClient().cleanupTransport();
}
}
/**
* This is used to create a stub which will be triggered through object pool factory, which will create an
* instance of it.
*
* @return OAuth2TokenValidationServiceStub stub that is used to call an external service.
* @throws OAuthTokenValidationException will be thrown when initialization failed.
*/
private OAuth2TokenValidationServiceStub generateStub() throws OAuthTokenValidationException {
OAuth2TokenValidationServiceStub stub;
try {
URL hostURL = new URL(Utils.replaceSystemProperty(eventAdapterConfiguration.getProperties().get(
HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL)));
if (hostURL != null) {
stub = new OAuth2TokenValidationServiceStub(hostURL.toString());
if (stub != null) {
ServiceClient client = stub._getServiceClient();
client.getServiceContext().getConfigurationContext().setProperty(
HTTPConstants.CACHED_HTTP_CLIENT, httpClient);
HttpTransportProperties.Authenticator auth =
new HttpTransportProperties.Authenticator();
auth.setPreemptiveAuthentication(true);
String username = eventAdapterConfiguration.getProperties().get(HTTPEventAdapterConstants
.USERNAME);
String password = eventAdapterConfiguration.getProperties().get(HTTPEventAdapterConstants
.PASSWORD);
auth.setPassword(username);
auth.setUsername(password);
Options options = client.getOptions();
options.setProperty(HTTPConstants.AUTHENTICATE, auth);
options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Constants.VALUE_TRUE);
client.setOptions(options);
if (hostURL.getProtocol().equals("https")) {
// set up ssl factory since axis2 https transport is used.
EasySSLProtocolSocketFactory sslProtocolSocketFactory =
createProtocolSocketFactory();
Protocol authhttps = new Protocol(hostURL.getProtocol(),
(ProtocolSocketFactory) sslProtocolSocketFactory,
hostURL.getPort());
Protocol.registerProtocol(hostURL.getProtocol(), authhttps);
options.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, authhttps);
}
} else {
String errorMsg = "OAuth Validation instanization failed.";
throw new OAuthTokenValidationException(errorMsg);
}
} else {
String errorMsg = "host url is invalid";
throw new OAuthTokenValidationException(errorMsg);
}
} catch (AxisFault axisFault) {
throw new OAuthTokenValidationException(
"Error occurred while creating the OAuth2TokenValidationServiceStub.", axisFault);
} catch (MalformedURLException e) {
throw new OAuthTokenValidationException(
"Error occurred while parsing token endpoint URL", e);
}
return stub;
}
/**
* This is required to create a trusted connection with the external entity.
* Have to manually configure it since we use CommonHTTPTransport(axis2 transport) in axis2.
*
* @return an EasySSLProtocolSocketFactory for SSL communication.
*/
private EasySSLProtocolSocketFactory createProtocolSocketFactory() throws OAuthTokenValidationException {
try {
EasySSLProtocolSocketFactory easySSLPSFactory = new EasySSLProtocolSocketFactory();
return easySSLPSFactory;
} catch (IOException e) {
String errorMsg = "Failed to initiate EasySSLProtocolSocketFactory.";
throw new OAuthTokenValidationException(errorMsg, e);
} catch (GeneralSecurityException e) {
String errorMsg = "Failed to set the key material in easy ssl factory.";
throw new OAuthTokenValidationException(errorMsg, e);
}
}
/**
* This created httpclient pool that can be used to connect to external entity. This connection can be configured
* via broker.xml by setting up the required http connection parameters.
*
* @return an instance of HttpClient that is configured with MultiThreadedHttpConnectionManager
*/
private HttpClient createHttpClient() {
HttpConnectionManagerParams params = new HttpConnectionManagerParams();
params.setDefaultMaxConnectionsPerHost(Integer.parseInt(eventAdapterConfiguration.getProperties().get(
HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST)));
params.setMaxTotalConnections(Integer.parseInt(eventAdapterConfiguration.getProperties().get(
HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION)));
HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
connectionManager.setParams(params);
return new HttpClient(connectionManager);
}
}

@ -1,56 +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.event.input.adapter.extensions.http.oauth.exception;
/**
* This Exception will be thrown, when there any interference with token validation flow.
*/
public class OAuthTokenValidationException extends Exception {
private String errMessage;
public OAuthTokenValidationException(String msg, Exception nestedEx) {
super(msg, nestedEx);
setErrorMessage(msg);
}
public OAuthTokenValidationException(String message, Throwable cause) {
super(message, cause);
setErrorMessage(message);
}
public OAuthTokenValidationException(String msg) {
super(msg);
setErrorMessage(msg);
}
public OAuthTokenValidationException() {
super();
}
public OAuthTokenValidationException(Throwable cause) {
super(cause);
}
public String getErrorMessage() {
return errMessage;
}
public void setErrorMessage(String errMessage) {
this.errMessage = errMessage;
}
}

@ -1,69 +0,0 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.event.input.adapter.extensions.http.util;
/**
* This will be return after authentication and this will consist of the authenticated user info.
*/
public class AuthenticationInfo {
/**
* this variable is used to check whether the client is authenticated.
*/
private boolean authenticated;
private String username;
private String tenantDomain;
private int tenantId;
/**
* returns whether the client is authenticated
*/
public boolean isAuthenticated() {
return authenticated;
}
public void setAuthenticated(boolean authenticated) {
this.authenticated = authenticated;
}
/**
* returns the authenticated client username
*/
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
/**
* return the authenticated client tenant domain
*/
public String getTenantDomain() {
return tenantDomain;
}
public void setTenantDomain(String tenantDomain) {
this.tenantDomain = tenantDomain;
}
public int getTenantId() {
return tenantId;
}
public void setTenantId(int tenantId) {
this.tenantId = tenantId;
}
}

@ -1,76 +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.event.input.adapter.extensions.http.util;
import com.jayway.jsonpath.JsonPath;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.simple.JSONArray;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.wso2.carbon.event.input.adapter.extensions.ContentInfo;
import org.wso2.carbon.event.input.adapter.extensions.ContentValidator;
import java.util.Map;
public class HTTPContentValidator implements ContentValidator {
private static final Log log = LogFactory.getLog(HTTPContentValidator.class);
private static String JSON_ARRAY_START_CHAR = "[";
@Override
public ContentInfo validate(String msgPayload, Map<String, String> paramMap) {
String deviceId = paramMap.get("deviceId");
String msg = msgPayload;
String deviceIdJsonPath = paramMap.get(HTTPEventAdapterConstants.DEVICE_ID_JSON_PATH);
boolean status;
if (msg.startsWith(JSON_ARRAY_START_CHAR)) {
status = processMultipleEvents(msg, deviceId, deviceIdJsonPath);
} else {
status = processSingleEvent(msg, deviceId, deviceIdJsonPath);
}
return new ContentInfo(status, msg);
}
private boolean processSingleEvent(String msg, String deviceIdFromTopic, String deviceIdJsonPath) {
Object res = JsonPath.read(msg, deviceIdJsonPath);
String deviceIdFromContent = (res != null) ? res.toString() : "";
if (deviceIdFromContent.equals(deviceIdFromTopic)) {
return true;
}
return false;
}
private boolean processMultipleEvents(String msg, String deviceIdFromTopic, String deviceIdJsonPath) {
try {
JSONParser jsonParser = new JSONParser();
JSONArray jsonArray = (JSONArray) jsonParser.parse(msg);
boolean status = false;
for (int i = 0; i < jsonArray.size(); i++) {
status = processSingleEvent(jsonArray.get(i).toString(), deviceIdFromTopic, deviceIdJsonPath);
if (!status) {
return status;
}
}
return status;
} catch (ParseException e) {
log.error("Invalid input " + msg, e);
return false;
}
}
}

@ -1,74 +0,0 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.wso2.carbon.event.input.adapter.extensions.http.util;
/**
* This holds the constants related to HTTP event adapter.
*/
public final class HTTPEventAdapterConstants {
private HTTPEventAdapterConstants() {
}
public static final String ADAPTER_TYPE_HTTP = "oauth-http";
public static final String ADAPTER_USAGE_TIPS_PREFIX = "http.usage.tips_prefix";
public static final String ADAPTER_USAGE_TIPS_MID1 = "http.usage.tips_mid1";
public static final String ADAPTER_USAGE_TIPS_MID2 = "http.usage.tips_mid2";
public static final String ADAPTER_USAGE_TIPS_MID3 = "http.usage.tips_mid3";
public static final String ADAPTER_USAGE_TIPS_POSTFIX = "http.usage.tips_postfix";
public static final int ADAPTER_MIN_THREAD_POOL_SIZE = 8;
public static final int ADAPTER_MAX_THREAD_POOL_SIZE = 100;
public static final int ADAPTER_EXECUTOR_JOB_QUEUE_SIZE = 10000;
public static final long DEFAULT_KEEP_ALIVE_TIME_IN_MILLS = 20000;
public static final String ENDPOINT_PREFIX = "/endpoints/";
public static final String ENDPOINT_URL_SEPARATOR = "/";
public static final String ENDPOINT_TENANT_KEY = "t";
public static final String ADAPTER_MIN_THREAD_POOL_SIZE_NAME = "minThread";
public static final String ADAPTER_MAX_THREAD_POOL_SIZE_NAME = "maxThread";
public static final String ADAPTER_KEEP_ALIVE_TIME_NAME = "keepAliveTimeInMillis";
public static final String ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME = "jobQueueSize";
public static final String EXPOSED_TRANSPORTS = "transports";
public static final String HTTPS = "https";
public static final String HTTP = "http";
public static final String LOCAL = "local";
public static final String ALL = "all";
public static final String CARBON_CONFIG_PORT_OFFSET_NODE = "Ports.Offset";
public static final int DEFAULT_HTTP_PORT = 9763;
public static final int DEFAULT_HTTPS_PORT = 9443;
public static final String MAXIMUM_TOTAL_HTTP_CONNECTION = "maximumTotalHttpConnection";
public static final String MAXIMUM_TOTAL_HTTP_CONNECTION_HINT = "maximumTotalHttpConnection.hint";
public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST = "maximumHttpConnectionPerHost";
public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST_HINT = "maximumHttpConnectionPerHost.hint";
public static final String TOKEN_VALIDATION_ENDPOINT_URL = "tokenValidationEndpointUrl";
public static final String TOKEN_VALIDATION_ENDPOINT_URL_HINT = "tokenValidationEndpointUrl.hint";
public static final String USERNAME = "username";
public static final String USERNAME_HINT = "username.hint";
public static final String PASSWORD = "password";
public static final String PASSWORD_HINT = "password.hint";
public static final String DEFAULT_STRING = "default";
public static final String MAX_HTTP_CONNECTION = "2";
public static final String MAX_TOTAL_HTTP_CONNECTION = "100";
public static final String TENANT_DOMAIN_TAG = "tenantDomain";
public static final String USERNAME_TAG = "username";
public static final String PAYLOAD_TAG = "payload";
public static final String DEVICE_ID_JSON_PATH = "device_id_json_path";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME = "contentValidation";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT = "contentValidation.hint";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS = "contentValidationParams";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT = "contentValidationParams.hint";
public static final String DEFAULT = "default";
public static final String MQTT_CONTENT_VALIDATION_DEFAULT_PARAMETERS =
"device_id_json_path:meta_deviceId";
}

@ -1,77 +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.event.input.adapter.extensions.internal;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.http.HttpService;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterFactory;
import org.wso2.carbon.event.input.adapter.extensions.http.HTTPEventAdapterFactory;
import org.wso2.carbon.event.input.adapter.extensions.mqtt.MQTTEventAdapterFactory;
import org.wso2.carbon.user.core.service.RealmService;
/**
* @scr.component component.name="input.iot.Mqtt.AdapterService.component" immediate="true"
*/
/**
* @scr.component name="org.wso2.carbon.event.input.adapter.extension.EventAdapterServiceComponent" 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"
* @scr.reference name="http.service" interface="org.osgi.service.http.HttpService"
* cardinality="1..1" policy="dynamic" bind="setHttpService" unbind="unsetHttpService"
*/
public class EventAdapterServiceComponent {
private static final Log log = LogFactory.getLog(EventAdapterServiceComponent.class);
protected void activate(ComponentContext context) {
try {
InputEventAdapterFactory mqttEventAdapterFactory = new MQTTEventAdapterFactory();
context.getBundleContext().registerService(InputEventAdapterFactory.class.getName(),
mqttEventAdapterFactory, null);
InputEventAdapterFactory httpEventEventAdapterFactory = new HTTPEventAdapterFactory();
context.getBundleContext().registerService(InputEventAdapterFactory.class.getName(),
httpEventEventAdapterFactory, null);
if (log.isDebugEnabled()) {
log.debug("Successfully deployed the input IoT-MQTT adapter service");
}
} catch (RuntimeException e) {
log.error("Can not create the input IoT-MQTT adapter service ", e);
}
}
protected void setRealmService(RealmService realmService) {
EventAdapterServiceDataHolder.registerRealmService(realmService);
}
protected void unsetRealmService(RealmService realmService) {
EventAdapterServiceDataHolder.registerRealmService(null);
}
protected void setHttpService(HttpService httpService) {
EventAdapterServiceDataHolder.registerHTTPService(httpService);
}
protected void unsetHttpService(HttpService httpService) {
EventAdapterServiceDataHolder.registerHTTPService(null);
}
}

@ -1,50 +0,0 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.wso2.carbon.event.input.adapter.extensions.internal;
import org.osgi.service.http.HttpService;
import org.wso2.carbon.user.core.service.RealmService;
/**
* common place to hold some OSGI service references.
*/
public final class EventAdapterServiceDataHolder {
private static RealmService realmService;
private static HttpService httpService;
private EventAdapterServiceDataHolder() {
}
public static void registerRealmService(
RealmService realmService) {
EventAdapterServiceDataHolder.realmService = realmService;
}
public static RealmService getRealmService() {
return realmService;
}
public static void registerHTTPService(
HttpService httpService) {
EventAdapterServiceDataHolder.httpService = httpService;
}
public static HttpService getHTTPService() {
return httpService;
}
}

@ -1,38 +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.event.input.adapter.extensions.mqtt;
/**
* This holds the constants related to MQTT input adapter.
*/
public class Constants {
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 TOKEN_SCOPE = "production";
public static final String APPLICATION_TYPE = "device";
public static final String CLIENT_ID = "client_id";
public static final String CLIENT_SECRET = "client_secret";
public static final String CLIENT_NAME = "client_name";
public static final String DEFAULT = "default";
public static final String MQTT_CONTENT_VALIDATION_DEFAULT_PARAMETERS =
"device_id_json_path:event.metaData.deviceId,device_id_topic_hierarchy_index:2";
public static final String TOPIC = "topic";
public static final String PAYLOAD = "payload";
public static final String DEVICE_ID_JSON_PATH = "device_id_json_path";
public static final String DEVICE_ID_TOPIC_HIERARCHY_INDEX = "device_id_topic_hierarchy_index";
}

@ -1,166 +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.event.input.adapter.extensions.mqtt;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapter;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterListener;
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterException;
import org.wso2.carbon.event.input.adapter.core.exception.TestConnectionNotSupportedException;
import org.wso2.carbon.event.input.adapter.extensions.mqtt.util.MQTTAdapterListener;
import org.wso2.carbon.event.input.adapter.extensions.mqtt.util.MQTTBrokerConnectionConfiguration;
import org.wso2.carbon.event.input.adapter.extensions.mqtt.util.MQTTEventAdapterConstants;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* Input MQTTEventAdapter will be used to receive events with MQTT protocol using specified broker and topic.
*/
public class MQTTEventAdapter implements InputEventAdapter {
private final InputEventAdapterConfiguration eventAdapterConfiguration;
private final Map<String, String> globalProperties;
private InputEventAdapterListener eventAdapterListener;
private final String id = UUID.randomUUID().toString();
private MQTTAdapterListener mqttAdapterListener;
private MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration;
public MQTTEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
this.eventAdapterConfiguration = eventAdapterConfiguration;
this.globalProperties = globalProperties;
}
@Override
public void init(InputEventAdapterListener eventAdapterListener) throws InputEventAdapterException {
this.eventAdapterListener = eventAdapterListener;
try {
int keepAlive;
//If global properties are available those will be assigned else constant values will be assigned
if (globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_KEEP_ALIVE) != null) {
keepAlive = Integer.parseInt((globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_KEEP_ALIVE)));
} else {
keepAlive = MQTTEventAdapterConstants.ADAPTER_CONF_DEFAULT_KEEP_ALIVE;
}
String contentValidationParams = eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
String params[] = contentValidationParams.split(",");
Map<String, String> paramsMap = new HashMap<>();
for (String param: params) {
String paramsKeyAndValue[] = splitOnFirst(param, ':');
if (paramsKeyAndValue.length != 2) {
throw new InputEventAdapterException("Invalid parameters for content validation - " + param);
}
paramsMap.put(paramsKeyAndValue[0], paramsKeyAndValue[1]);
}
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),
paramsMap
);
mqttAdapterListener = new MQTTAdapterListener(mqttBrokerConnectionConfiguration,
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC),
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID),
eventAdapterListener, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
} catch (Throwable t) {
throw new InputEventAdapterException(t.getMessage(), t);
}
}
private String[] splitOnFirst(String str, char c) {
int idx = str.indexOf(c);
String head = str.substring(0, idx);
String tail = str.substring(idx + 1);
return new String[] { head, tail} ;
}
@Override
public void testConnect() throws TestConnectionNotSupportedException {
throw new TestConnectionNotSupportedException("not-supported");
}
@Override
public void connect() {
mqttAdapterListener.createConnection();
}
@Override
public void disconnect() {
//when mqtt and this feature both together then this method becomes a blocking method, Therefore
// have used a thread to skip it.
try {
Thread thread = new Thread(new Runnable() {
public void run() {
if (mqttAdapterListener != null) {
mqttAdapterListener.stopListener(eventAdapterConfiguration.getName());
}
}
});
thread.start();
thread.join(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
@Override
public void destroy() {
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MQTTEventAdapter)) return false;
MQTTEventAdapter that = (MQTTEventAdapter) o;
if (!id.equals(that.id)) return false;
return true;
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public boolean isEventDuplicatedInCluster() {
return true;
}
@Override
public boolean isPolling() {
return true;
}
}

@ -1,135 +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.event.input.adapter.extensions.mqtt;
import org.wso2.carbon.event.input.adapter.core.*;
import org.wso2.carbon.event.input.adapter.extensions.mqtt.util.MQTTEventAdapterConstants;
import java.util.*;
/**
* The mqtt event adapter factory class to create a mqtt input adapter
*/
public class MQTTEventAdapterFactory extends InputEventAdapterFactory {
private ResourceBundle resourceBundle = ResourceBundle.getBundle
("org.wso2.carbon.event.input.adapter.extensions.mqtt.i18n.Resources", Locale.getDefault());
@Override
public String getType() {
return MQTTEventAdapterConstants.ADAPTER_TYPE_MQTT;
}
@Override
public List<String> getSupportedMessageFormats() {
List<String> supportInputMessageTypes = new ArrayList<String>();
supportInputMessageTypes.add(MessageType.JSON);
return supportInputMessageTypes;
}
@Override
public List<Property> getPropertyList() {
List<Property> propertyList = new ArrayList<Property>();
// set topic
Property topicProperty = new Property(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC);
topicProperty.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC));
topicProperty.setRequired(true);
topicProperty.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC_HINT));
propertyList.add(topicProperty);
//Broker Url
Property brokerUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
brokerUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL));
brokerUrl.setRequired(true);
brokerUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL_HINT));
propertyList.add(brokerUrl);
//DCR endpoint details
Property dcrUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL);
dcrUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL));
dcrUrl.setRequired(false);
dcrUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL_HINT));
propertyList.add(dcrUrl);
//Content Validator details
Property contentValidator = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME);
contentValidator.setDisplayName(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME));
contentValidator.setRequired(false);
contentValidator.setHint(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT));
contentValidator.setDefaultValue(Constants.DEFAULT);
propertyList.add(contentValidator);
//Content Validator Params details
Property contentValidatorParams = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
contentValidatorParams.setDisplayName(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS));
contentValidatorParams.setRequired(false);
contentValidatorParams.setHint(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT));
contentValidatorParams.setDefaultValue(Constants.MQTT_CONTENT_VALIDATION_DEFAULT_PARAMETERS);
propertyList.add(contentValidatorParams);
//Broker Username
Property userName = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME);
userName.setDisplayName(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME));
userName.setRequired(false);
userName.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME_HINT));
propertyList.add(userName);
//Broker Required Scopes.
Property scopes = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES);
scopes.setDisplayName(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES));
scopes.setRequired(false);
scopes.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES_HINT));
propertyList.add(scopes);
//Broker clear session
Property clearSession = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION);
clearSession.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION));
clearSession.setRequired(false);
clearSession.setOptions(new String[]{"true", "false"});
clearSession.setDefaultValue("true");
clearSession.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION_HINT));
propertyList.add(clearSession);
// set clientId
Property clientId = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID);
clientId.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID));
clientId.setRequired(false);
clientId.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID_HINT));
propertyList.add(clientId);
return propertyList;
}
@Override
public String getUsageTips() {
return null;
}
@Override
public InputEventAdapter createEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
return new MQTTEventAdapter(eventAdapterConfiguration, globalProperties);
}
}

@ -1,56 +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.event.input.adapter.extensions.mqtt.exception;
/**
* This exception will thrown when content validator is failed to intialiaze.
*/
public class MQTTContentValidatorInitializationException extends RuntimeException {
private String errMessage;
public MQTTContentValidatorInitializationException(String msg, Exception nestedEx) {
super(msg, nestedEx);
setErrorMessage(msg);
}
public MQTTContentValidatorInitializationException(String message, Throwable cause) {
super(message, cause);
setErrorMessage(message);
}
public MQTTContentValidatorInitializationException(String msg) {
super(msg);
setErrorMessage(msg);
}
public MQTTContentValidatorInitializationException() {
super();
}
public MQTTContentValidatorInitializationException(Throwable cause) {
super(cause);
}
public String getErrorMessage() {
return errMessage;
}
public void setErrorMessage(String errMessage) {
this.errMessage = errMessage;
}
}

@ -1,284 +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.event.input.adapter.extensions.mqtt.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.core.ServerStatus;
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.extensions.ContentInfo;
import org.wso2.carbon.event.input.adapter.extensions.ContentValidator;
import org.wso2.carbon.event.input.adapter.extensions.mqtt.Constants;
import org.wso2.carbon.event.input.adapter.extensions.mqtt.exception.MQTTContentValidatorInitializationException;
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
public class MQTTAdapterListener implements MqttCallback, Runnable {
private static final Log log = LogFactory.getLog(MQTTAdapterListener.class);
private MqttClient mqttClient;
private MqttConnectOptions connectionOptions;
private boolean cleanSession;
private int keepAlive;
private MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration;
private String mqttClientId;
private String topic;
private int tenantId;
private boolean connectionSucceeded = false;
ContentValidator contentValidator;
Map<String, String> contentValidationParams;
private InputEventAdapterListener eventAdapterListener = null;
public MQTTAdapterListener(MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration,
String topic, String mqttClientId,
InputEventAdapterListener inputEventAdapterListener, int tenantId) {
if(mqttClientId == null || mqttClientId.trim().isEmpty()){
mqttClientId = MqttClient.generateClientId();
}
this.mqttClientId = mqttClientId;
this.mqttBrokerConnectionConfiguration = mqttBrokerConnectionConfiguration;
this.cleanSession = mqttBrokerConnectionConfiguration.isCleanSession();
this.keepAlive = mqttBrokerConnectionConfiguration.getKeepAlive();
this.topic = topic;
this.eventAdapterListener = inputEventAdapterListener;
this.tenantId = tenantId;
//SORTING messages until the server fetches them
String temp_directory = System.getProperty("java.io.tmpdir");
MqttDefaultFilePersistence dataStore = new MqttDefaultFilePersistence(temp_directory);
try {
// Construct the connection options object that contains connection parameters
// such as cleanSession and LWT
connectionOptions = new MqttConnectOptions();
connectionOptions.setCleanSession(cleanSession);
connectionOptions.setKeepAliveInterval(keepAlive);
// Construct an MQTT blocking mode client
mqttClient = new MqttClient(this.mqttBrokerConnectionConfiguration.getBrokerUrl(), this.mqttClientId,
dataStore);
// Set this wrapper as the callback handler
mqttClient.setCallback(this);
String contentValidatorClassName = this.mqttBrokerConnectionConfiguration.getContentValidatorClassName();
if (contentValidatorClassName != null && contentValidatorClassName.equals(Constants.DEFAULT)) {
contentValidator = new MQTTContentValidator();
} else if (contentValidatorClassName != null && !contentValidatorClassName.isEmpty()) {
try {
Class<? extends ContentValidator> contentValidatorClass = Class.forName(contentValidatorClassName)
.asSubclass(ContentValidator.class);
contentValidator = contentValidatorClass.newInstance();
} catch (ClassNotFoundException e) {
throw new MQTTContentValidatorInitializationException(
"Unable to find the class authorizer: " + contentValidatorClassName, e);
} catch (InstantiationException e) {
throw new MQTTContentValidatorInitializationException(
"Unable to create an instance of :" + contentValidatorClassName, e);
} catch (IllegalAccessException e) {
throw new MQTTContentValidatorInitializationException("Access of the instance in not allowed.", e);
}
}
contentValidationParams = mqttBrokerConnectionConfiguration.getContentValidatorParams();
} catch (MqttException e) {
log.error("Exception occurred while subscribing to MQTT broker at "
+ mqttBrokerConnectionConfiguration.getBrokerUrl());
throw new InputEventAdapterRuntimeException(e);
} catch (Throwable e) {
log.error("Exception occurred while subscribing to MQTT broker at "
+ mqttBrokerConnectionConfiguration.getBrokerUrl());
throw new InputEventAdapterRuntimeException(e);
}
}
public void startListener() throws MqttException {
if (this.mqttBrokerConnectionConfiguration.getBrokerUsername() != null && this.mqttBrokerConnectionConfiguration.getDcrUrl() != null) {
String username = this.mqttBrokerConnectionConfiguration.getBrokerUsername();
String dcrUrlString = this.mqttBrokerConnectionConfiguration.getDcrUrl();
String scopes = this.mqttBrokerConnectionConfiguration.getBrokerScopes();
//getJWT Client Parameters.
if (dcrUrlString != null && !dcrUrlString.isEmpty()) {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true);
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(username);
try {
URL dcrUrl = new URL(dcrUrlString);
HttpClient httpClient = MQTTUtil.getHttpClient(dcrUrl.getProtocol());
HttpPost postMethod = new HttpPost(dcrUrlString);
RegistrationProfile registrationProfile = new RegistrationProfile();
registrationProfile.setCallbackUrl(Constants.EMPTY_STRING);
registrationProfile.setGrantType(Constants.GRANT_TYPE);
registrationProfile.setOwner(username);
registrationProfile.setTokenScope(Constants.TOKEN_SCOPE);
registrationProfile.setApplicationType(Constants.APPLICATION_TYPE);
registrationProfile.setClientName(username + "_" + tenantId);
String jsonString = registrationProfile.toJSON();
StringEntity requestEntity = new StringEntity(jsonString, ContentType.APPLICATION_JSON);
postMethod.setEntity(requestEntity);
HttpResponse httpResponse = httpClient.execute(postMethod);
String response = MQTTUtil.getResponseString(httpResponse);
try {
JSONParser jsonParser = new JSONParser();
JSONObject jsonPayload = (JSONObject) jsonParser.parse(response);
String clientId = (String) jsonPayload.get(Constants.CLIENT_ID);
String clientSecret = (String) jsonPayload.get(Constants.CLIENT_SECRET);
JWTClientManagerService jwtClientManagerService = MQTTUtil.getJWTClientManagerService();
AccessTokenInfo accessTokenInfo = jwtClientManagerService.getJWTClient().getAccessToken(
clientId, clientSecret, username, scopes);
connectionOptions.setUserName(accessTokenInfo.getAccessToken());
} catch (ParseException e) {
String msg = "error occurred while parsing client credential payload";
log.error(msg, e);
} catch (JWTClientException e) {
String msg = "error occurred while parsing the response from JWT Client";
log.error(msg, e);
}
} catch (MalformedURLException e) {
log.error("Invalid dcrUrl : " + dcrUrlString);
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | IOException e) {
log.error("Failed to create an https connection.", e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}
// Connect to the MQTT server
mqttClient.connect(connectionOptions);
// Subscribe to the requested topic
// The QoS specified is the maximum level that messages will be sent to the client at.
// For instance if QoS 1 is specified, any messages originally published at QoS 2 will
// be downgraded to 1 when delivering to the client but messages published at 1 and 0
// will be received at the same level they were published at.
mqttClient.subscribe(topic);
}
public void stopListener(String adapterName) {
if (connectionSucceeded) {
try {
// Un-subscribe accordingly and disconnect from the MQTT server.
if (!ServerStatus.getCurrentStatus().equals(ServerStatus.STATUS_SHUTTING_DOWN) || cleanSession) {
mqttClient.unsubscribe(topic);
}
mqttClient.disconnect(3000);
} catch (MqttException e) {
log.error("Can not unsubscribe from the destination " + topic
+ " with the event adapter " + adapterName, e);
}
}
//This is to stop all running reconnection threads
connectionSucceeded = true;
}
@Override
public void connectionLost(Throwable throwable) {
log.warn("MQTT connection not reachable " + throwable);
connectionSucceeded = false;
new Thread(this).start();
}
@Override
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
try {
String msgText = mqttMessage.toString();
if (log.isDebugEnabled()) {
log.debug(msgText);
}
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId);
if (log.isDebugEnabled()) {
log.debug("Event received in MQTT Event Adapter - " + msgText);
}
if (contentValidator != null) {
ContentInfo contentInfo;
synchronized (contentValidationParams) {
contentValidationParams.put(Constants.TOPIC, topic);
contentInfo = contentValidator.validate(msgText,contentValidationParams);
contentValidationParams.remove(Constants.TOPIC);
contentValidationParams.remove(Constants.PAYLOAD);
}
if (contentInfo != null && contentInfo.isValidContent()) {
eventAdapterListener.onEvent(contentInfo.getMsgText());
}
} else {
eventAdapterListener.onEvent(msgText);
}
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
}
@Override
public void run() {
while (!connectionSucceeded) {
try {
MQTTEventAdapterConstants.initialReconnectDuration = MQTTEventAdapterConstants.initialReconnectDuration
* MQTTEventAdapterConstants.reconnectionProgressionFactor;
Thread.sleep(MQTTEventAdapterConstants.initialReconnectDuration);
startListener();
connectionSucceeded = true;
log.info("MQTT Connection successful");
} catch (InterruptedException e) {
log.error("Interruption occurred while waiting for reconnection", e);
} catch (MqttException e) {
log.error("MQTT Exception occurred when starting listener", e);
}
}
}
public void createConnection() {
new Thread(this).start();
}
}

@ -1,123 +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.event.input.adapter.extensions.mqtt.util;
import org.wso2.carbon.event.input.adapter.extensions.mqtt.Constants;
import org.wso2.carbon.event.input.adapter.extensions.util.PropertyUtils;
import java.util.Map;
/**
* This holds the configurations related to MQTT Broker.
*/
public class MQTTBrokerConnectionConfiguration {
private String brokerUsername = null;
private String brokerScopes = null;
private boolean cleanSession = true;
private int keepAlive;
private String brokerUrl;
private String dcrUrl;
private String contentValidatorClassName;
private Map<String, String> contentValidatorParams;
public String getBrokerScopes() {
return brokerScopes;
}
public void setBrokerScopes(String brokerScopes) {
this.brokerScopes = brokerScopes;
}
public String getBrokerUsername() {
return brokerUsername;
}
public void setBrokerUsername(String brokerUsername) {
this.brokerUsername = brokerUsername;
}
public void setCleanSession(boolean cleanSession) {
this.cleanSession = cleanSession;
}
public boolean isCleanSession() {
return cleanSession;
}
public String getBrokerUrl() {
return brokerUrl;
}
public void setBrokerUrl(String brokerUrl) {
this.brokerUrl = brokerUrl;
}
public String getDcrUrl() {
return dcrUrl;
}
public void setDcrUrl(String dcrUrl) {
this.dcrUrl = dcrUrl;
}
public int getKeepAlive() {
return keepAlive;
}
public void setKeepAlive(int keepAlive) {
this.keepAlive = keepAlive;
}
public String getContentValidatorClassName() {
return contentValidatorClassName;
}
public void setContentValidatorClassName(String contentValidatorClassName) {
this.contentValidatorClassName = contentValidatorClassName;
}
public Map<String, String> getContentValidatorParams() {
return contentValidatorParams;
}
public void setContentValidatorParams(Map<String, String> contentValidatorParams) {
this.contentValidatorParams = contentValidatorParams;
}
public MQTTBrokerConnectionConfiguration(String brokerUrl, String brokerUsername, String brokerScopes,
String dcrUrl, String cleanSession, int keepAlive,
String contentValidatorClassName, Map<String, String> contentValidatorParams) {
this.brokerUsername = brokerUsername;
this.brokerScopes = brokerScopes;
if (brokerScopes == null) {
this.brokerScopes = Constants.EMPTY_STRING;
}
this.brokerUrl = PropertyUtils.replaceMqttProperty(brokerUrl);
this.dcrUrl = PropertyUtils.replaceMqttProperty(dcrUrl);
this.contentValidatorClassName = contentValidatorClassName;
if (cleanSession != null) {
this.cleanSession = Boolean.parseBoolean(cleanSession);
}
this.keepAlive = keepAlive;
if (contentValidatorParams != null) {
this.contentValidatorParams = contentValidatorParams;
}
}
}

@ -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.event.input.adapter.extensions.mqtt.util;
import com.jayway.jsonpath.JsonPath;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.wso2.carbon.event.input.adapter.extensions.ContentInfo;
import org.wso2.carbon.event.input.adapter.extensions.ContentValidator;
import org.wso2.carbon.event.input.adapter.extensions.mqtt.Constants;
import java.util.Map;
public class MQTTContentValidator implements ContentValidator {
private static String JSON_ARRAY_START_CHAR = "[";
private static final Log log = LogFactory.getLog(MQTTContentValidator.class);
@Override
public ContentInfo validate(String msgPayload, Map<String, String> params) {
String topic = params.get(Constants.TOPIC);
String topics[] = topic.split("/");
String msg = msgPayload;
String deviceIdJsonPath = params.get(Constants.DEVICE_ID_JSON_PATH);
String deviceIdInTopicHierarchyLevel = params.get(Constants.DEVICE_ID_TOPIC_HIERARCHY_INDEX);
int deviceIdInTopicHierarchyLevelIndex = 0;
if (deviceIdInTopicHierarchyLevel != null && !deviceIdInTopicHierarchyLevel.isEmpty()) {
deviceIdInTopicHierarchyLevelIndex = Integer.parseInt(deviceIdInTopicHierarchyLevel);
}
String deviceIdFromTopic = topics[deviceIdInTopicHierarchyLevelIndex];
boolean status;
if (msg.startsWith(JSON_ARRAY_START_CHAR)) {
status = processMultipleEvents(msg, deviceIdFromTopic, deviceIdJsonPath);
} else {
status = processSingleEvent(msg, deviceIdFromTopic, deviceIdJsonPath);
}
return new ContentInfo(status, msg);
}
private boolean processSingleEvent(String msg, String deviceIdFromTopic, String deviceIdJsonPath) {
Object res = JsonPath.read(msg, deviceIdJsonPath);
String deviceIdFromContent = (res != null) ? res.toString() : "";
if (deviceIdFromContent.equals(deviceIdFromTopic)) {
return true;
}
return false;
}
private boolean processMultipleEvents(String msg, String deviceIdFromTopic, String deviceIdJsonPath) {
try {
JSONParser jsonParser = new JSONParser();
JSONArray jsonArray = (JSONArray) jsonParser.parse(msg);
boolean status = false;
for (int i = 0; i < jsonArray.size(); i++) {
status = processSingleEvent(jsonArray.get(i).toString(), deviceIdFromTopic, deviceIdJsonPath);
if (!status) {
return status;
}
}
return status;
} catch (ParseException e) {
log.error("Invalid input " + msg, e);
return false;
}
}
}

@ -1,50 +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.event.input.adapter.extensions.mqtt.util;
/**
* This holds the constants related to mqtt event adapter.
*/
public class MQTTEventAdapterConstants {
public static final String ADAPTER_TYPE_MQTT = "oauth-mqtt";
public static final String ADAPTER_CONF_URL = "url";
public static final String ADAPTER_CONF_USERNAME = "username";
public static final String ADAPTER_CONF_USERNAME_HINT = "username.hint";
public static final String ADAPTER_CONF_SCOPES = "scopes";
public static final String ADAPTER_CONF_SCOPES_HINT = "scopes.hint";
public static final String ADAPTER_CONF_URL_HINT = "url.hint";
public static final String ADAPTER_CONF_DCR_URL = "dcrUrl";
public static final String ADAPTER_CONF_DCR_URL_HINT = "dcrUrl.hint";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME = "contentValidation";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT = "contentValidation.hint";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS = "contentValidationParams";
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT = "contentValidationParams.hint";
public static final String ADAPTER_MESSAGE_TOPIC = "topic";
public static final String ADAPTER_MESSAGE_TOPIC_HINT = "topic.hint";
public static final String ADAPTER_CONF_CLIENTID = "clientId";
public static final String ADAPTER_CONF_CLIENTID_HINT = "clientId.hint";
public static final String ADAPTER_CONF_CLEAN_SESSION = "cleanSession";
public static final String ADAPTER_CONF_CLEAN_SESSION_HINT = "cleanSession.hint";
public static final String ADAPTER_CONF_KEEP_ALIVE = "keepAlive";
public static final int ADAPTER_CONF_DEFAULT_KEEP_ALIVE = 60000;
public static int initialReconnectDuration = 10000;
public static final int reconnectionProgressionFactor = 2;
}

@ -1,99 +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.event.input.adapter.extensions.mqtt.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
/**
* This is the utility class that is used for MQTT input adapater.
*/
public class MQTTUtil {
private static final String HTTPS_PROTOCOL = "https";
private static final Log log = LogFactory.getLog(MQTTUtil.class);
/**
* Return a http client instance
*
* @param protocol- service endpoint protocol http/https
* @return
*/
public static HttpClient getHttpClient(String protocol)
throws IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
HttpClient httpclient;
if (HTTPS_PROTOCOL.equals(protocol)) {
SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
} else {
httpclient = HttpClients.createDefault();
}
return httpclient;
}
public static String getResponseString(HttpResponse httpResponse) throws IOException {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
String readLine;
String response = "";
while (((readLine = br.readLine()) != null)) {
response += readLine;
}
return response;
} finally {
EntityUtils.consumeQuietly(httpResponse.getEntity());
if (br != null) {
try {
br.close();
} catch (IOException e) {
log.warn("Error while closing the connection! " + e.getMessage());
}
}
}
}
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;
}
}

@ -1,73 +0,0 @@
package org.wso2.carbon.event.input.adapter.extensions.mqtt.util;
/**
* This class represents the data that are required to register
* the oauth application.
*/
public class RegistrationProfile {
private String callbackUrl;
private String clientName;
private String tokenScope;
private String owner;
private String grantType;
private String applicationType;
private static final String TAG = RegistrationProfile.class.getSimpleName();
public String getCallbackUrl() {
return callbackUrl;
}
public void setCallbackUrl(String callBackUrl) {
this.callbackUrl = callBackUrl;
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public String getTokenScope() {
return tokenScope;
}
public void setTokenScope(String tokenScope) {
this.tokenScope = tokenScope;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getGrantType() {
return grantType;
}
public void setGrantType(String grantType) {
this.grantType = grantType;
}
public String getApplicationType() {
return applicationType;
}
public void setApplicationType(String applicationType) {
this.applicationType = applicationType;
}
public String toJSON() {
String jsonString =
"{\"callbackUrl\": \"" + callbackUrl + "\",\"clientName\": \"" + clientName + "\", \"tokenScope\": " +
"\"" + tokenScope + "\", \"owner\": \"" + owner + "\"," + "\"grantType\": \"" + grantType +
"\", \"saasApp\" :false }\n";
return jsonString;
}
}

@ -1,55 +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.event.input.adapter.extensions.util;
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.core.util.Utils;
public class PropertyUtils {
private static final String MQTT_PORT = "\\$\\{mqtt.broker.port\\}";
private static final String MQTT_BROKER_HOST = "\\$\\{mqtt.broker.host\\}";
private static final String CARBON_CONFIG_PORT_OFFSET = "Ports.Offset";
private static final String DEFAULT_CARBON_SERVER_HOST_PROPERTY = "server.host";
private static final int CARBON_DEFAULT_PORT_OFFSET = 0;
private static final int DEFAULT_MQTT_PORT = 1883;
//This method is only used if the mb features are within DAS.
public static String replaceMqttProperty (String urlWithPlaceholders) {
urlWithPlaceholders = Utils.replaceSystemProperty(urlWithPlaceholders);
urlWithPlaceholders = urlWithPlaceholders.replaceAll(MQTT_PORT, "" + (DEFAULT_MQTT_PORT + getPortOffset()));
urlWithPlaceholders = urlWithPlaceholders.replaceAll(MQTT_BROKER_HOST, System.getProperty(DEFAULT_CARBON_SERVER_HOST_PROPERTY,
"localhost"));
return urlWithPlaceholders;
}
private static int getPortOffset() {
ServerConfiguration carbonConfig = ServerConfiguration.getInstance();
String portOffset = System.getProperty("portOffset",
carbonConfig.getFirstProperty(CARBON_CONFIG_PORT_OFFSET));
try {
if ((portOffset != null)) {
return Integer.parseInt(portOffset.trim());
} else {
return CARBON_DEFAULT_PORT_OFFSET;
}
} catch (NumberFormatException e) {
return CARBON_DEFAULT_PORT_OFFSET;
}
}
}

@ -1,38 +0,0 @@
#
# Copyright (c) 2005-2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
#
# WSO2 Inc. licenses this file to you under the Apache License,
# Version 2.0 (the "License"); you may not use this file except
# in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
transports=Transport(s)
http.usage.tips_prefix=Following url formats are used to receive events</br>For super tenants:</br>&nbsp;&nbsp;<i>http://localhost:
http.usage.tips_mid1=/endpoints/&lt;event_receiver_name&gt</i></br>&nbsp;&nbsp;<i>https://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_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.
contentValidation=contentValidation
contentValidation.hint=Class Name of the content Validation or 'default' to set default class, required to implement (if required)
contentValidationParams=contentValidationParams
contentValidationParams.hint=ContentValidationParams, comma seperated. (if required)

@ -1,38 +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.
#
topic=Topic
topic.hint=Topic subscribed
clientId=Client Id
clientId.hint=client identifier is used by the server to identify a client when it reconnects, It used for durable subscriptions or reliable delivery of messages is required.
url=Broker Url
username=Username
username.hint=Username of the broker (if required)
scopes=Scopes
scopes.hint=Scopes required to connect to broker (if required)
dcrUrl=dcrUrl
dcrUrl.hint=dynamic client registration endpoint URL to create application (if required) eg: https://localhost:9443/dynamic-client-web/register
contentValidation=contentValidation
contentValidation.hint=Class Name of the content Validation or 'default' to set default class, required to implement (if required)
contentValidationParams=contentValidationParams
contentValidationParams.hint=ContentValidationParams, comma seperated. (if required)
url.hint=MQTT broker url tcp://localhost:1883
cleanSession=Clean Session
cleanSession.hint=Persist topic subscriptions and ack positions across client sessions
keepAlive=Keep Alive (In seconds)
events.duplicated.in.cluster=Is events duplicated in cluster

@ -33,7 +33,6 @@
<url>http://wso2.org</url>
<modules>
<module>org.wso2.carbon.event.input.adapter.extensions</module>
<module>org.wso2.carbon.event.output.adapter.extensions.ui</module>
<module>org.wso2.carbon.event.output.adapter.extensions.ui.endpoint</module>
</modules>

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2005-2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
~
~ WSO2 Inc. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>mb-extensions</artifactId>
<groupId>org.wso2.iot</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization</artifactId>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Component - MQTT - Authorization Manager</name>
<description>MQTT authorization manager based on Carbon device manager</description>
<url>http://wso2.org</url>
<dependencies>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.utils</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.andes.wso2</groupId>
<artifactId>andes</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.user.api</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.user.core</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Private-Package>
org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.internal
</Private-Package>
<Export-Package>
!org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.internal,
org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.*
</Export-Package>
<Import-Package>
org.apache.log4j,
org.dna.mqtt.moquette.server,
org.wso2.andes.configuration.enums,
org.wso2.andes.mqtt,
org.wso2.carbon.context,
org.apache.commons.logging,
org.osgi.service.component,
org.wso2.carbon.user.core.service,
org.wso2.carbon.user.core.tenant,
org.wso2.carbon.user.api
</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,105 @@
/*
* 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.andes.extensions.device.mgt.mqtt.authorization;
import org.apache.log4j.Logger;
import org.dna.mqtt.moquette.server.IAuthorizer;
import org.wso2.andes.configuration.enums.MQTTAuthoriztionPermissionLevel;
import org.wso2.andes.mqtt.MQTTAuthorizationSubject;
import org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.internal.AuthorizationDataHolder;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.user.api.UserRealm;
import org.wso2.carbon.user.api.UserStoreException;
import java.util.List;
/**
* Authorize the connecting users against Carbon Permission Model. Intended usage is
* via providing fully qualified class name in broker.xml
* <p/>
* This is just a simple authorization model. For dynamic topics use an implementation based on IAuthorizer
*/
public class DeviceAccessBasedMQTTAuthorizer implements IAuthorizer {
private static final Logger logger = Logger.getLogger(DeviceAccessBasedMQTTAuthorizer.class);
private static final String CONNECTION_PERMISSION = "/permission/admin/device-mgt/user";
private static final String SCOPE_IDENTIFIER = "scope";
/**
* {@inheritDoc} Authorize the user against carbon device mgt model.
*/
@Override
public boolean isAuthorizedForTopic(MQTTAuthorizationSubject authorizationSubject, String topic,
MQTTAuthoriztionPermissionLevel permissionLevel) {
String topics[] = topic.split("/");
if (topics.length < 3) {
return false;
}
String tenantIdFromTopic = topics[0];
if (!tenantIdFromTopic.equals(authorizationSubject.getTenantDomain())) {
return false;
}
String deviceTypeFromTopic = topics[1];
String deviceIdFromTopic = topics[2];
List<String> scopes = (List<String>) authorizationSubject.getProperties().get(SCOPE_IDENTIFIER);
if (scopes != null) {
for (String scope : scopes) {
//TODO : have to validate token with scopes.
}
}
return true;
}
/**
* {@inheritDoc} Authorized the user against carbon device mgt model.
*/
@Override
public boolean isAuthorizedToConnect(MQTTAuthorizationSubject authorizationSubject) {
return isUserAuthorized(authorizationSubject, CONNECTION_PERMISSION, "ui.execute");
}
/**
* Check whether the client is authorized with the given permission and action.
*
* @param authorizationSubject this contains the client information
* @param permission Carbon permission that requires for the use
* @param action Carbon permission action that requires for the given permission.
* @return boolean - true if user is authorized else return false.
*/
private boolean isUserAuthorized(MQTTAuthorizationSubject authorizationSubject, String permission, String action) {
String username = authorizationSubject.getUsername();
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
authorizationSubject.getTenantDomain(), true);
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
UserRealm userRealm = AuthorizationDataHolder.getInstance().getRealmService()
.getTenantUserRealm(tenantId);
if (userRealm != null && userRealm.getAuthorizationManager() != null) {
return userRealm.getAuthorizationManager().isUserAuthorized(username, permission, action);
}
return false;
} catch (UserStoreException e) {
String errorMsg = String.format("Unable to authorize the user : %s", username);
logger.error(errorMsg, e);
return false;
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}

@ -0,0 +1,57 @@
/*
* Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* you may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.internal;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.user.core.tenant.TenantManager;
public class AuthorizationDataHolder {
private RealmService realmService;
private TenantManager tenantManager;
private static AuthorizationDataHolder thisInstance = new AuthorizationDataHolder();
private AuthorizationDataHolder() {}
public static AuthorizationDataHolder getInstance() {
return thisInstance;
}
public RealmService getRealmService() {
return realmService;
}
public void setRealmService(RealmService realmService) {
this.realmService = realmService;
this.setTenantManager(realmService);
}
private void setTenantManager(RealmService realmService) {
if (realmService == null) {
throw new IllegalStateException("Realm service is not initialized properly");
}
this.tenantManager = realmService.getTenantManager();
}
public TenantManager getTenantManager() {
return tenantManager;
}
}

@ -0,0 +1,72 @@
/*
* Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* you may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.internal;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.user.core.service.RealmService;
/**
* @scr.component name="org.wso2.carbon.devicemgt.policy.manager" 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"
*/
@SuppressWarnings("unused")
public class AuthorizationServiceComponent {
private static Log log = LogFactory.getLog(AuthorizationServiceComponent.class);
protected void activate(ComponentContext componentContext) {
}
@SuppressWarnings("unused")
protected void deactivate(ComponentContext componentContext) {
}
/**
* Sets Realm Service
*
* @param realmService An instance of RealmService
*/
protected void setRealmService(RealmService realmService) {
if (log.isDebugEnabled()) {
log.debug("Setting Realm Service");
}
AuthorizationDataHolder.getInstance().setRealmService(realmService);
}
/**
* Unsets Realm Service
*
* @param realmService An instance of RealmService
*/
protected void unsetRealmService(RealmService realmService) {
if (log.isDebugEnabled()) {
log.debug("Unsetting Realm Service");
}
AuthorizationDataHolder.getInstance().setRealmService(null);
}
}

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
~
~ WSO2 Inc. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.wso2.iot</groupId>
<artifactId>iot-extensions</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mb-extensions</artifactId>
<packaging>pom</packaging>
<name>WSO2 Carbon - MB Extension</name>
<url>http://wso2.org</url>
<modules>
<module>org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization</module>
</modules>
</project>

@ -35,10 +35,6 @@
<description>This feature contains the bundles required for Input Event Adapter functionality</description>
<dependencies>
<dependency>
<groupId>org.wso2.iot</groupId>
<artifactId>org.wso2.carbon.event.input.adapter.extensions</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.iot</groupId>
<artifactId>org.wso2.carbon.event.output.adapter.extensions.ui</artifactId>
@ -93,16 +89,12 @@
</properties>
</adviceFile>
<bundles>
<bundleDef>
org.wso2.iot:org.wso2.carbon.event.input.adapter.extensions:${carbon.iot.device.mgt.version}
</bundleDef>
<bundleDef>
org.wso2.iot:org.wso2.carbon.event.output.adapter.extensions.ui:${carbon.iot.device.mgt.version}
</bundleDef>
</bundles>
<importFeatures>
<importFeatureDef>org.wso2.carbon.core.server:${carbon.kernel.version}</importFeatureDef>
<importFeatureDef>org.wso2.carbon.identity.jwt.client.extension:${carbon.device.mgt.version}</importFeatureDef>
</importFeatures>
</configuration>
</execution>

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
~
~ WSO2 Inc. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>mb-extensions-feature</artifactId>
<groupId>org.wso2.iot</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.feature</artifactId>
<packaging>pom</packaging>
<name>WSO2 Carbon - MQTT Authorization Feature</name>
<url>http://wso2.org</url>
<description>This feature contains the bundles required for mqtt authorization</description>
<dependencies>
<dependency>
<groupId>org.wso2.iot</groupId>
<artifactId>org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.wso2.maven</groupId>
<artifactId>carbon-p2-plugin</artifactId>
<version>${carbon.p2.plugin.version}</version>
<executions>
<execution>
<id>4-p2-feature-generation</id>
<phase>package</phase>
<goals>
<goal>p2-feature-gen</goal>
</goals>
<configuration>
<id>org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization</id>
<propertiesFile>../../etc/feature.properties</propertiesFile>
<adviceFile>
<properties>
<propertyDef>org.wso2.carbon.p2.category.type:server</propertyDef>
<propertyDef>org.eclipse.equinox.p2.type.group:true</propertyDef>
</properties>
</adviceFile>
<bundles>
<bundleDef>
org.wso2.iot:org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization:${carbon.iot.device.mgt.version}
</bundleDef>
</bundles>
<importFeatures>
<importFeatureDef>org.wso2.carbon.core.server:${carbon.kernel.version}</importFeatureDef>
</importFeatures>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,19 @@
#
# Copyright (c) 2005-2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
#
# WSO2 Inc. licenses this file to you under the Apache License,
# Version 2.0 (the "License"); you may not use this file except
# in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
custom = true

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
~
~ WSO2 Inc. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.wso2.iot</groupId>
<artifactId>iot-extensions</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mb-extensions-feature</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>WSO2 Carbon - Device Management, MB Extensions Feature</name>
<url>http://wso2.org</url>
<modules>
<module>org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.feature</module>
</modules>
</project>

@ -34,7 +34,9 @@
<modules>
<module>components/das-extensions</module>
<module>components/mb-extensions</module>
<module>features/das-extensions-feature</module>
<module>features/mb-extensions-feature</module>
</modules>
</project>

@ -145,6 +145,9 @@
<featureArtifactDef>
org.wso2.carbon.devicemgt-plugins:org.wso2.carbon.device.mgt.iot.feature:${carbon.device.mgt.plugin.version}
</featureArtifactDef>
<featureArtifactDef>
org.wso2.carbon.devicemgt-plugins:org.wso2.carbon.device.mgt.iot.adapter.feature:${carbon.device.mgt.plugin.version}
</featureArtifactDef>
<featureArtifactDef>
org.wso2.carbon.devicemgt-plugins:org.wso2.carbon.device.mgt.iot.androidsense.feature:${carbon.device.mgt.plugin.version}
</featureArtifactDef>
@ -396,6 +399,9 @@
<featureArtifactDef>
org.wso2.iot:org.wso2.carbon.event.adapter.extensions.server.feature:${carbon.iot.device.mgt.version}
</featureArtifactDef>
<featureArtifactDef>
org.wso2.iot:org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.feature:${carbon.iot.device.mgt.version}
</featureArtifactDef>
<!-- Mediation Features -->
<featureArtifactDef>
@ -729,6 +735,10 @@
<id>org.wso2.carbon.event.adapter.extensions.server.feature.group</id>
<version>${carbon.iot.device.mgt.version}</version>
</feature>
<feature>
<id>org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.feature.group</id>
<version>${carbon.iot.device.mgt.version}</version>
</feature>
<!-- End of IoTServer Features -->
<!-- Device Management Features -->
@ -786,6 +796,10 @@
<id>org.wso2.carbon.device.mgt.iot.feature.group</id>
<version>${carbon.device.mgt.plugin.version}</version>
</feature>
<feature>
<id>org.wso2.carbon.device.mgt.iot.adapter.feature.group</id>
<version>${carbon.device.mgt.plugin.version}</version>
</feature>
<feature>
<id>org.wso2.carbon.device.mgt.iot.androidsense.feature.group</id>
<version>${carbon.device.mgt.plugin.version}</version>

@ -20,7 +20,7 @@ public class ConnectedCupMQttTransportHandler extends MQTTTransportHandler {
private static ConnectedCupMQttTransportHandler connectedCupMQttTransportHandler;
private static String publishTopic = "wso2/%s/" + DEVICE_TYPE + "/%s";
private static String publishTopic = "%s/" + DEVICE_TYPE + "/%s";
protected ConnectedCupMQttTransportHandler() {
super(iotServerSubscriber, DEVICE_TYPE, "tcp://localhost:1883", "");

@ -57,7 +57,7 @@ public class ConnectedCupManagerService implements DeviceManagementService{
@Override
public ProvisioningConfig getProvisioningConfig() {
return new ProvisioningConfig("carbon.super", true);
return new ProvisioningConfig("carbon.super", false);
}
@Override

@ -1025,11 +1025,6 @@
<artifactId>org.wso2.carbon.event.output.adapter.core</artifactId>
<version>${carbon.analytics.common.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.input.adapter.core</artifactId>
<version>${carbon.analytics.common.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.stream.core</artifactId>
@ -1040,24 +1035,27 @@
<artifactId>org.wso2.carbon.databridge.commons</artifactId>
<version>${carbon.analytics.common.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.iot</groupId>
<artifactId>org.wso2.carbon.event.input.adapter.extensions</artifactId>
<artifactId>org.wso2.carbon.event.output.adapter.extensions.ui</artifactId>
<version>${carbon.iot.device.mgt.version}</version>
</dependency>
<!--mqtt-->
<dependency>
<groupId>org.wso2.iot</groupId>
<artifactId>org.wso2.carbon.event.output.adapter.extensions.ui</artifactId>
<artifactId>org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization</artifactId>
<version>${carbon.iot.device.mgt.version}</version>
</dependency>
<!--mqtt-->
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>${eclipse.paho.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.andes.wso2</groupId>
<artifactId>andes</artifactId>
<version>${carbon.messaging.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

Loading…
Cancel
Save