diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..9ccb7b219 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hawkbit-dev@eclipse.org. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/README.md b/README.md index 990707312..c6f2d9b26 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,11 @@ see [hawkBit Documentation](https://www.eclipse.org/hawkbit/documentation/overvi * Want to chat with the team behind hawkBit? [![Join the chat at https://gitter.im/eclipse/hawkbit](https://badges.gitter.im/eclipse/hawkbit.svg)](https://gitter.im/eclipse/hawkbit?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) * Having issues with hawkBit? Open a [GitHub issue](https://github.com/eclipse/hawkbit/issues). -* You can also check out our [Project Homepage](https://projects.eclipse.org/projects/iot.hawkbit) for further contact options. +* You can also check out our [Project Homepage](https://www.eclipse.org/hawkbit) for further contact options. + +# Examples and Extensions + +Next to the hawkBit core hosted here the project maintains as well an [examples](https://github.com/eclipse/hawkbit-examples) and [extensions](https://github.com/eclipse/hawkbit-extensions) repositories. # hawkBit sandbox @@ -53,30 +57,31 @@ Next to the [Update Server](hawkbit-runtime/hawkbit-update-server) we are also p # Clone, build and run hawkBit -## Build +## Build and start hawkBit [Update Server](hawkbit-runtime/hawkbit-update-server) ``` $ git clone https://github.com/eclipse/hawkbit.git $ cd hawkbit $ mvn clean install -``` - -## Start hawkBit [Update Server](hawkbit-runtime/hawkbit-update-server) - -``` $ java -jar ./hawkbit-runtime/hawkbit-update-server/target/hawkbit-update-server-#version#.jar ``` -## Start hawkBit [Device Simulator](examples/hawkbit-device-simulator) (optional) +## Start hawkBit [Device Simulator](https://github.com/eclipse/hawkbit-examples/hawkbit-device-simulator) (optional) ``` -$ java -jar ./examples/hawkbit-device-simulator/target/hawkbit-device-simulator-#version#.jar +$ git clone https://github.com/eclipse/hawkbit-examples.git +$ cd hawkbit-examples +$ mvn clean install ``` -## Generate getting started data with the [Management API example](examples/hawkbit-example-mgmt-simulator) (optional) +``` +$ java -jar ./hawkbit-device-simulator/target/hawkbit-device-simulator-#version#.jar +``` + +## Generate getting started data with the [Management API example](https://github.com/eclipse/hawkbit-examples/hawkbit-example-mgmt-simulator) (optional) ``` -$ java -jar ./examples/hawkbit-example-mgmt-simulator/target/hawkbit-example-mgmt-simulator-#version#.jar +$ java -jar ./hawkbit-example-mgmt-simulator/target/hawkbit-example-mgmt-simulator-#version#.jar ``` # Releases and Roadmap diff --git a/docs/src/main/resources/_data/menus.yml b/docs/src/main/resources/_data/menus.yml index f488d0acd..bd11d3dc8 100644 --- a/docs/src/main/resources/_data/menus.yml +++ b/docs/src/main/resources/_data/menus.yml @@ -1,6 +1,2 @@ -- name: News - url: news/index.html -- name: Blog - url: blog/index.html - name: Documentation url: documentation/overview/introduction.html \ No newline at end of file diff --git a/docs/src/main/resources/documentation/architecture/rollout-management.md b/docs/src/main/resources/documentation/architecture/rollout-management.md index 9b7a1792c..f8e7a8f7b 100644 --- a/docs/src/main/resources/documentation/architecture/rollout-management.md +++ b/docs/src/main/resources/documentation/architecture/rollout-management.md @@ -8,7 +8,7 @@ title: Rollout Management Software update operations in large scale IoT scenarios with hundreds of thousands of devices require special handling. That includes: -- _Technical Scalability_ by means of horizontal scale of the _Rollouts_ server cluster in the cloud. +- _Technical Scalability_ by means of horizontal scale of the _hawkBit_ server cluster in the cloud. - _Global_ artifact _content delivery_ capacities. - _Functional Scalability_ by means of: - Secure handling of large volumes of devices at rollout creation time. diff --git a/docs/src/main/resources/documentation/guide/customtheme.md b/docs/src/main/resources/documentation/guide/customtheme.md index d10736359..172db179c 100644 --- a/docs/src/main/resources/documentation/guide/customtheme.md +++ b/docs/src/main/resources/documentation/guide/customtheme.md @@ -13,7 +13,7 @@ The mechanism described below is the rather simple case by customizing the theme # Example App -An example application with customized theme can be found [here](https://github.com/eclipse/hawkbit/tree/master/examples/hawkbit-custom-theme-example). +An example application with customized theme can be found [here](https://github.com/eclipse/hawkbit-examples/tree/master/hawkbit-custom-theme-example). # Overview Vaadin separates the appearance of the user interface from its logic using themes. Themes can include Sass or CSS style sheets, custom HTML layouts, and any necessary graphics. @@ -46,7 +46,7 @@ Every custom theme should always refer the base theme and customization can be d } ``` -- Finally the structure should be as in the [example app](https://github.com/eclipse/hawkbit/tree/master/examples/hawkbit-custom-theme-example/src/main/resources/VAADIN). +- Finally the structure should be as in the [example app](https://github.com/eclipse/hawkbit-examples/tree/master/hawkbit-custom-theme-example/src/main/resources/VAADIN). # Procedure to add a custom footer - Any footer can be added by creating "footer.html" in **src/main/resources --> VAADIN -- themes --> {XXXtheme} --> layouts** folder. An example can be found [here](https://github.com/eclipse/hawkbit/blob/master/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/layouts/footer.html). \ No newline at end of file diff --git a/docs/src/main/resources/documentation/guide/feignclient.md b/docs/src/main/resources/documentation/guide/feignclient.md index aaedf5de8..e8ead5074 100644 --- a/docs/src/main/resources/documentation/guide/feignclient.md +++ b/docs/src/main/resources/documentation/guide/feignclient.md @@ -6,14 +6,11 @@ title: Clustering {% include base.html %} # Create Feign REST Client -In this guide we describe how to create a [Feign](https://github.com/Netflix/feign) Rest Client based on a [Spring Boot](http://projects.spring.io/spring-boot/) Application. [hawkBit](https://projects.eclipse.org/projects/iot.hawkbit) provides REST interfaces for [Management API](https://github.com/eclipse/hawkbit/tree/master/hawkbit-ddi-api) and [DDI API] (https://github.com/eclipse/hawkbit/tree/master/hawkbit-ddi-api). Using this interfaces you can create a feign client with the help of the [feign inheritance support] (http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign-inheritance). -Our [example](https://github.com/eclipse/hawkbit/tree/master/examples) modules demonstrate how to create [Feign](https://github.com/Netflix/feign) client resources. Here you can find the [Management API client resources](https://github.com/eclipse/hawkbit/tree/master/examples/hawkbit-example-mgmt-feign-client) and the [DDI client resources](https://github.com/eclipse/hawkbit/tree/master/examples/hawkbit-example-ddi-feign-client). -A small [simulator application](https://github.com/eclipse/hawkbit/blob/master/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java) demonstrates how you can interact with the [hawkBit](https://projects.eclipse.org/projects/iot.hawkbit) via the [Management API +In this guide we describe how to create a [Feign](https://github.com/Netflix/feign) Rest Client based on a [Spring Boot](http://projects.spring.io/spring-boot/) Application. hawkBit provides REST interfaces for [Management API](https://github.com/eclipse/hawkbit/tree/master/hawkbit-ddi-api) and [DDI API] (https://github.com/eclipse/hawkbit/tree/master/hawkbit-ddi-api). Using this interfaces you can create a feign client with the help of the [feign inheritance support] (http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign-inheritance). +Our [example](https://github.com/eclipse/hawkbit-examples) modules demonstrate how to create [Feign](https://github.com/Netflix/feign) client resources. Here you can find the [Management API client resources](hhttps://github.com/eclipse/hawkbit-examples/tree/master/hawkbit-example-mgmt-feign-client) and the [DDI client resources](https://github.com/eclipse/hawkbit-examples/tree/master/hawkbit-example-ddi-feign-client). +A small [simulator application](https://github.com/eclipse/hawkbit-examples/tree/master/hawkbit-example-mgmt-simulator) demonstrates how you can interact with the hawkBit via the [Management API ](http://www.eclipse.org/hawkbit/documentation/interfaces/management-api.html). -Note: A hawkbit application have to be run. Therefore, you can use our [example application](https://github.com/eclipse/hawkbit/tree/master/examples/hawkbit-example-app) - - ### Example Managment API simulator In the follow code section, you can a see a feign client resource example. The interface extend the orgin api inteface to declare the `@FeignClient`. The `@FeignClient`declares that a REST client with that interface should be created. @@ -41,7 +38,7 @@ public class CreateStartedRolloutExample { ``` -At [hawkbit-example-core-feign-client](https://github.com/eclipse/hawkbit/tree/master/examples/hawkbit-example-core-feign-client) is a spring configuration to auto configure some beans, which can be reused for a own feign client. +At [hawkbit-example-core-feign-client](https://github.com/eclipse/hawkbit-examples/tree/master/hawkbit-example-core-feign-client) is a spring configuration to auto configure some beans, which can be reused for a own feign client. ``` @Configuration diff --git a/docs/src/main/resources/documentation/guide/runhawkbit.md b/docs/src/main/resources/documentation/guide/runhawkbit.md index b00d58121..948b56f81 100644 --- a/docs/src/main/resources/documentation/guide/runhawkbit.md +++ b/docs/src/main/resources/documentation/guide/runhawkbit.md @@ -20,12 +20,12 @@ This guide describes a target architecture that is more like one that you will e - [MariaDB](https://mariadb.org) for the repository. - [RabbitMQ](https://www.rabbitmq.com) for DMF communication. - For testing and demonstration purposes we will also use: - - [hawkBit Device Simulator](https://github.com/eclipse/hawkbit/tree/master/examples/hawkbit-device-simulator). - - [hawkBit Management API example client](https://github.com/eclipse/hawkbit/tree/master/examples/hawkbit-mgmt-api-client). + - [hawkBit Device Simulator](https://github.com/eclipse/hawkbit-examples/tree/master/hawkbit-device-simulator). + - [hawkBit Management API example client](https://github.com/eclipse/hawkbit-examples/tree/master/hawkbit-mgmt-api-client). # Prerequisites - You have a working [hawkBit core build](https://github.com/eclipse/hawkbit). -- You have a working [hawkBit examples build](https://github.com/eclipse/hawkbit/examples). +- You have a working [hawkBit examples build](https://github.com/eclipse/hawkbit-examples). # Steps @@ -66,7 +66,7 @@ spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 {% endhighlight %} -### Adapt hostname of example scenario [creation script](https://github.com/eclipse/hawkbit/tree/master/examples/hawkbit-mgmt-api-client) (optional) +### Adapt hostname of example scenario [creation script](https://github.com/eclipse/hawkbit-examples/blob/master/hawkbit-example-mgmt-simulator/src/main/resources/application.properties) Should only be necessary if your system does not run on localhost or uses a different port than the example app. @@ -86,7 +86,7 @@ hawkbit-example-mgmt-simulator-##VERSION##.jar --hawkbit.url=YOUR_HOST:PORT see [update server](https://github.com/eclipse/hawkbit/tree/master/hawkbit-runtime/hawkbit-update-server) -### Compile & Run example scenario [creation script](https://github.com/eclipse/hawkbit/tree/master/examples/hawkbit-mgmt-api-client) (optional). +### Compile & Run example scenario [creation script](https://github.com/eclipse/hawkbit-examples/tree/master/hawkbit-example-mgmt-simulator) (optional). This has to be done before the device simulator is started. _hawkBit_ creates the mandatory tenant metadata with first login into either _Management UI_ or API (which is done by this client). @@ -94,7 +94,7 @@ However, this is not done by _DMF_ which is in fact used by the device simulator ### Compile & Run device simulator (optional). -see [device simulator](https://github.com/eclipse/hawkbit/tree/master/examples/hawkbit-device-simulator) +see [device simulator](https://github.com/eclipse/hawkbit-examples/tree/master/hawkbit-device-simulator) ## Enjoy hawkBit with a real database, artifact storage and all [interfaces](../interfaces/interfaces.html) available. diff --git a/docs/src/main/resources/documentation/images/hawkBit_overview.jpeg b/docs/src/main/resources/documentation/images/hawkBit_overview.jpeg new file mode 100644 index 000000000..c16b20d88 Binary files /dev/null and b/docs/src/main/resources/documentation/images/hawkBit_overview.jpeg differ diff --git a/docs/src/main/resources/documentation/interfaces/interfaces.md b/docs/src/main/resources/documentation/interfaces/interfaces.md index c11154ddd..1f2ca4580 100644 --- a/docs/src/main/resources/documentation/interfaces/interfaces.md +++ b/docs/src/main/resources/documentation/interfaces/interfaces.md @@ -5,7 +5,7 @@ title: Interfaces {% include base.html %} -![](../images/interfaces.png){:width="100%"} +![](../images/hawkBit_overview.jpeg){:width="100%"} # Graphical User Interface diff --git a/docs/src/main/resources/documentation/interfaces/management-api.md b/docs/src/main/resources/documentation/interfaces/management-api.md index 6b5019a00..c5dd47f8a 100644 --- a/docs/src/main/resources/documentation/interfaces/management-api.md +++ b/docs/src/main/resources/documentation/interfaces/management-api.md @@ -37,7 +37,7 @@ Available Management APIs resources are: * [Target Tag](https://docs.bosch-iot-rollouts.com/documentation/rest-api/targettag-api-guide.html) * [Distribution Set Tag](https://docs.bosch-iot-rollouts.com/documentation/rest-api/distributionsettag-api-guide.html) * [Rollouts](https://docs.bosch-iot-rollouts.com/documentation/rest-api/rollout-api-guide.html) -* [Tenant](https://docs.bosch-iot-rollouts.com/documentation/rest-api/tenant-api-guide.html) +* [System Configuration](https://docs.bosch-iot-rollouts.com/documentation/rest-api/tenant-api-guide.html) ## Headers diff --git a/docs/src/main/resources/documentation/overview/features.md b/docs/src/main/resources/documentation/overview/features.md index 4079caadc..0cd3e3f93 100644 --- a/docs/src/main/resources/documentation/overview/features.md +++ b/docs/src/main/resources/documentation/overview/features.md @@ -3,4 +3,63 @@ layout: documentation title: Features --- -{% include base.html %} \ No newline at end of file +{% include base.html %} + +# Feature overview + +### Device and software repository +- Repository that holds the provisioning targets and assignable software distributions. +- That includes a full software update history for every device. +- Support for pre-commission devices in the repository and plug and play, i.e. device is created if it is authenticated for the first time. + +### Update Management +- Directly deploy a defined software distribution to a device (by Management UI or API). +- Update handling is independent of the device type, integration approach or connectivity. + +### Management UI/Console +- Create/Read/Update/Delete operations for provisioning targets (i.e. devices) and repository content (i.e. software). +- Manage and monitor software update operations. +- Optimized for professional users, e.g. administrators, developers and 2nd/3rd level support staff. +- Ease of use drag-and-drop paradigm. +- Flexible grouping of data. +- Flexible filters for data browsing. +- Responsive to resolution. +- Lazy loading of data. +- All information on one page. +- Optional integration with Bosch IoT Permissions service for full multi user support with fine granular permission based authorization. + +### Artifact Content Delivery +- Partial downloads supported. +- Download resume supported (RFC7233). +- Content management by RESTful API and UI (see above). +- Authorization based on software assignment, i.e. a device can only download what has been assigned to it in the first place. +- Delta artifact hosting supported. +- Artifact signature hosting supported. + +### Rollout/Campaign Management +- Secure handling of large volumes of devices at rollout creation time. +- Flexible deployment group definition as part of a rollout. +- Monitoring of the rollout progress. +- Emergency rollout shutdown in case of update failures. + +## Interfaces +### Management API +- RESTful API +- Create/Read/Update/Delete operations for provisioning targets (i.e. devices) and repository content (i.e. software). +- Manage and monitor software update operations. +- Online API documentation. +- JSON payload with Hypermedia support. +- Supports filtering, sorting and paging. + +### Direct Device Integration API +- RESTful HTTP based API for direct device integration + - JSON payload. + - Traffic optimized (content based Etag generation, not modified). +- Feedback channel from device. +- TLS encryption. + +### Device Management Federation API +- Indirect device integration through a device management service or application into hawkBit. +- Optimized for high service to service throughput with [AMQP](https://www.rabbitmq.com/amqp-0-9-1-reference.html) messaging interface. +- Separate AMQP vHost per tenant for maximum security. + diff --git a/docs/src/main/resources/documentation/overview/getting-started.md b/docs/src/main/resources/documentation/overview/getting-started.md index 93e4ee9b6..18a20a102 100644 --- a/docs/src/main/resources/documentation/overview/getting-started.md +++ b/docs/src/main/resources/documentation/overview/getting-started.md @@ -20,8 +20,7 @@ $ cd hawkbit $ mvn clean install {% endhighlight %} -#### Start hawkBit update server -[Example Application](https://github.com/eclipse/hawkbit/tree/master/examples/hawkbit-example-app) +#### Start hawkBit [update server](https://github.com/eclipse/hawkbit/tree/master/hawkbit-runtime/hawkbit-update-server) {% highlight bash %} $ java -jar ./hawkbit-runtime/hawkbit-update-server/target/hawkbit-update-server-#version#-SNAPSHOT.jar @@ -29,19 +28,19 @@ $ java -jar ./hawkbit-runtime/hawkbit-update-server/target/hawkbit-update-server #### Build hawkBit examples {% highlight bash %} -$ git clone https://github.com/eclipse/hawkbit.git -$ cd hawkbit/examples +$ git clone https://github.com/eclipse/hawkbit-examples.git +$ cd hawkbit-examples $ mvn clean install {% endhighlight %} #### Start hawkBit device simulator -[Device Simulator](https://github.com/eclipse/hawkbit/tree/master/examples/hawkbit-device-simulator) +[Device Simulator](https://github.com/eclipse/hawkbit-examples/tree/master/hawkbit-device-simulator) {% highlight bash %} -$ java -jar ./examples/hawkbit-device-simulator/target/hawkbit-device-simulator-#version#.jar +$ java -jar ./hawkbit-device-simulator/target/hawkbit-device-simulator-#version#.jar {% endhighlight %} #### Generate Getting Started data -[Example Management API Client](https://github.com/eclipse/hawkbit/tree/master/examples/hawkbit-example-mgmt-simulator) +[Example Management API Client](https://github.com/eclipse/hawkbit-examples/tree/master/hawkbit-example-mgmt-simulator) {% highlight bash %} -$ java -jar ./examples/hawkbit-example-mgmt-simulator/target/hawkbit-example-mgmt-simulator-#version#.jar +$ java -jar ./hawkbit-example-mgmt-simulator/target/hawkbit-example-mgmt-simulator-#version#.jar {% endhighlight %} diff --git a/examples/README.md b/examples/README.md deleted file mode 100644 index 5c60ec341..000000000 --- a/examples/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Examples - -Example projects that show how _hawkBit_ can be used to create, run or access an _hawkBit_ empowered update server. - -- `hawkbit-custom-theme-example` : Example for a customized theme for Management UI. -- `hawkbit-device-simulator` : Simulates device software updates, leveraging the hawkBit device integration options. -- `hawkbit-example-app` : Allows you to run the Spring Boot hawkBit app. Includes all _hawkBit_ interfaces, i.e. DDI, DMF, Mgmt-API, Mgmt-UI. -- `hawkbit-example-core-feign-client` : Core resources for the client examples. -- `hawkbit-example-ddi-feign-client` : Example _hawkBit_ DDI client based on the _hawkBit_ DDI API. -- `hawkbit-example-mgmt-feign-client` : Example _hawkBit_ Management client based on the _hawkBit_ Management API -- `hawkbit-example-mgmt-simulator` : Example client simulation for the _hawkBit_ Management API based on Spring Boot and the hawkbit-example-mgmt-feign-client. \ No newline at end of file diff --git a/examples/hawkbit-custom-theme-example/.gitignore b/examples/hawkbit-custom-theme-example/.gitignore deleted file mode 100644 index 6a3b2b405..000000000 --- a/examples/hawkbit-custom-theme-example/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/.springBeans diff --git a/examples/hawkbit-custom-theme-example/README.md b/examples/hawkbit-custom-theme-example/README.md deleted file mode 100644 index 5a6a571c8..000000000 --- a/examples/hawkbit-custom-theme-example/README.md +++ /dev/null @@ -1 +0,0 @@ -Theme customization example for Eclipse hawkBit. See wiki for the theme customization guide. \ No newline at end of file diff --git a/examples/hawkbit-custom-theme-example/pom.xml b/examples/hawkbit-custom-theme-example/pom.xml deleted file mode 100644 index f747e95bb..000000000 --- a/examples/hawkbit-custom-theme-example/pom.xml +++ /dev/null @@ -1,111 +0,0 @@ - - - 4.0.0 - - org.eclipse.hawkbit - hawkbit-examples-parent - 0.2.0-SNAPSHOT - - hawkbit-custom-theme-example - hawkBit :: Examples :: Custom Theme Example App - - - - - com.vaadin - vaadin-maven-plugin - ${vaadin.plugin.version} - - src/main/resources - - - - - update-theme - compile-theme - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - repackage - - - ${baseDir} - false - org.eclipse.hawkbit.app.Start - JAR - - - - - - - - - - - org.eclipse.hawkbit - hawkbit-autoconfigure - ${project.version} - - - org.eclipse.hawkbit - hawkbit-ui - ${project.version} - - - org.eclipse.hawkbit - hawkbit-security-integration - ${project.version} - - - org.eclipse.hawkbit - hawkbit-http-security - ${project.version} - - - org.eclipse.hawkbit - hawkbit-repository-jpa - ${project.version} - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-jetty - - - org.springframework.boot - spring-boot-starter - - - org.springframework.security - spring-security-aspects - - - com.h2database - h2 - - - - diff --git a/examples/hawkbit-custom-theme-example/src/main/java/org/eclipse/hawkbit/app/MyLoginUI.java b/examples/hawkbit-custom-theme-example/src/main/java/org/eclipse/hawkbit/app/MyLoginUI.java deleted file mode 100644 index 225a0573d..000000000 --- a/examples/hawkbit-custom-theme-example/src/main/java/org/eclipse/hawkbit/app/MyLoginUI.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.app; - -import org.eclipse.hawkbit.ui.login.AbstractHawkbitLoginUI; -import org.eclipse.hawkbit.ui.themes.HawkbitTheme; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; - -import com.vaadin.annotations.Theme; -import com.vaadin.annotations.Title; -import com.vaadin.spring.annotation.SpringUI; -import com.vaadin.spring.navigator.SpringViewProvider; - -/** - * Example hawkBit login UI implementation. - * - * A {@link SpringUI} annotated class must be present in the classpath for the - * login path. The easiest way to get an hawkBit login UI running is to extend - * the {@link AbstractHawkbitLoginUI} and to annotated it with {@link SpringUI} as in - * this example to the defined {@link HawkbitTheme#LOGIN_UI_PATH}. - * - */ -@SpringUI(path = HawkbitTheme.LOGIN_UI_PATH) -@Title("hawkBit Theme example") -@Theme(value = "exampletheme") -public class MyLoginUI extends AbstractHawkbitLoginUI { - - private static final long serialVersionUID = 1L; - - @Autowired - protected MyLoginUI(final SpringViewProvider viewProvider, final ApplicationContext context) { - super(viewProvider, context); - } - -} diff --git a/examples/hawkbit-custom-theme-example/src/main/java/org/eclipse/hawkbit/app/MyUI.java b/examples/hawkbit-custom-theme-example/src/main/java/org/eclipse/hawkbit/app/MyUI.java deleted file mode 100644 index 94e275d51..000000000 --- a/examples/hawkbit-custom-theme-example/src/main/java/org/eclipse/hawkbit/app/MyUI.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.eclipse.hawkbit.app; -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ - -import org.eclipse.hawkbit.ui.AbstractHawkbitUI; -import org.eclipse.hawkbit.ui.push.EventPushStrategy; - -import com.vaadin.annotations.Push; -import com.vaadin.annotations.Theme; -import com.vaadin.annotations.Title; -import com.vaadin.shared.communication.PushMode; -import com.vaadin.shared.ui.ui.Transport; -import com.vaadin.spring.annotation.SpringUI; - -/** - * Example hawkBit UI implementation. - * - * A {@link SpringUI} annotated class must be present in the classpath. The - * easiest way to get an hawkBit UI running is to extend the {@link AbstractHawkbitUI} - * and to annotated it with {@link SpringUI} as in this example. - * - */ -@SpringUI -@Push(value = PushMode.AUTOMATIC, transport = Transport.WEBSOCKET) -@Title("hawkBit Theme example") -@Theme(value = "exampletheme") -public class MyUI extends AbstractHawkbitUI { - - private static final long serialVersionUID = 1L; - - /** - * Constructor - * - * @param pushStrategy - * the push strategy - * @param eventBus - * the event bus - */ - public MyUI(final EventPushStrategy pushStrategy) { - super(pushStrategy); - } -} diff --git a/examples/hawkbit-custom-theme-example/src/main/java/org/eclipse/hawkbit/app/Start.java b/examples/hawkbit-custom-theme-example/src/main/java/org/eclipse/hawkbit/app/Start.java deleted file mode 100644 index fdad8a999..000000000 --- a/examples/hawkbit-custom-theme-example/src/main/java/org/eclipse/hawkbit/app/Start.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.eclipse.hawkbit.app; -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ - -import org.eclipse.hawkbit.autoconfigure.security.EnableHawkbitManagedSecurityConfiguration; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * A {@link SpringBootApplication} annotated class with a main method to start. - * The minimal configuration for the stand alone hawkBit server. - * - */ -@SpringBootApplication -@EnableHawkbitManagedSecurityConfiguration -// Exception squid:S1118 - Spring boot standard behavior -@SuppressWarnings({ "squid:S1118" }) -public class Start { - /** - * Main method to start the spring-boot application. - * - * @param args - * the VM arguments. - */ - // Exception squid:S2095 - Spring boot standard behavior - @SuppressWarnings({ "squid:S2095" }) - public static void main(final String[] args) { - SpringApplication.run(Start.class, args); - } -} diff --git a/examples/hawkbit-custom-theme-example/src/main/resources/VAADIN/themes/exampletheme/.gitignore b/examples/hawkbit-custom-theme-example/src/main/resources/VAADIN/themes/exampletheme/.gitignore deleted file mode 100644 index 1cdd02b74..000000000 --- a/examples/hawkbit-custom-theme-example/src/main/resources/VAADIN/themes/exampletheme/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/addons.scss -/styles.css diff --git a/examples/hawkbit-custom-theme-example/src/main/resources/VAADIN/themes/exampletheme/customstyles/examplevariables.scss b/examples/hawkbit-custom-theme-example/src/main/resources/VAADIN/themes/exampletheme/customstyles/examplevariables.scss deleted file mode 100644 index 6bf201f9c..000000000 --- a/examples/hawkbit-custom-theme-example/src/main/resources/VAADIN/themes/exampletheme/customstyles/examplevariables.scss +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ - -$dark-gray: #848484; - -//Example color change -$hawkbit-primary-color: $dark-gray; -$hawkbit-primary-color-light: #D8D8D8; -$app-selection-item-selection-color: $dark-gray; -$app-focus-color: $dark-gray; -$app-selection-color: $dark-gray; -$tag-text-color: $dark-gray; -$tab-sheet-caption-color: $dark-gray; -$table-details-tab-font-color: $dark-gray; -$widget-caption-color: $dark-gray; -$accordion-action-history-title-color: $dark-gray; -$menu-title-bg-color: $dark-gray; -$button-icon-color: $dark-gray; \ No newline at end of file diff --git a/examples/hawkbit-custom-theme-example/src/main/resources/VAADIN/themes/exampletheme/images/profile-pic-57px.jpg b/examples/hawkbit-custom-theme-example/src/main/resources/VAADIN/themes/exampletheme/images/profile-pic-57px.jpg deleted file mode 100644 index d730cb5f6..000000000 Binary files a/examples/hawkbit-custom-theme-example/src/main/resources/VAADIN/themes/exampletheme/images/profile-pic-57px.jpg and /dev/null differ diff --git a/examples/hawkbit-custom-theme-example/src/main/resources/VAADIN/themes/exampletheme/layouts/footer.html b/examples/hawkbit-custom-theme-example/src/main/resources/VAADIN/themes/exampletheme/layouts/footer.html deleted file mode 100644 index f2ac781ba..000000000 --- a/examples/hawkbit-custom-theme-example/src/main/resources/VAADIN/themes/exampletheme/layouts/footer.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - diff --git a/examples/hawkbit-custom-theme-example/src/main/resources/VAADIN/themes/exampletheme/styles.scss b/examples/hawkbit-custom-theme-example/src/main/resources/VAADIN/themes/exampletheme/styles.scss deleted file mode 100644 index 4b3f29814..000000000 --- a/examples/hawkbit-custom-theme-example/src/main/resources/VAADIN/themes/exampletheme/styles.scss +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ - -@import "../hawkbit/customstyles/hawkbitvariables"; -@import "customstyles/examplevariables"; -@import "../hawkbit/hawkbittheme"; -@import "addons"; - -// This file prefixes all rules with the theme name to avoid causing conflicts with other themes. -.exampletheme { - @include addons; - @include hawkbittheme; -} diff --git a/examples/hawkbit-custom-theme-example/src/main/resources/application.properties b/examples/hawkbit-custom-theme-example/src/main/resources/application.properties deleted file mode 100644 index 3ffb51bd0..000000000 --- a/examples/hawkbit-custom-theme-example/src/main/resources/application.properties +++ /dev/null @@ -1,16 +0,0 @@ -# -# Copyright (c) 2015 Bosch Software Innovations GmbH and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://www.eclipse.org/legal/epl-v10.html -# - -# UI demo account -hawkbit.server.ui.demo.password=admin -hawkbit.server.ui.demo.user=admin -hawkbit.server.ui.demo.tenant=DEFAULT - -# UI help links -hawkbit.server.ui.links.documentation.root=https://github.com/eclipse/hawkbit diff --git a/examples/hawkbit-device-simulator/.gitignore b/examples/hawkbit-device-simulator/.gitignore deleted file mode 100644 index 09e3bc9b2..000000000 --- a/examples/hawkbit-device-simulator/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/bin/ -/target/ diff --git a/examples/hawkbit-device-simulator/README.md b/examples/hawkbit-device-simulator/README.md deleted file mode 100644 index 4d8183dd7..000000000 --- a/examples/hawkbit-device-simulator/README.md +++ /dev/null @@ -1,78 +0,0 @@ -# hawkBit Device Simulator - -The device simulator handles software update commands from the update server. - -## Run on your own workstation -``` -java -jar examples/hawkbit-device-simulator/target/hawkbit-device-simulator-*-SNAPSHOT.jar -``` -Or: -``` -run org.eclipse.hawkbit.simulator.DeviceSimulator -``` - -## Deploy to cloud foundry environment - -- Go to ```target``` subfolder. -- Run ```cf push``` - -## Notes - -The simulator has user authentication enabled in **cloud profile**. Default credentials: -* username : admin -* passwd : admin - -This can be configured/disabled by spring boot properties - -## hawkBit APIs - -The simulator supports `DDI` as well as the `DMF` integration APIs. - -In case there is no AMQP message broker (like rabbitMQ) running, you can disable the AMQP support for the device simulator, so the simulator is not trying to connect to an amqp message broker. - -Configuration property `hawkbit.device.simulator.amqp.enabled=false` - -## Usage - -### Graphical User Interface -The device simulator comes with a graphical user interface which makes it very easy to generate dummy devices handled by the device simulator. -The status and the update progress of the simulated device are shown in the UI. -The UI can be accessed via the URL: -``` -http://localhost:8083 -``` - - ![](src/main/images/generateScreenshot.png) - - ![](src/main/images/updateProcessScreenshot.png) - - ![](src/main/images/updateResultOverviewScreenshot.png) - - -### REST API -The device simulator exposes an REST-API which can be used to trigger device creation. - -Optional parameters: -* name : name prefix simulated devices (default: "dmfSimulated"), followed by counter -* amount : number of simulated devices (default: 20, capped at: 4000) -* tenant : in a multi-tenenat ready hawkBit installation (default: "DEFAULT") -* api : the API which should be used for the simulated device either `dmf` or `ddi` (default: "ddi") -* endpoint : URL which defines the hawkbit DDI base endpoint (deffault: "http://localhost:8080") -* polldelay : number in milliseconds of the delay when DDI simulated devices should poll the endpoint (default: "30") -* gatewaytoken : an hawkbit gateway token to be used in case hawkbit does not allow anonymous access for DDI devices (default: "") - - -Example: for 20 simulated devices (default) -``` -http://localhost:8083/start -``` - -Example: for 10 simulated devices that start with the name prefix "activeSim": -``` -http://localhost:8083/start?amount=10&name=activeSim -``` - -Example: for 5 simulated devices that start with the name prefix "ddi" using the Direct Device Integration API (http) authenticated by given gateway token, a pool interval of 10 seconds and a custom port for the DDI service.: -``` -http://localhost:8083/start?amount=5&name=ddi&api=ddi&gatewaytoken=d5F2mmlARiMuMOquRmLlxW4xZFHy4mEV&polldelay=10&endpoint=http://localhost:8085 -``` diff --git a/examples/hawkbit-device-simulator/cf/manifest.yml b/examples/hawkbit-device-simulator/cf/manifest.yml deleted file mode 100644 index efc18ab45..000000000 --- a/examples/hawkbit-device-simulator/cf/manifest.yml +++ /dev/null @@ -1,20 +0,0 @@ -# -# Copyright (c) 2015 Bosch Software Innovations GmbH and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://www.eclipse.org/legal/epl-v10.html -# - ---- -applications: -- name: hawkbit-simulator - memory: 1024M - instances: 1 - buildpack: https://github.com/cloudfoundry/java-buildpack - path: @project.build.finalName@.jar - services: - - dmf-rabbit - env: - SPRING_PROFILES_ACTIVE: cloud diff --git a/examples/hawkbit-device-simulator/pom.xml b/examples/hawkbit-device-simulator/pom.xml deleted file mode 100644 index d9d8fd23a..000000000 --- a/examples/hawkbit-device-simulator/pom.xml +++ /dev/null @@ -1,142 +0,0 @@ - - - 4.0.0 - - org.eclipse.hawkbit - 0.2.0-SNAPSHOT - hawkbit-examples-parent - - - hawkbit-device-simulator - hawkBit :: Examples :: Device Simulator - Device Management Federation API based simulator - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - repackage - - - ${baseDir} - false - org.eclipse.hawkbit.simulator.DeviceSimulator - JAR - - - - - - - - src/main/resources - - - cf - true - ${project.build.directory} - - manifest.yml - - - - - - - - org.eclipse.hawkbit - hawkbit-dmf-api - ${project.version} - - - org.springframework.amqp - spring-rabbit - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-jetty - - - org.springframework.boot - spring-boot-starter-logging - - - org.springframework.security - spring-security-web - - - org.springframework.security - spring-security-config - - - org.springframework.boot - spring-boot-starter - - - org.springframework.boot - spring-boot-starter-actuator - - - com.vaadin - vaadin-spring-boot-starter - - - com.vaadin - vaadin-push - - - org.springframework.boot - spring-boot-autoconfigure - - - com.google.guava - guava - - - io.github.openfeign - feign-jackson - - - io.github.openfeign - feign-core - - - com.jayway.jsonpath - json-path - - - org.apache.httpcomponents - httpclient - - - - - - com.vaadin - vaadin-bom - ${vaadin.version} - pom - import - - - - diff --git a/examples/hawkbit-device-simulator/src/main/images/generateScreenshot.png b/examples/hawkbit-device-simulator/src/main/images/generateScreenshot.png deleted file mode 100644 index 6c31c2d7d..000000000 Binary files a/examples/hawkbit-device-simulator/src/main/images/generateScreenshot.png and /dev/null differ diff --git a/examples/hawkbit-device-simulator/src/main/images/updateProcessScreenshot.png b/examples/hawkbit-device-simulator/src/main/images/updateProcessScreenshot.png deleted file mode 100644 index dd3652790..000000000 Binary files a/examples/hawkbit-device-simulator/src/main/images/updateProcessScreenshot.png and /dev/null differ diff --git a/examples/hawkbit-device-simulator/src/main/images/updateResultOverviewScreenshot.png b/examples/hawkbit-device-simulator/src/main/images/updateResultOverviewScreenshot.png deleted file mode 100644 index 78e16758f..000000000 Binary files a/examples/hawkbit-device-simulator/src/main/images/updateResultOverviewScreenshot.png and /dev/null differ diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/AbstractSimulatedDevice.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/AbstractSimulatedDevice.java deleted file mode 100644 index a2a036e1b..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/AbstractSimulatedDevice.java +++ /dev/null @@ -1,189 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator; - -import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus; - -/** - * The bean of a simulated device which can be stored in the - * {@link DeviceSimulatorRepository} or shown in the UI. - * - * @author Michael Hirsch - * - */ -public abstract class AbstractSimulatedDevice { - - private String id; - private String tenant; - private Status status; - private double progress; - private String swversion = "unknown"; - private UpdateStatus updateStatus = new UpdateStatus(ResponseStatus.SUCCESSFUL, "Simulation complete!"); - private Protocol protocol = Protocol.DMF_AMQP; - private String targetSecurityToken; - private int pollDelaySec; - private int nextPollCounterSec; - - /** - * Enum definition of the protocol to be used for the simulated device. - * - */ - public enum Protocol { - /** - * Device Management Federation API via AMQP, push mechanism. - */ - DMF_AMQP, - /** - * Direct Device Interface via HTTP, poll mechanism. - */ - DDI_HTTP; - } - - /** - * The current status of the simulated device. - * - * @author Michael Hirsch - * - */ - public enum Status { - /** - * device is in status unknown. - */ - UNKNWON, - /** - * device is in status pending which represents is updating software. - */ - PEDNING, - /** - * device has been updated successfully. - */ - FINISH, - /** - * device has been updated with an error. - */ - ERROR; - } - - /** - * empty constructor. - */ - AbstractSimulatedDevice() { - - } - - /** - * Creates a new simulated device. - * - * @param id - * the ID of the simulated device - * @param tenant - * the tenant of the simulated device - * @param int - * pollDelaySec - */ - AbstractSimulatedDevice(final String id, final String tenant, final Protocol protocol, final int pollDelaySec) { - this.id = id; - this.tenant = tenant; - this.status = Status.UNKNWON; - this.progress = 0.0; - this.protocol = protocol; - this.pollDelaySec = pollDelaySec; - } - - /** - * Can be called by a scheduler to trigger a device polling, like in real - * scenarios devices are frequently asking for updates etc. - */ - public abstract void poll(); - - public int getPollDelaySec() { - return pollDelaySec; - } - - public void setPollDelaySec(final int pollDelaySec) { - this.pollDelaySec = pollDelaySec; - } - - /** - * Method to clean-up resource e.g. when the simulated device has been - * removed from the repository. - */ - public void clean() { - - } - - public String getId() { - return id; - } - - public Status getStatus() { - return status; - } - - public double getProgress() { - return progress; - } - - public String getTenant() { - return tenant; - } - - public void setId(final String id) { - this.id = id; - } - - public void setTenant(final String tenant) { - this.tenant = tenant; - } - - public void setStatus(final Status status) { - this.status = status; - } - - public void setProgress(final double progress) { - this.progress = progress; - } - - public String getSwversion() { - return swversion; - } - - public void setSwversion(final String swversion) { - this.swversion = swversion; - } - - public UpdateStatus getUpdateStatus() { - return updateStatus; - } - - public void setUpdateStatus(final UpdateStatus updateStatus) { - this.updateStatus = updateStatus; - } - - public Protocol getProtocol() { - return protocol; - } - - public int getNextPollCounterSec() { - return nextPollCounterSec; - } - - public void setNextPollCounterSec(final int nextPollDelayInSec) { - this.nextPollCounterSec = nextPollDelayInSec; - } - - public String getTargetSecurityToken() { - return targetSecurityToken; - } - - public void setTargetSecurityToken(final String targetSecurityToken) { - this.targetSecurityToken = targetSecurityToken; - } - -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DDISimulatedDevice.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DDISimulatedDevice.java deleted file mode 100644 index 677d77a37..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DDISimulatedDevice.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator; - -import org.eclipse.hawkbit.simulator.http.ControllerResource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.jayway.jsonpath.JsonPath; -import com.jayway.jsonpath.PathNotFoundException; - -/** - * A simulated device using the DDI API of the hawkBit update server. - * - */ -public class DDISimulatedDevice extends AbstractSimulatedDevice { - - private static final Logger LOGGER = LoggerFactory.getLogger(DDISimulatedDevice.class); - - private final ControllerResource controllerResource; - - private final DeviceSimulatorUpdater deviceUpdater; - - private volatile boolean removed; - private volatile Long currentActionId; - - /** - * @param id - * the ID of the device - * @param tenant - * the tenant of the simulated device - * @param pollDelaySec - * the delay of the poll interval in sec - * @param controllerResource - * the http controller resource - * @param deviceUpdater - * the service to update devices - */ - public DDISimulatedDevice(final String id, final String tenant, final int pollDelaySec, - final ControllerResource controllerResource, final DeviceSimulatorUpdater deviceUpdater) { - super(id, tenant, Protocol.DDI_HTTP, pollDelaySec); - this.controllerResource = controllerResource; - this.deviceUpdater = deviceUpdater; - } - - @Override - public void clean() { - super.clean(); - removed = true; - } - - /** - * Polls the base URL for the DDI API interface. - */ - @Override - public void poll() { - if (!removed) { - final String basePollJson = controllerResource.get(getTenant(), getId()); - try { - final String href = JsonPath.parse(basePollJson).read("_links.deploymentBase.href"); - final long actionId = Long.parseLong(href.substring(href.lastIndexOf('/') + 1, href.indexOf('?'))); - if (currentActionId == null) { - final String deploymentJson = controllerResource.getDeployment(getTenant(), getId(), actionId); - final String swVersion = JsonPath.parse(deploymentJson).read("deployment.chunks[0].version"); - currentActionId = actionId; - startDdiUpdate(actionId, swVersion); - } - } catch (final PathNotFoundException e) { - // href might not be in the json response, so ignore - // exception here. - LOGGER.trace("Response does not contain a deploymentbase href link, ignoring.", e); - } - - } - } - - private void startDdiUpdate(final long actionId, final String swVersion) { - deviceUpdater.startUpdate(getTenant(), getId(), actionId, swVersion, null, null, (device, actionId1) -> { - switch (device.getUpdateStatus().getResponseStatus()) { - case SUCCESSFUL: - controllerResource.postSuccessFeedback(getTenant(), getId(), actionId1); - break; - case ERROR: - controllerResource.postErrorFeedback(getTenant(), getId(), actionId1); - break; - default: - throw new IllegalStateException("simulated device has an unknown response status + " - + device.getUpdateStatus().getResponseStatus()); - } - currentActionId = null; - }); - } -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DMFSimulatedDevice.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DMFSimulatedDevice.java deleted file mode 100644 index 65227b55d..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DMFSimulatedDevice.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator; - -import org.eclipse.hawkbit.simulator.amqp.SpSenderService; - -/** - * A simulated device using the DMF API of the hawkBit update server. - */ -public class DMFSimulatedDevice extends AbstractSimulatedDevice { - private final SpSenderService spSenderService; - - /** - * @param id - * the ID of the device - * @param tenant - * the tenant of the simulated device - */ - public DMFSimulatedDevice(final String id, final String tenant, final SpSenderService spSenderService, - final int pollDelaySec) { - super(id, tenant, Protocol.DMF_AMQP, pollDelaySec); - this.spSenderService = spSenderService; - } - - @Override - public void poll() { - spSenderService.createOrUpdateThing(super.getTenant(), super.getId()); - } - -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulator.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulator.java deleted file mode 100644 index 6cfb19bc2..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulator.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator; - -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.scheduling.TaskScheduler; -import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler; - -import com.google.common.eventbus.AsyncEventBus; -import com.google.common.eventbus.EventBus; -import com.vaadin.spring.annotation.EnableVaadin; - -/** - * The main-method to start the Spring-Boot application. - * - */ -@SpringBootApplication -@EnableVaadin -@EnableScheduling -public class DeviceSimulator { - - public DeviceSimulator() { - // utility class - } - - /** - * @return an asynchronous event bus to publish and retrieve events. - */ - @Bean - EventBus eventBus() { - return new AsyncEventBus(Executors.newFixedThreadPool(4)); - } - - /** - * @return central ScheduledExecutorService - */ - @Bean - ScheduledExecutorService threadPool() { - return Executors.newScheduledThreadPool(8); - } - - @Bean - TaskScheduler taskScheduler() { - return new ConcurrentTaskScheduler(threadPool()); - } - - /** - * Start the Spring Boot Application. - * - * @param args - * the args - */ - // Exception squid:S2095 - Spring boot standard behavior - @SuppressWarnings({ "squid:S2095" }) - public static void main(final String[] args) { - SpringApplication.run(DeviceSimulator.class, args); - } -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulatorRepository.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulatorRepository.java deleted file mode 100644 index 8b70c7469..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulatorRepository.java +++ /dev/null @@ -1,143 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import org.springframework.stereotype.Service; - -/** - * An in-memory simulated device repository to hold the simulated device in - * memory and be able to retrieve them again. - * - * @author Michael Hirsch - * - */ -@Service -public class DeviceSimulatorRepository { - - private final Map devices = new ConcurrentHashMap<>(); - - private final Set tenants = new HashSet<>(); - - /** - * Adds a simulated device to the repository. - * - * @param simulatedDevice - * the device to add - * @return the device which has been added to the repository - */ - public AbstractSimulatedDevice add(final AbstractSimulatedDevice simulatedDevice) { - devices.put(new DeviceKey(simulatedDevice.getTenant().toLowerCase(), simulatedDevice.getId()), simulatedDevice); - tenants.add(simulatedDevice.getTenant().toLowerCase()); - return simulatedDevice; - } - - /** - * @return all simulated devices - */ - public Collection getAll() { - return devices.values(); - } - - /** - * Retrieves a single simulated devices or {@code null} if device does not - * exists. - * - * @param tenant - * the tenant of the simulated device - * @param id - * the ID of the device - * @return a simulated device from the repository or {@code null} if device - * does not exixts. - */ - public AbstractSimulatedDevice get(final String tenant, final String id) { - return devices.get(new DeviceKey(tenant.toLowerCase(), id)); - } - - /** - * Removes a device from the simulation. - * - * @param tenant - * the tenant of the simulated device - * @param id - * the ID of the device - * @return the simulated device or null if it was not in the - * repository - */ - public AbstractSimulatedDevice remove(final String tenant, final String id) { - return devices.remove(new DeviceKey(tenant.toLowerCase(), id)); - } - - public Set getTenants() { - return tenants; - } - - /** - * Clears all stored devices. - */ - public void clear() { - devices.values().forEach(AbstractSimulatedDevice::clean); - devices.clear(); - tenants.clear(); - } - - private static final class DeviceKey { - private final String tenant; - private final String id; - - private DeviceKey(final String tenant, final String id) { - this.tenant = tenant; - this.id = id; - } - - @Override - public int hashCode() {// NOSONAR - as this is generated - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - result = prime * result + ((tenant == null) ? 0 : tenant.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) {// NOSONAR - as this is - // generated - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final DeviceKey other = (DeviceKey) obj; - if (id == null) { - if (other.id != null) { - return false; - } - } else if (!id.equals(other.id)) { - return false; - } - if (tenant == null) { - if (other.tenant != null) { - return false; - } - } else if (!tenant.equals(other.tenant)) { - return false; - } - return true; - } - } -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulatorUpdater.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulatorUpdater.java deleted file mode 100644 index 5b0f8273f..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulatorUpdater.java +++ /dev/null @@ -1,373 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.security.DigestOutputStream; -import java.security.KeyManagementException; -import java.security.KeyStoreException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLContextBuilder; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.eclipse.hawkbit.dmf.json.model.DmfArtifact; -import org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule; -import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol; -import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus; -import org.eclipse.hawkbit.simulator.amqp.SpSenderService; -import org.eclipse.hawkbit.simulator.event.InitUpdate; -import org.eclipse.hawkbit.simulator.event.ProgressUpdate; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; - -import com.google.common.eventbus.EventBus; -import com.google.common.io.BaseEncoding; -import com.google.common.io.ByteStreams; - -/** - * Update simulation handler. - * - */ -@Service -public class DeviceSimulatorUpdater { - - private static final Logger LOGGER = LoggerFactory.getLogger(DeviceSimulatorUpdater.class); - - @Autowired - private ScheduledExecutorService threadPool; - - @Autowired - private SpSenderService spSenderService; - - @Autowired - private SimulatedDeviceFactory deviceFactory; - - @Autowired - private EventBus eventbus; - - @Autowired - private DeviceSimulatorRepository repository; - - /** - * Starting an simulated update process of an simulated device. - * - * @param tenant - * the tenant of the device - * @param id - * the ID of the simulated device - * @param actionId - * the actionId from the hawkbit update server to start the - * update. - * @param modules - * the software module version from the hawkbit update server - * @param swVersion - * the software version as static value in case modules is null - * @param targetSecurityToken - * the target security token for download authentication - * @param callback - * the callback which gets called when the simulated update - * process has been finished - */ - public void startUpdate(final String tenant, final String id, final long actionId, final String swVersion, - final List modules, final String targetSecurityToken, final UpdaterCallback callback) { - AbstractSimulatedDevice device = repository.get(tenant, id); - - // plug and play - non existing device will be auto created - if (device == null) { - device = repository - .add(deviceFactory.createSimulatedDevice(id, tenant, Protocol.DMF_AMQP, 1800, null, null)); - } - - device.setProgress(0.0); - - if (CollectionUtils.isEmpty(modules)) { - device.setSwversion(swVersion); - } else { - device.setSwversion( - modules.stream().map(DmfSoftwareModule::getModuleVersion).collect(Collectors.joining(", "))); - } - device.setTargetSecurityToken(targetSecurityToken); - eventbus.post(new InitUpdate(device)); - - threadPool.schedule(new DeviceSimulatorUpdateThread(device, spSenderService, actionId, eventbus, threadPool, - callback, modules), 2_000, TimeUnit.MILLISECONDS); - } - - private static final class DeviceSimulatorUpdateThread implements Runnable { - - private static final String BUT_GOT_LOG_MESSAGE = " but got: "; - - private static final String DOWNLOAD_LOG_MESSAGE = "Download "; - - private static final int MINIMUM_TOKENLENGTH_FOR_HINT = 6; - - private static final Random rndSleep = new SecureRandom(); - - private final AbstractSimulatedDevice device; - private final SpSenderService spSenderService; - private final long actionId; - private final EventBus eventbus; - private final ScheduledExecutorService threadPool; - private final UpdaterCallback callback; - private final List modules; - - private DeviceSimulatorUpdateThread(final AbstractSimulatedDevice device, final SpSenderService spSenderService, - final long actionId, final EventBus eventbus, final ScheduledExecutorService threadPool, - final UpdaterCallback callback, final List modules) { - this.device = device; - this.spSenderService = spSenderService; - this.actionId = actionId; - this.eventbus = eventbus; - this.callback = callback; - this.modules = modules; - this.threadPool = threadPool; - } - - @Override - public void run() { - if (device.getProgress() <= 0 && modules != null) { - device.setUpdateStatus(simulateDownloads(device.getTargetSecurityToken())); - if (isErrorResponse(device.getUpdateStatus())) { - device.setProgress(1.0); - callback.updateFinished(device, actionId); - eventbus.post(new ProgressUpdate(device)); - return; - } - // download is 80% of the game after all - device.setProgress(0.8); - } - - final double newProgress = device.getProgress() + 0.2; - device.setProgress(newProgress); - if (newProgress < 1.0) { - threadPool.schedule(new DeviceSimulatorUpdateThread(device, spSenderService, actionId, eventbus, - threadPool, callback, modules), rndSleep.nextInt(5_000), TimeUnit.MILLISECONDS); - } else { - callback.updateFinished(device, actionId); - } - eventbus.post(new ProgressUpdate(device)); - } - - private UpdateStatus simulateDownloads(final String targetToken) { - final List status = new ArrayList<>(); - - LOGGER.info("Simulate downloads for {}", device.getId()); - - modules.forEach( - module -> module.getArtifacts().forEach(artifact -> handleArtifact(targetToken, status, artifact))); - - final UpdateStatus result = new UpdateStatus(ResponseStatus.SUCCESSFUL); - result.getStatusMessages().add("Simulation complete!"); - status.forEach(download -> { - result.getStatusMessages().addAll(download.getStatusMessages()); - if (isErrorResponse(download)) { - result.setResponseStatus(ResponseStatus.ERROR); - } - }); - - LOGGER.info("Download simulations complete for {}", device.getId()); - - return result; - } - - private static boolean isErrorResponse(final UpdateStatus status) { - if (status == null) { - return false; - } - - return ResponseStatus.ERROR.equals(status.getResponseStatus()); - } - - private static void handleArtifact(final String targetToken, final List status, - final DmfArtifact artifact) { - - if (artifact.getUrls().containsKey("HTTPS")) { - status.add(downloadUrl(artifact.getUrls().get("HTTPS"), targetToken, artifact.getHashes().getSha1(), - artifact.getSize())); - } else if (artifact.getUrls().containsKey("HTTP")) { - status.add(downloadUrl(artifact.getUrls().get("HTTP"), targetToken, artifact.getHashes().getSha1(), - artifact.getSize())); - } - } - - private static UpdateStatus downloadUrl(final String url, final String targetToken, final String sha1Hash, - final long size) { - - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Downloading {} with token {}, expected sha1 hash {} and size {}", url, - hideTokenDetails(targetToken), sha1Hash, size); - } - - try { - return readAndCheckDownloadUrl(url, targetToken, sha1Hash, size); - } catch (IOException | KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) { - LOGGER.error("Failed to download " + url, e); - return new UpdateStatus(ResponseStatus.ERROR, "Failed to download " + url + ": " + e.getMessage()); - } - - } - - private static UpdateStatus readAndCheckDownloadUrl(final String url, final String targetToken, - final String sha1Hash, final long size) - throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException, IOException { - long overallread; - final CloseableHttpClient httpclient = createHttpClientThatAcceptsAllServerCerts(); - final HttpGet request = new HttpGet(url); - request.addHeader(HttpHeaders.AUTHORIZATION, "TargetToken " + targetToken); - - final String sha1HashResult; - try (final CloseableHttpResponse response = httpclient.execute(request)) { - - if (response.getStatusLine().getStatusCode() != HttpStatus.OK.value()) { - final String message = wrongStatusCode(url, response); - return new UpdateStatus(ResponseStatus.ERROR, message); - } - - if (response.getEntity().getContentLength() != size) { - final String message = wrongContentLength(url, size, response); - return new UpdateStatus(ResponseStatus.ERROR, message); - } - - // Exception squid:S2070 - not used for hashing sensitive - // data - @SuppressWarnings("squid:S2070") - final MessageDigest md = MessageDigest.getInstance("SHA-1"); - - overallread = getOverallRead(response, md); - - if (overallread != size) { - final String message = incompleteRead(url, size, overallread); - return new UpdateStatus(ResponseStatus.ERROR, message); - } - - sha1HashResult = BaseEncoding.base16().lowerCase().encode(md.digest()); - } - - if (!sha1Hash.equalsIgnoreCase(sha1HashResult)) { - final String message = wrongHash(url, sha1Hash, overallread, sha1HashResult); - return new UpdateStatus(ResponseStatus.ERROR, message); - } - - final String message = "Downloaded " + url + " (" + overallread + " bytes)"; - LOGGER.debug(message); - return new UpdateStatus(ResponseStatus.SUCCESSFUL, message); - } - - private static long getOverallRead(final CloseableHttpResponse response, final MessageDigest md) - throws IOException { - - long overallread; - - try (final OutputStream os = ByteStreams.nullOutputStream(); - final BufferedOutputStream bos = new BufferedOutputStream(new DigestOutputStream(os, md))) { - - try (BufferedInputStream bis = new BufferedInputStream(response.getEntity().getContent())) { - overallread = ByteStreams.copy(bis, bos); - } - } - - return overallread; - } - - private static String hideTokenDetails(final String targetToken) { - if (targetToken == null) { - return ""; - } - - if (targetToken.isEmpty()) { - return ""; - } - - if (targetToken.length() <= MINIMUM_TOKENLENGTH_FOR_HINT) { - return "***"; - } - - return targetToken.substring(0, 2) + "***" - + targetToken.substring(targetToken.length() - 2, targetToken.length()); - } - - private static String wrongHash(final String url, final String sha1Hash, final long overallread, - final String sha1HashResult) { - final String message = DOWNLOAD_LOG_MESSAGE + url + " failed with SHA1 hash missmatch (Expected: " - + sha1Hash + BUT_GOT_LOG_MESSAGE + sha1HashResult + ") (" + overallread + " bytes)"; - LOGGER.error(message); - return message; - } - - private static String incompleteRead(final String url, final long size, final long overallread) { - final String message = DOWNLOAD_LOG_MESSAGE + url + " is incomplete (Expected: " + size - + BUT_GOT_LOG_MESSAGE + overallread + ")"; - LOGGER.error(message); - return message; - } - - private static String wrongContentLength(final String url, final long size, - final CloseableHttpResponse response) { - final String message = DOWNLOAD_LOG_MESSAGE + url + " has wrong content length (Expected: " + size - + BUT_GOT_LOG_MESSAGE + response.getEntity().getContentLength() + ")"; - LOGGER.error(message); - return message; - } - - private static String wrongStatusCode(final String url, final CloseableHttpResponse response) { - final String message = DOWNLOAD_LOG_MESSAGE + url + " failed (" + response.getStatusLine().getStatusCode() - + ")"; - LOGGER.error(message); - return message; - } - - private static CloseableHttpClient createHttpClientThatAcceptsAllServerCerts() - throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException { - final SSLContextBuilder builder = new SSLContextBuilder(); - builder.loadTrustMaterial(null, (chain, authType) -> true); - final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build()); - return HttpClients.custom().setSSLSocketFactory(sslsf).build(); - } - } - - /** - * Callback interface which is called when the simulated update process has - * been finished and the caller of starting the simulated update process can - * send the result back to the hawkBit update server. - */ - @FunctionalInterface - public interface UpdaterCallback { - /** - * Callback method to indicate that the simulated update process has - * been finished. - * - * @param device - * the device which has been updated - * @param actionId - * the ID of the action from the hawkbit update server - */ - void updateFinished(AbstractSimulatedDevice device, final Long actionId); - } - -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/NextPollTimeController.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/NextPollTimeController.java deleted file mode 100644 index 96b4a1e97..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/NextPollTimeController.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator; - -import java.util.Collection; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import org.eclipse.hawkbit.simulator.event.NextPollCounterUpdate; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.google.common.eventbus.EventBus; - -/** - * Poll time trigger which executes the {@link DDISimulatedDevice#poll()} every - * second. - */ -@Component -public class NextPollTimeController { - - private static final Logger LOGGER = LoggerFactory.getLogger(NextPollTimeController.class); - - private static final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); - private static final ExecutorService pollService = Executors.newFixedThreadPool(1); - - @Autowired - private DeviceSimulatorRepository repository; - - @Autowired - private EventBus eventBus; - - /** - * Constructor which schedules the poll trigger runnable every second. - */ - public NextPollTimeController() { - executorService.scheduleWithFixedDelay(new NextPollUpdaterRunnable(), 1, 1, TimeUnit.SECONDS); - } - - private class NextPollUpdaterRunnable implements Runnable { - @Override - public void run() { - final Collection devices = repository.getAll(); - - devices.forEach(device -> { - int nextCounter = device.getNextPollCounterSec() - 1; - if (nextCounter < 0) { - try { - pollService.submit(() -> device.poll()); - } catch (final IllegalStateException e) { - LOGGER.trace("Device could not be polled", e); - } - nextCounter = device.getPollDelaySec(); - } - - device.setNextPollCounterSec(nextCounter); - }); - eventBus.post(new NextPollCounterUpdate(devices)); - } - } -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulatedDeviceFactory.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulatedDeviceFactory.java deleted file mode 100644 index be9b5cd6b..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulatedDeviceFactory.java +++ /dev/null @@ -1,123 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator; - -import java.net.URL; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol; -import org.eclipse.hawkbit.simulator.amqp.SpSenderService; -import org.eclipse.hawkbit.simulator.http.ControllerResource; -import org.eclipse.hawkbit.simulator.http.GatewayTokenInterceptor; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import feign.Feign; -import feign.Logger; - -/** - * The simulated device factory to create either {@link DMFSimulatedDevice} or - * {@link DDISimulatedDevice}. - */ -@Service -public class SimulatedDeviceFactory { - @Autowired - private DeviceSimulatorUpdater deviceUpdater; - - @Autowired - private SpSenderService spSenderService; - - @Autowired - private ScheduledExecutorService threadPool; - - /** - * Creating a simulated device. - * - * @param id - * the ID of the simulated device - * @param tenant - * the tenant of the simulated device - * @param protocol - * the protocol which should be used be the simulated device - * @param pollDelaySec - * the poll delay time in seconds which should be used for - * {@link DDISimulatedDevice}s and {@link DMFSimulatedDevice} - * @param baseEndpoint - * the http base endpoint which should be used for - * {@link DDISimulatedDevice}s - * @param gatewayToken - * the gatewayToken to be used to authenticate - * {@link DDISimulatedDevice}s at the endpoint - * @return the created simulated device - */ - public AbstractSimulatedDevice createSimulatedDevice(final String id, final String tenant, final Protocol protocol, - final int pollDelaySec, final URL baseEndpoint, final String gatewayToken) { - return createSimulatedDevice(id, tenant, protocol, pollDelaySec, baseEndpoint, gatewayToken, false); - } - - private AbstractSimulatedDevice createSimulatedDevice(final String id, final String tenant, final Protocol protocol, - final int pollDelaySec, final URL baseEndpoint, final String gatewayToken, final boolean pollImmediatly) { - switch (protocol) { - case DMF_AMQP: - return createDmfDevice(id, tenant, pollDelaySec, pollImmediatly); - case DDI_HTTP: - return createDdiDevice(id, tenant, pollDelaySec, baseEndpoint, gatewayToken); - default: - throw new IllegalArgumentException("Protocol " + protocol + " unknown"); - } - } - - private AbstractSimulatedDevice createDdiDevice(final String id, final String tenant, final int pollDelaySec, - final URL baseEndpoint, final String gatewayToken) { - final ControllerResource controllerResource = Feign.builder().logger(new Logger.ErrorLogger()) - .requestInterceptor(new GatewayTokenInterceptor(gatewayToken)).logLevel(Logger.Level.BASIC) - .target(ControllerResource.class, baseEndpoint.toString()); - return new DDISimulatedDevice(id, tenant, pollDelaySec, controllerResource, deviceUpdater); - } - - private AbstractSimulatedDevice createDmfDevice(final String id, final String tenant, final int pollDelaySec, - final boolean pollImmediatly) { - final AbstractSimulatedDevice device = new DMFSimulatedDevice(id, tenant, spSenderService, pollDelaySec); - device.setNextPollCounterSec(pollDelaySec); - if (pollImmediatly) { - spSenderService.createOrUpdateThing(tenant, id); - } - - threadPool.schedule(() -> spSenderService.updateAttributesOfThing(tenant, id), 2_000, TimeUnit.MILLISECONDS); - - return device; - } - - /** - * Creating a simulated device and send an immediate DMF poll to update - * server. - * - * @param id - * the ID of the simulated device - * @param tenant - * the tenant of the simulated device - * @param protocol - * the protocol which should be used be the simulated device - * @param pollDelaySec - * the poll delay time in seconds which should be used for - * {@link DDISimulatedDevice}s and {@link DMFSimulatedDevice} - * @param baseEndpoint - * the http base endpoint which should be used for - * {@link DDISimulatedDevice}s - * @param gatewayToken - * the gatewayToken to be used to authenticate - * {@link DDISimulatedDevice}s at the endpoint - * @return the created simulated device - */ - public AbstractSimulatedDevice createSimulatedDeviceWithImmediatePoll(final String id, final String tenant, - final Protocol protocol, final int pollDelaySec, final URL baseEndpoint, final String gatewayToken) { - return createSimulatedDevice(id, tenant, protocol, pollDelaySec, baseEndpoint, gatewayToken, true); - } -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationController.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationController.java deleted file mode 100644 index 4a809bb06..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationController.java +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator; - -import java.net.MalformedURLException; -import java.net.URL; - -import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol; -import org.eclipse.hawkbit.simulator.amqp.AmqpProperties; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -/** - * REST endpoint for controlling the device simulator. - */ -@RestController -public class SimulationController { - - @Autowired - private DeviceSimulatorRepository repository; - - @Autowired - private SimulatedDeviceFactory deviceFactory; - - @Autowired - private AmqpProperties amqpProperties; - - /** - * The start resource to start a device creation. - * - * @param name - * the name prefix of the generated device naming - * @param amount - * the amount of devices to be created - * @param tenant - * the tenant to create the device to - * @param api - * the api-protocol to be used either {@code dmf} or {@code ddi} - * @param endpoint - * the URL endpoint to be used of the hawkbit-update-server for - * DDI devices - * @param pollDelay - * number of delay in milliseconds to delay polling of DDI - * devices - * @param gatewayToken - * the hawkbit-update-server gatewaytoken in case authentication - * is enforced in hawkbit - * @return a response string that devices has been created - * @throws MalformedURLException - */ - @RequestMapping("/start") - ResponseEntity start(@RequestParam(value = "name", defaultValue = "simulated") final String name, - @RequestParam(value = "amount", defaultValue = "20") final int amount, - @RequestParam(value = "tenant", defaultValue = "DEFAULT") final String tenant, - @RequestParam(value = "api", defaultValue = "dmf") final String api, - @RequestParam(value = "endpoint", defaultValue = "http://localhost:8080") final String endpoint, - @RequestParam(value = "polldelay", defaultValue = "1800") final int pollDelay, - @RequestParam(value = "gatewaytoken", defaultValue = "") final String gatewayToken) - throws MalformedURLException { - - final Protocol protocol; - switch (api.toLowerCase()) { - case "dmf": - protocol = Protocol.DMF_AMQP; - break; - case "ddi": - protocol = Protocol.DDI_HTTP; - break; - default: - return ResponseEntity.badRequest().body("query param api only allows value of 'dmf' or 'ddi'"); - } - - if (protocol == Protocol.DMF_AMQP && isDmfDisabled()) { - return ResponseEntity.badRequest() - .body("The AMQP interface has been disabled, to use DMF protocol you need to enable the AMQP interface via '" - + AmqpProperties.CONFIGURATION_PREFIX + ".enabled=true'"); - } - - for (int i = 0; i < amount; i++) { - final String deviceId = name + i; - repository.add(deviceFactory.createSimulatedDeviceWithImmediatePoll(deviceId, tenant, protocol, pollDelay, - new URL(endpoint), gatewayToken)); - } - - return ResponseEntity.ok("Updated " + amount + " " + protocol + " connected targets!"); - } - - private boolean isDmfDisabled() { - return !amqpProperties.isEnabled(); - } -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationProperties.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationProperties.java deleted file mode 100644 index f0ef62375..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationProperties.java +++ /dev/null @@ -1,190 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.Random; -import java.util.concurrent.TimeUnit; - -import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol; -import org.hibernate.validator.constraints.NotEmpty; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; - -import com.google.common.base.Splitter; - -/** - * General simulator service properties. - * - */ -@Component -@ConfigurationProperties("hawkbit.device.simulator") -// Exception for squid:S2245 : not security relevant random number generation -@SuppressWarnings("squid:S2245") -public class SimulationProperties { - private static final Splitter SPLITTER = Splitter.on(',').omitEmptyStrings().trimResults(); - private static final Random RANDOM = new Random(); - - /** - * List of tenants where the simulator should auto start simulations after - * startup. - */ - private final List autostarts = new ArrayList<>(); - - private final List attributes = new ArrayList<>(); - - public List getAttributes() { - return attributes; - } - - public List getAutostarts() { - return this.autostarts; - } - - /** - * Properties for target attributes set as part of simulation. - * - */ - public static class Attribute { - private String key; - private String value; - private String random; - - public String getKey() { - return key; - } - - public String getValue() { - return Optional.ofNullable(value).orElseGet(this::getRandomElement); - } - - public void setKey(final String key) { - this.key = key; - } - - public void setValue(final String value) { - this.value = value; - } - - public void setRandom(final String random) { - this.random = random; - } - - public String getRandom() { - return random; - } - - private String getRandomElement() { - final List options = SPLITTER.splitToList(random); - return options.get(RANDOM.nextInt(options.size())); - } - } - - /** - * Auto start configuration for simulation setups that the simulator begins - * after startup. - * - */ - public static class Autostart { - /** - * Name prefix of simulated devices, followed by counter, e.g. - * simulated0, simulated1, simulated2.... - */ - private String name = "simulated"; - - /** - * Amount of simulated devices. - */ - private int amount = 20; - - /** - * Tenant name for the simulation. - */ - @NotEmpty - private String tenant; - - /** - * API for simulation. - */ - private Protocol api = Protocol.DMF_AMQP; - - /** - * Endpoint in case of DDI API based simulation. - */ - private String endpoint = "http://localhost:8080"; - - /** - * Poll time in {@link TimeUnit#SECONDS} for simulated devices. - */ - private int pollDelay = (int) TimeUnit.MINUTES.toSeconds(30); - - /** - * Optional gateway token for DDI API based simulation. - */ - private String gatewayToken = ""; - - public String getName() { - return name; - } - - public void setName(final String name) { - this.name = name; - } - - public int getAmount() { - return amount; - } - - public void setAmount(final int amount) { - this.amount = amount; - } - - public String getTenant() { - return tenant; - } - - public void setTenant(final String tenant) { - this.tenant = tenant; - } - - public Protocol getApi() { - return api; - } - - public void setApi(final Protocol api) { - this.api = api; - } - - public String getEndpoint() { - return endpoint; - } - - public void setEndpoint(final String endpoint) { - this.endpoint = endpoint; - } - - public int getPollDelay() { - return pollDelay; - } - - public void setPollDelay(final int pollDelay) { - this.pollDelay = pollDelay; - } - - public String getGatewayToken() { - return gatewayToken; - } - - public void setGatewayToken(final String gatewayToken) { - this.gatewayToken = gatewayToken; - } - } -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulatorStartup.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulatorStartup.java deleted file mode 100644 index 71aeade1c..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulatorStartup.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator; - -import java.net.MalformedURLException; -import java.net.URL; - -import org.eclipse.hawkbit.simulator.amqp.AmqpProperties; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.context.ApplicationListener; -import org.springframework.stereotype.Component; - -/** - * Execution of operations after startup. Set up of simulations. - * - */ -@Component -@ConditionalOnProperty(prefix = "hawkbit.device.simulator", name = "autostart", matchIfMissing = true) -public class SimulatorStartup implements ApplicationListener { - private static final Logger LOGGER = LoggerFactory.getLogger(SimulatorStartup.class); - - @Autowired - private SimulationProperties simulationProperties; - - @Autowired - private DeviceSimulatorRepository repository; - - @Autowired - private SimulatedDeviceFactory deviceFactory; - - @Autowired - private AmqpProperties amqpProperties; - - @Override - public void onApplicationEvent(final ApplicationReadyEvent event) { - simulationProperties.getAutostarts().forEach(autostart -> { - for (int i = 0; i < autostart.getAmount(); i++) { - final String deviceId = autostart.getName() + i; - try { - if (amqpProperties.isEnabled()) { - repository.add(deviceFactory.createSimulatedDeviceWithImmediatePoll(deviceId, - autostart.getTenant(), autostart.getApi(), autostart.getPollDelay(), - new URL(autostart.getEndpoint()), autostart.getGatewayToken())); - } - - } catch (final MalformedURLException e) { - LOGGER.error("Creation of simulated device at startup failed.", e); - } - } - }); - } - -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/UpdateStatus.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/UpdateStatus.java deleted file mode 100644 index f4e1f75a7..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/UpdateStatus.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator; - -import java.util.ArrayList; -import java.util.List; - -/** - * Update status of the simulated update. - * - */ -public class UpdateStatus { - private ResponseStatus responseStatus; - private List statusMessages; - - /** - * Constructor. - * - * @param responseStatus - * of the update - */ - public UpdateStatus(final ResponseStatus responseStatus) { - this.responseStatus = responseStatus; - } - - /** - * Constructor including status message. - * - * @param responseStatus - * of the update - * @param message - * of the update status - */ - public UpdateStatus(final ResponseStatus responseStatus, final String message) { - this(responseStatus); - statusMessages = new ArrayList<>(); - statusMessages.add(message); - } - - public ResponseStatus getResponseStatus() { - return responseStatus; - } - - public void setResponseStatus(final ResponseStatus responseStatus) { - this.responseStatus = responseStatus; - } - - public List getStatusMessages() { - if (statusMessages == null) { - statusMessages = new ArrayList<>(); - } - - return statusMessages; - } - - /** - * The status to response to the hawkBit update server if an simulated - * update process should be respond with successful or failure update. - */ - public enum ResponseStatus { - /** - * Update has been successful and response the successful update. - */ - SUCCESSFUL, - - /** - * Update has been not successful and response the error update. - */ - ERROR; - } - -} \ No newline at end of file diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpConfiguration.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpConfiguration.java deleted file mode 100644 index 6dc47059c..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpConfiguration.java +++ /dev/null @@ -1,177 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator.amqp; - -import java.time.Duration; -import java.util.Map; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.amqp.core.Binding; -import org.springframework.amqp.core.BindingBuilder; -import org.springframework.amqp.core.FanoutExchange; -import org.springframework.amqp.core.Queue; -import org.springframework.amqp.core.QueueBuilder; -import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory; -import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; -import org.springframework.amqp.rabbit.connection.ConnectionFactory; -import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; -import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.amqp.RabbitProperties; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.retry.backoff.ExponentialBackOffPolicy; -import org.springframework.retry.support.RetryTemplate; - -import com.google.common.collect.Maps; - -/** - * The spring AMQP configuration to use a AMQP for communication with SP update - * server. - */ -@Configuration -@EnableConfigurationProperties(AmqpProperties.class) -@ConditionalOnProperty(prefix = AmqpProperties.CONFIGURATION_PREFIX, name = "enabled") -public class AmqpConfiguration { - - private static final Logger LOGGER = LoggerFactory.getLogger(AmqpConfiguration.class); - - @Autowired - protected AmqpProperties amqpProperties; - - @Autowired - private ConnectionFactory connectionFactory; - - /** - * @return {@link RabbitTemplate} with automatic retry, published confirms - * and {@link Jackson2JsonMessageConverter}. - */ - @Bean - public RabbitTemplate rabbitTemplate() { - final RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory); - rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter()); - - final RetryTemplate retryTemplate = new RetryTemplate(); - retryTemplate.setBackOffPolicy(new ExponentialBackOffPolicy()); - rabbitTemplate.setRetryTemplate(retryTemplate); - - rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> { - if (ack) { - LOGGER.debug("Message with correlation ID {} confirmed by broker.", correlationData.getId()); - } else { - LOGGER.error("Broker is unable to handle message with correlation ID {} : {}", correlationData.getId(), - cause); - } - - }); - - return rabbitTemplate; - } - - @Configuration - protected static class RabbitConnectionFactoryCreator { - - /** - * {@link ConnectionFactory} with enabled publisher confirms and - * heartbeat. - * - * @param config - * with standard {@link RabbitProperties} - * @return {@link ConnectionFactory} - */ - @Bean - public ConnectionFactory rabbitConnectionFactory(final RabbitProperties config) { - final CachingConnectionFactory factory = new CachingConnectionFactory(); - factory.setRequestedHeartBeat(60); - factory.setPublisherConfirms(true); - - final String addresses = config.getAddresses(); - factory.setAddresses(addresses); - if (config.getHost() != null) { - factory.setHost(config.getHost()); - factory.setPort(config.getPort()); - } - if (config.getUsername() != null) { - factory.setUsername(config.getUsername()); - } - if (config.getPassword() != null) { - factory.setPassword(config.getPassword()); - } - if (config.getVirtualHost() != null) { - factory.setVirtualHost(config.getVirtualHost()); - } - return factory; - } - } - - /** - * Creates the receiver queue from update server for receiving message from - * update server. - * - * @return the queue - */ - @Bean - public Queue receiverConnectorQueueFromHawkBit() { - final Map arguments = getTTLMaxArgs(); - - return QueueBuilder.nonDurable(amqpProperties.getReceiverConnectorQueueFromSp()).autoDelete() - .withArguments(arguments).build(); - } - - /** - * Creates the receiver exchange for sending messages to update server. - * - * @return the exchange - */ - @Bean - public FanoutExchange exchangeQueueToConnector() { - return new FanoutExchange(amqpProperties.getSenderForSpExchange(), false, true); - } - - /** - * Create the Binding - * {@link AmqpConfiguration#receiverConnectorQueueFromHawkBit()} to - * {@link AmqpConfiguration#exchangeQueueToConnector()}. - * - * @return the binding and create the queue and exchange - */ - @Bean - public Binding bindReceiverQueueToSpExchange() { - return BindingBuilder.bind(receiverConnectorQueueFromHawkBit()).to(exchangeQueueToConnector()); - } - - /** - * Returns the Listener factory. - * - * @return the {@link SimpleMessageListenerContainer} that gets used receive - * AMQP messages - */ - @Bean(name = { "listenerContainerFactory" }) - public SimpleRabbitListenerContainerFactory listenerContainerFactory() { - final SimpleRabbitListenerContainerFactory containerFactory = new SimpleRabbitListenerContainerFactory(); - containerFactory.setDefaultRequeueRejected(true); - containerFactory.setConnectionFactory(connectionFactory); - containerFactory.setConcurrentConsumers(3); - containerFactory.setMaxConcurrentConsumers(10); - containerFactory.setPrefetchCount(20); - return containerFactory; - } - - private static Map getTTLMaxArgs() { - final Map args = Maps.newHashMapWithExpectedSize(2); - args.put("x-message-ttl", Duration.ofDays(1).toMillis()); - args.put("x-max-length", 100_000); - return args; - } - -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpProperties.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpProperties.java deleted file mode 100644 index 9bafd4ff0..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpProperties.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator.amqp; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; - -/** - * Bean which holds the necessary properties for configuring the AMQP - * connection. - * - */ -@Component -@ConfigurationProperties("hawkbit.device.simulator.amqp") -public class AmqpProperties { - - /** - * The prefix for this configuration. - */ - public static final String CONFIGURATION_PREFIX = "hawkbit.device.simulator.amqp"; - - /** - * Indicates if the AMQP interface is enabled for the device simulator. - */ - private boolean enabled; - - /** - * Set to true for the simulator run DMF health check. - */ - private boolean checkDmfHealth = false; - - /** - * Queue for receiving DMF messages from update server. - */ - private String receiverConnectorQueueFromSp = "simulator_receiver"; - - /** - * Exchange for sending DMF messages to update server. - */ - private String senderForSpExchange = "simulator.replyTo"; - - /** - * Message time to live (ttl) for the deadletter queue. Default ttl is 1 - * hour. - */ - private int deadLetterTtl = 60_000; - - public boolean isCheckDmfHealth() { - return checkDmfHealth; - } - - public void setCheckDmfHealth(final boolean checkDmfHealth) { - this.checkDmfHealth = checkDmfHealth; - } - - public String getReceiverConnectorQueueFromSp() { - return receiverConnectorQueueFromSp; - } - - public void setReceiverConnectorQueueFromSp(final String receiverConnectorQueueFromSp) { - this.receiverConnectorQueueFromSp = receiverConnectorQueueFromSp; - } - - public String getSenderForSpExchange() { - return senderForSpExchange; - } - - public void setSenderForSpExchange(final String senderForSpExchange) { - this.senderForSpExchange = senderForSpExchange; - } - - public int getDeadLetterTtl() { - return deadLetterTtl; - } - - public void setDeadLetterTtl(final int deadLetterTtl) { - this.deadLetterTtl = deadLetterTtl; - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(final boolean enabled) { - this.enabled = enabled; - } -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/MessageHandlerCacheConstant.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/MessageHandlerCacheConstant.java deleted file mode 100644 index fd287b3a3..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/MessageHandlerCacheConstant.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator.amqp; - -/** - * The constants for the caching. - * - * - * - */ -public final class MessageHandlerCacheConstant { - - /** - * The name of the cache. - */ - public static final String CACHE_NAME = "hawkbit.device.simulator.states"; - - private MessageHandlerCacheConstant() { - - } -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/MessageService.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/MessageService.java deleted file mode 100644 index 8bb1e1292..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/MessageService.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator.amqp; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.amqp.core.Message; -import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.amqp.support.converter.AbstractJavaTypeMapper; -import org.springframework.beans.factory.annotation.Autowired; - -/** - * Abstract class for sender and receiver service. - * - * - * - */ -public class MessageService { - - private static final Logger LOGGER = LoggerFactory.getLogger(MessageService.class); - - protected RabbitTemplate rabbitTemplate; - - protected AmqpProperties amqpProperties; - - /** - * Constructor. - * - * @param rabbitTemplate - * the rabbit template - * @param amqpProperties - * the amqp properties - * @param messageConverter - * the message converter - */ - @Autowired - public MessageService(final RabbitTemplate rabbitTemplate, final AmqpProperties amqpProperties) { - this.rabbitTemplate = rabbitTemplate; - this.amqpProperties = amqpProperties; - } - - public void setAmqpProperties(final AmqpProperties amqpProperties) { - this.amqpProperties = amqpProperties; - } - - public void setRabbitTemplate(final RabbitTemplate rabbitTemplate) { - this.rabbitTemplate = rabbitTemplate; - } - - /** - * Method to call when error emerges. - * - * @param message - * the message that triggered the error - * @param error - * the error - */ - public void logAndThrowMessageError(final Message message, final String error) { - LOGGER.error("Error \"{}\" reported by message {}", error, message.getMessageProperties().getMessageId()); - throw new IllegalArgumentException(error); - } - - /** - * Convert a message body to a given class and set the message header - * AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME for Jackson converter. - * - * @param message - * which body will converted - * @param clazz - * the body class - * @return the converted body - */ - @SuppressWarnings("unchecked") - public T convertMessage(final Message message, final Class clazz) { - message.getMessageProperties().getHeaders().put(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME, - clazz.getTypeName()); - return (T) rabbitTemplate.getMessageConverter().fromMessage(message); - } -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/ReceiverService.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/ReceiverService.java deleted file mode 100644 index 2e8833bab..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/ReceiverService.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator.amqp; - -import org.springframework.amqp.AmqpRejectAndDontRequeueException; -import org.springframework.amqp.core.Message; -import org.springframework.amqp.core.MessageProperties; -import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.beans.factory.annotation.Autowired; - -/** - * Abstract class for all receiver objects. - * - * - * - */ -public abstract class ReceiverService extends MessageService { - - /** - * Constructor. - * - * @param rabbitTemplate - * RabbitTemplate - * @param amqpProperties - * AmqpProperties - * @param messageConverter - * MessageConverter - */ - @Autowired - public ReceiverService(final RabbitTemplate rabbitTemplate, final AmqpProperties amqpProperties) { - super(rabbitTemplate, amqpProperties); - } - - /** - * Method to validate if content type is set in the message properties. - * - * @param message - * the message to get validated - */ - protected void checkContentTypeJson(final Message message) { - if (message.getBody().length == 0) { - return; - } - final MessageProperties messageProperties = message.getMessageProperties(); - final String headerContentType = (String) messageProperties.getHeaders().get("content-type"); - if (null != headerContentType) { - messageProperties.setContentType(headerContentType); - } - final String contentType = messageProperties.getContentType(); - if (contentType != null && contentType.contains("json")) { - return; - } - throw new AmqpRejectAndDontRequeueException("Content-Type is not JSON compatible"); - } - -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SenderService.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SenderService.java deleted file mode 100644 index 3fd86c4a0..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SenderService.java +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator.amqp; - -import java.nio.charset.StandardCharsets; -import java.util.UUID; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.amqp.core.Message; -import org.springframework.amqp.core.MessageProperties; -import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.amqp.rabbit.support.CorrelationData; -import org.springframework.amqp.support.converter.AbstractJavaTypeMapper; -import org.springframework.beans.factory.annotation.Autowired; - -/** - * Abstract calls for sender service objects. - * - * - * - */ -public abstract class SenderService extends MessageService { - - private static final Logger LOGGER = LoggerFactory.getLogger(SenderService.class); - - /** - * Constructor for sender service. - * - * @param rabbitTemplate - * the rabbit template - * @param amqpProperties - * the amqp properties - * @param cacheManager - * the cache manager - */ - @Autowired - public SenderService(final RabbitTemplate rabbitTemplate, final AmqpProperties amqpProperties) { - super(rabbitTemplate, amqpProperties); - } - - /** - * Send a message if the message is not null. - * - * @param address - * the exchange name - * @param message - * the amqp message which will be send if its not null - */ - public void sendMessage(final String address, final Message message) { - if (message == null) { - return; - } - message.getMessageProperties().getHeaders().remove(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME); - - final String correlationId = UUID.randomUUID().toString(); - - if (isCorrelationIdEmpty(message)) { - message.getMessageProperties().setCorrelationId(correlationId.getBytes(StandardCharsets.UTF_8)); - } - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Sending message {} to exchange {} with correlationId {}", message, address, correlationId); - } else { - LOGGER.debug("Sending message to exchange {} with correlationId {}", address, correlationId); - } - - rabbitTemplate.send(address, null, message, new CorrelationData(correlationId)); - } - - private static boolean isCorrelationIdEmpty(final Message message) { - return message.getMessageProperties().getCorrelationId() == null - || message.getMessageProperties().getCorrelationId().length <= 0; - } - - /** - * Convert object and message properties to message. - * - * @param object - * to get converted - * @param messageProperties - * to get converted - * @return converted message - */ - public Message convertMessage(final Object object, final MessageProperties messageProperties) { - return rabbitTemplate.getMessageConverter().toMessage(object, messageProperties); - } - -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SimulatedUpdate.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SimulatedUpdate.java deleted file mode 100644 index bd8316901..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SimulatedUpdate.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator.amqp; - -import java.io.Serializable; -import java.time.LocalDateTime; - -/** - * Object for holding attributes for a simulated update for the device - * simulator. - */ -public class SimulatedUpdate implements Serializable { - - private static final long serialVersionUID = 1L; - - protected final String tenant; - protected final String thingId; - - protected final Long actionId; - - protected transient LocalDateTime startCacheTime; - - /** - * Constructor of the class. - * - * @param tenant - * the tenant name. - * @param thingId - * the thing id. - * @param actionId - * the action id - * @param softwareModuleId - * software modul id - * @param urls - * the artifact download urls. - */ - public SimulatedUpdate(final String tenant, final String thingId, final Long actionId) { - this.tenant = tenant; - this.thingId = thingId; - this.actionId = actionId; - this.startCacheTime = LocalDateTime.now(); - } - - public String getTenant() { - return tenant; - } - - public String getThingId() { - return thingId; - } - - public Long getActionId() { - return actionId; - } - - public LocalDateTime getStartCacheTime() { - return startCacheTime; - } -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SpReceiverService.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SpReceiverService.java deleted file mode 100644 index ad432d023..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SpReceiverService.java +++ /dev/null @@ -1,205 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator.amqp; - -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -import org.eclipse.hawkbit.dmf.amqp.api.EventTopic; -import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey; -import org.eclipse.hawkbit.dmf.amqp.api.MessageType; -import org.eclipse.hawkbit.dmf.json.model.DmfDownloadAndUpdateRequest; -import org.eclipse.hawkbit.simulator.DeviceSimulatorRepository; -import org.eclipse.hawkbit.simulator.DeviceSimulatorUpdater; -import org.eclipse.jetty.util.ConcurrentHashSet; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.amqp.core.Message; -import org.springframework.amqp.core.MessageProperties; -import org.springframework.amqp.rabbit.annotation.RabbitListener; -import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.messaging.handler.annotation.Header; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Component; - -/** - * Handle all incoming Messages from hawkBit update server. - * - */ -@Component -@ConditionalOnProperty(prefix = AmqpProperties.CONFIGURATION_PREFIX, name = "enabled") -public class SpReceiverService extends ReceiverService { - private static final Logger LOGGER = LoggerFactory.getLogger(ReceiverService.class); - - private final SpSenderService spSenderService; - - private final DeviceSimulatorUpdater deviceUpdater; - - private final DeviceSimulatorRepository repository; - - private final Set openPings = new ConcurrentHashSet<>(); - - /** - * Constructor. - * - * @param rabbitTemplate - * for sending messages - * @param amqpProperties - * for amqp configuration - * @param spSenderService - * to send messages - * @param deviceUpdater - * simulator service for updates - * @param repository - * to manage simulated devices - */ - @Autowired - public SpReceiverService(final RabbitTemplate rabbitTemplate, final AmqpProperties amqpProperties, - final SpSenderService spSenderService, final DeviceSimulatorUpdater deviceUpdater, - final DeviceSimulatorRepository repository) { - super(rabbitTemplate, amqpProperties); - this.spSenderService = spSenderService; - this.deviceUpdater = deviceUpdater; - this.repository = repository; - } - - /** - * Handle the incoming Message from Queue with the property - * (hawkbit.device.simulator.amqp.receiverConnectorQueueFromSp). - * - * @param message - * the incoming message - * @param type - * the action type - * @param thingId - * the thing id in message header - * @param tenant - * the device belongs to - */ - @RabbitListener(queues = "${hawkbit.device.simulator.amqp.receiverConnectorQueueFromSp}", containerFactory = "listenerContainerFactory") - public void recieveMessageSp(final Message message, @Header(MessageHeaderKey.TYPE) final String type, - @Header(name = MessageHeaderKey.THING_ID, required = false) final String thingId, - @Header(MessageHeaderKey.TENANT) final String tenant) { - final MessageType messageType = MessageType.valueOf(type); - - if (MessageType.EVENT.equals(messageType)) { - checkContentTypeJson(message); - handleEventMessage(message, thingId); - return; - } - - if (MessageType.THING_DELETED.equals(messageType)) { - checkContentTypeJson(message); - repository.remove(tenant, thingId); - return; - } - - if (MessageType.PING_RESPONSE.equals(messageType)) { - final String correlationId = new String(message.getMessageProperties().getCorrelationId(), - StandardCharsets.UTF_8); - if (!openPings.remove(correlationId)) { - LOGGER.error("Unknown PING_RESPONSE received for correlationId: {}.", correlationId); - } - - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Got ping response from tenant {} with correlationId {} with timestamp {}", tenant, - correlationId, new String(message.getBody(), StandardCharsets.UTF_8)); - } - - return; - } - - LOGGER.info("No valid message type property."); - } - - @Scheduled(fixedDelay = 5_000, initialDelay = 5_000) - void checkDmfHealth() { - if (!amqpProperties.isCheckDmfHealth()) { - return; - } - - if (openPings.size() > 5) { - LOGGER.error("Currently {} open pings! DMF does not seem to be reachable.", openPings.size()); - } else { - LOGGER.debug("Currently {} open pings", openPings.size()); - } - - repository.getTenants().forEach(tenant -> { - final String correlationId = UUID.randomUUID().toString(); - spSenderService.ping(tenant, correlationId); - openPings.add(correlationId); - LOGGER.debug("Ping tenant {} with correlationId {}", tenant, correlationId); - }); - } - - private void handleEventMessage(final Message message, final String thingId) { - final Object eventHeader = message.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC); - if (eventHeader == null) { - logAndThrowMessageError(message, "Event Topic is not set"); - } - // Exception squid:S2259 - Checked before - @SuppressWarnings({ "squid:S2259" }) - final EventTopic eventTopic = EventTopic.valueOf(eventHeader.toString()); - switch (eventTopic) { - case DOWNLOAD_AND_INSTALL: - handleUpdateProcess(message, thingId); - break; - case CANCEL_DOWNLOAD: - handleCancelDownloadAction(message, thingId); - break; - default: - LOGGER.info("No valid event property."); - break; - } - } - - private void handleCancelDownloadAction(final Message message, final String thingId) { - final MessageProperties messageProperties = message.getMessageProperties(); - final Map headers = messageProperties.getHeaders(); - final String tenant = (String) headers.get(MessageHeaderKey.TENANT); - final Long actionId = convertMessage(message, Long.class); - - final SimulatedUpdate update = new SimulatedUpdate(tenant, thingId, actionId); - spSenderService.finishUpdateProcess(update, Arrays.asList("Simulation canceled")); - } - - private void handleUpdateProcess(final Message message, final String thingId) { - final MessageProperties messageProperties = message.getMessageProperties(); - final Map headers = messageProperties.getHeaders(); - final String tenant = (String) headers.get(MessageHeaderKey.TENANT); - - final DmfDownloadAndUpdateRequest downloadAndUpdateRequest = convertMessage(message, - DmfDownloadAndUpdateRequest.class); - final Long actionId = downloadAndUpdateRequest.getActionId(); - final String targetSecurityToken = downloadAndUpdateRequest.getTargetSecurityToken(); - - deviceUpdater.startUpdate(tenant, thingId, actionId, null, downloadAndUpdateRequest.getSoftwareModules(), - targetSecurityToken, (device, actionId1) -> { - switch (device.getUpdateStatus().getResponseStatus()) { - case SUCCESSFUL: - spSenderService.finishUpdateProcess( - new SimulatedUpdate(device.getTenant(), device.getId(), actionId1), - device.getUpdateStatus().getStatusMessages()); - break; - case ERROR: - spSenderService.finishUpdateProcessWithError( - new SimulatedUpdate(device.getTenant(), device.getId(), actionId1), - device.getUpdateStatus().getStatusMessages()); - break; - default: - break; - } - }); - } -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SpSenderService.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SpSenderService.java deleted file mode 100644 index 41b2fcca1..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SpSenderService.java +++ /dev/null @@ -1,270 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator.amqp; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.eclipse.hawkbit.dmf.amqp.api.AmqpSettings; -import org.eclipse.hawkbit.dmf.amqp.api.EventTopic; -import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey; -import org.eclipse.hawkbit.dmf.amqp.api.MessageType; -import org.eclipse.hawkbit.dmf.json.model.DmfActionStatus; -import org.eclipse.hawkbit.dmf.json.model.DmfActionUpdateStatus; -import org.eclipse.hawkbit.dmf.json.model.DmfAttributeUpdate; -import org.eclipse.hawkbit.simulator.SimulationProperties; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.amqp.core.Message; -import org.springframework.amqp.core.MessageProperties; -import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -/** - * Sender service to send messages to update server. - */ -@Service -public class SpSenderService extends SenderService { - - private static final Logger LOGGER = LoggerFactory.getLogger(SpSenderService.class); - - private final String spExchange; - - private final SimulationProperties simulationProperties; - - /** - * - * @param rabbitTemplate - * the rabbit template - * @param amqpProperties - * the amqp properties - * @param simulationProperties - * for attributes update class - */ - @Autowired - public SpSenderService(final RabbitTemplate rabbitTemplate, final AmqpProperties amqpProperties, - final SimulationProperties simulationProperties) { - super(rabbitTemplate, amqpProperties); - spExchange = AmqpSettings.DMF_EXCHANGE; - this.simulationProperties = simulationProperties; - } - - public void ping(final String tenant, final String correlationId) { - final MessageProperties messageProperties = new MessageProperties(); - messageProperties.getHeaders().put(MessageHeaderKey.TENANT, tenant); - messageProperties.getHeaders().put(MessageHeaderKey.TYPE, MessageType.PING.toString()); - messageProperties.setCorrelationId(correlationId.getBytes()); - messageProperties.setReplyTo(amqpProperties.getSenderForSpExchange()); - messageProperties.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN); - - sendMessage(spExchange, new Message(null, messageProperties)); - } - - /** - * Finish the update process. This will send a action status to SP. - * - * @param update - * the simulated update object - * @param updateResultMessages - * a description according the update process - */ - public void finishUpdateProcess(final SimulatedUpdate update, final List updateResultMessages) { - final Message updateResultMessage = createUpdateResultMessage(update, DmfActionStatus.FINISHED, - updateResultMessages); - sendMessage(spExchange, updateResultMessage); - } - - /** - * Finish update process with error and send error to SP. - * - * @param update - * the simulated update object - * @param updateResultMessages - * list of messages for error - */ - public void finishUpdateProcessWithError(final SimulatedUpdate update, final List updateResultMessages) { - sendErrorgMessage(update, updateResultMessages); - LOGGER.debug("Update process finished with error \"{}\" reported by thing {}", updateResultMessages, - update.getThingId()); - } - - /** - * Send an error message to SP. - * - * @param tenant - * the tenant - * @param updateResultMessages - * the error message description to send - * @param actionId - * the ID of the action for the error message - */ - public void sendErrorMessage(final String tenant, final List updateResultMessages, final Long actionId) { - final Message message = createActionStatusMessage(tenant, DmfActionStatus.ERROR, updateResultMessages, - actionId); - sendMessage(spExchange, message); - } - - /** - * Send a warning message to SP. - * - * @param update - * the simulated update object - * @param updateResultMessages - * a warning description - */ - public void sendWarningMessage(final SimulatedUpdate update, final List updateResultMessages) { - final Message message = createActionStatusMessage(update, updateResultMessages, DmfActionStatus.WARNING); - sendMessage(spExchange, message); - } - - /** - * Method to send a action status to SP. - * - * @param tenant - * the tenant - * @param actionStatus - * the action status - * @param updateResultMessages - * the message to get send - * @param actionId - * the cached value - */ - public void sendActionStatusMessage(final String tenant, final DmfActionStatus actionStatus, - final List updateResultMessages, final Long actionId) { - final Message message = createActionStatusMessage(tenant, actionStatus, updateResultMessages, actionId); - sendMessage(message); - - } - - /** - * Create new thing created message and send to udpate server. - * - * @param tenant - * the tenant to create the target - * @param targetId - * the ID of the target to create or update - */ - public void createOrUpdateThing(final String tenant, final String targetId) { - sendMessage(spExchange, thingCreatedMessage(tenant, targetId)); - - LOGGER.debug("Created thing created message and send to update server for Thing \"{}\"", targetId); - } - - /** - * Create new attribute update message and send to update server. - * - * @param tenant - * the tenant to create the target - * @param targetId - * the ID of the target to create or update - */ - public void updateAttributesOfThing(final String tenant, final String targetId) { - sendMessage(spExchange, attributeUpdateMessage(tenant, targetId)); - - LOGGER.debug("Create update attributes message and send to update server for Thing \"{}\"", targetId); - } - - private Message thingCreatedMessage(final String tenant, final String targetId) { - final MessageProperties messagePropertiesForSP = new MessageProperties(); - messagePropertiesForSP.setHeader(MessageHeaderKey.TYPE, MessageType.THING_CREATED.name()); - messagePropertiesForSP.setHeader(MessageHeaderKey.TENANT, tenant); - messagePropertiesForSP.setHeader(MessageHeaderKey.THING_ID, targetId); - messagePropertiesForSP.setHeader(MessageHeaderKey.SENDER, "simulator"); - messagePropertiesForSP.setContentType(MessageProperties.CONTENT_TYPE_JSON); - messagePropertiesForSP.setReplyTo(amqpProperties.getSenderForSpExchange()); - return new Message(null, messagePropertiesForSP); - } - - private Message attributeUpdateMessage(final String tenant, final String targetId) { - final MessageProperties messagePropertiesForSP = new MessageProperties(); - messagePropertiesForSP.setHeader(MessageHeaderKey.TYPE, MessageType.EVENT.name()); - messagePropertiesForSP.setHeader(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ATTRIBUTES); - messagePropertiesForSP.setHeader(MessageHeaderKey.TENANT, tenant); - messagePropertiesForSP.setHeader(MessageHeaderKey.THING_ID, targetId); - messagePropertiesForSP.setContentType(MessageProperties.CONTENT_TYPE_JSON); - messagePropertiesForSP.setReplyTo(amqpProperties.getSenderForSpExchange()); - final DmfAttributeUpdate attributeUpdate = new DmfAttributeUpdate(); - - attributeUpdate.getAttributes().putAll(simulationProperties.getAttributes().stream().collect( - Collectors.toMap(SimulationProperties.Attribute::getKey, SimulationProperties.Attribute::getValue))); - - return convertMessage(attributeUpdate, messagePropertiesForSP); - } - - /** - * Send a created message to SP. - * - * @param message - * the message to get send - */ - private void sendMessage(final Message message) { - sendMessage(spExchange, message); - } - - /** - * Send error message to SP. - * - * @param context - * the current context - * @param updateResultMessages - * a list of descriptions according the update process - */ - private void sendErrorgMessage(final SimulatedUpdate update, final List updateResultMessages) { - final Message message = createActionStatusMessage(update, updateResultMessages, DmfActionStatus.ERROR); - sendMessage(spExchange, message); - } - - /** - * Create a action status message. - * - * @param actionStatus - * the ActionStatus - * @param actionMessage - * the message description - * @param actionId - * the action id - * @param cacheValue - * the cacheValue value - */ - private Message createActionStatusMessage(final String tenant, final DmfActionStatus actionStatus, - final List updateResultMessages, final Long actionId) { - final MessageProperties messageProperties = new MessageProperties(); - final Map headers = messageProperties.getHeaders(); - final DmfActionUpdateStatus actionUpdateStatus = new DmfActionUpdateStatus(actionId, actionStatus); - headers.put(MessageHeaderKey.TYPE, MessageType.EVENT.name()); - headers.put(MessageHeaderKey.TENANT, tenant); - headers.put(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ACTION_STATUS.name()); - headers.put(MessageHeaderKey.CONTENT_TYPE, MessageProperties.CONTENT_TYPE_JSON); - actionUpdateStatus.addMessage(updateResultMessages); - - return convertMessage(actionUpdateStatus, messageProperties); - } - - private Message createUpdateResultMessage(final SimulatedUpdate cacheValue, final DmfActionStatus actionStatus, - final List updateResultMessages) { - final MessageProperties messageProperties = new MessageProperties(); - final Map headers = messageProperties.getHeaders(); - final DmfActionUpdateStatus actionUpdateStatus = new DmfActionUpdateStatus(cacheValue.getActionId(), - actionStatus); - headers.put(MessageHeaderKey.TYPE, MessageType.EVENT.name()); - headers.put(MessageHeaderKey.TENANT, cacheValue.getTenant()); - headers.put(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ACTION_STATUS.name()); - headers.put(MessageHeaderKey.CONTENT_TYPE, MessageProperties.CONTENT_TYPE_JSON); - actionUpdateStatus.addMessage(updateResultMessages); - return convertMessage(actionUpdateStatus, messageProperties); - } - - private Message createActionStatusMessage(final SimulatedUpdate update, final List updateResultMessages, - final DmfActionStatus status) { - return createActionStatusMessage(update.getTenant(), status, updateResultMessages, update.getActionId()); - } - -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/event/InitUpdate.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/event/InitUpdate.java deleted file mode 100644 index 16a967f89..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/event/InitUpdate.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator.event; - -import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice; - -/** - * Event description which indicates the initialization of an update. - */ -public class InitUpdate { - - private final AbstractSimulatedDevice device; - - /** - * Creates new progress update event. - * - * @param device - * the device which progress has been updated - */ - public InitUpdate(final AbstractSimulatedDevice device) { - this.device = device; - } - - /** - * @return the device of the event - */ - public AbstractSimulatedDevice getDevice() { - return device; - } - -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/event/NextPollCounterUpdate.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/event/NextPollCounterUpdate.java deleted file mode 100644 index 7ed5e2cfc..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/event/NextPollCounterUpdate.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator.event; - -import java.util.Collection; - -import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice; - -/** - * Event description which indicates a poll time update. - */ -public class NextPollCounterUpdate { - - private final Collection devices; - - /** - * Creates poll timer update event. - * - * @param devices - * the devices which progress has been updated - */ - public NextPollCounterUpdate(final Collection devices) { - this.devices = devices; - } - - /** - * @return the devices of the event - */ - public Collection getDevices() { - return devices; - } - -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/event/ProgressUpdate.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/event/ProgressUpdate.java deleted file mode 100644 index 6c18e61ac..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/event/ProgressUpdate.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator.event; - -import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice; - -/** - * Event definition object which is published if the simulated device updated - * its update progress. - * - */ -public class ProgressUpdate { - - private final AbstractSimulatedDevice device; - - /** - * Creates new progress update event. - * - * @param device - * the device which progress has been updated - */ - public ProgressUpdate(final AbstractSimulatedDevice device) { - this.device = device; - } - - /** - * @return the device of the event - */ - public AbstractSimulatedDevice getDevice() { - return device; - } - -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/http/ControllerResource.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/http/ControllerResource.java deleted file mode 100644 index 1dac4c80b..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/http/ControllerResource.java +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator.http; - -import org.eclipse.hawkbit.simulator.DDISimulatedDevice; - -import feign.Body; -import feign.Headers; -import feign.Param; -import feign.RequestLine; - -/** - * A feign based controller resource interface declaration for - * {@link DDISimulatedDevice}s using over HTTP. - * - * @author Michael Hirsch - * - */ -public interface ControllerResource { - - /** - * The base poll URL for the devices to retrieve if there is an update - * available. - * - * @param tenant - * the tenant of the device - * @param controllerId - * the ID of the device - * @return the plain json response of the http request - */ - @RequestLine("GET /{tenant}/controller/v1/{controllerId}") - @Headers({ "Content-Type: application/json" }) - String get(@Param("tenant") final String tenant, @Param("controllerId") final String controllerId); - - /** - * Retrieving the deployment job response from the hawkbit update server. - * - * @param tenant - * the tenant for the simulated device - * @param controllerId - * the ID of the device - * @param actionId - * the ID of the action to retrieve - * @return the json response of the http request - */ - @RequestLine("GET /{tenant}/controller/v1/{controllerId}/deploymentBase/{actionId}") - @Headers({ "Content-Type: application/json" }) - String getDeployment(@Param("tenant") final String tenant, @Param("controllerId") final String controllerId, - @Param("actionId") final long actionId); - - /** - * Post a success update feedback to the hawkbit update server - * - * @param tenant - * the tenant of the device - * @param controllerId - * the ID of the device - * @param actionId - * the ID of the action to post feedback back - */ - @RequestLine("POST /{tenant}/controller/v1/{controllerId}/deploymentBase/{actionId}/feedback") - @Headers("Content-Type: application/json") - @Body("%7B\"id\":{actionId},\"time\":\"20140511T121314\",\"status\":%7B\"execution\":\"closed\",\"result\":%7B\"finished\":\"success\",\"progress\":%7B%7D%7D%7D%7D") - void postSuccessFeedback(@Param("tenant") final String tenant, @Param("controllerId") final String controllerId, - @Param("actionId") final long actionId); - - /** - * Post a failure update feedback to the hawkbit update server - * - * @param tenant - * the tenant of the device - * @param controllerId - * the ID of the device - * @param actionId - * the ID of the action to post feedback back - */ - @RequestLine("POST /{tenant}/controller/v1/{controllerId}/deploymentBase/{actionId}/feedback") - @Headers("Content-Type: application/json") - @Body("%7B\"id\":{actionId},\"time\":\"20140511T121314\",\"status\":%7B\"execution\":\"closed\",\"result\":%7B\"finished\":\"failure\",\"progress\":%7B%7D%7D%7D%7D") - void postErrorFeedback(@Param("tenant") final String tenant, @Param("controllerId") final String controllerId, - @Param("actionId") final long actionId); -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/http/GatewayTokenInterceptor.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/http/GatewayTokenInterceptor.java deleted file mode 100644 index 3381481de..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/http/GatewayTokenInterceptor.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator.http; - -import feign.RequestInterceptor; -import feign.RequestTemplate; - -/** - * A feign interceptor to apply the gateway-token header to each http-request. - * - * @author Michael Hirsch - * - */ -public class GatewayTokenInterceptor implements RequestInterceptor { - - private final String gatewayToken; - - /** - * @param gatewayToken - * the gatwway token to be used in the http-header - */ - public GatewayTokenInterceptor(final String gatewayToken) { - this.gatewayToken = gatewayToken; - } - - @Override - public void apply(final RequestTemplate template) { - template.header("Authorization", "GatewayToken " + gatewayToken); - } -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/ui/GenerateDialog.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/ui/GenerateDialog.java deleted file mode 100644 index 192dbe6ca..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/ui/GenerateDialog.java +++ /dev/null @@ -1,217 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator.ui; - -import java.net.MalformedURLException; -import java.net.URL; - -import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.vaadin.data.Property; -import com.vaadin.data.Validator; -import com.vaadin.data.util.ObjectProperty; -import com.vaadin.data.validator.NullValidator; -import com.vaadin.data.validator.RangeValidator; -import com.vaadin.data.validator.RegexpValidator; -import com.vaadin.server.FontAwesome; -import com.vaadin.server.Resource; -import com.vaadin.ui.Button; -import com.vaadin.ui.FormLayout; -import com.vaadin.ui.OptionGroup; -import com.vaadin.ui.TextField; -import com.vaadin.ui.Window; - -/** - * Popup dialog window for setting the values of generating the simulated - * devices, e.g. the amount. - * - * - */ -// Vaadin Inheritance -@SuppressWarnings("squid:MaximumInheritanceDepth") -public class GenerateDialog extends Window { - - private static final long serialVersionUID = 1L; - private static final Logger LOGGER = LoggerFactory.getLogger(GenerateDialog.class); - - private final FormLayout formLayout = new FormLayout(); - - private final TextField namePrefixTextField; - private final TextField amountTextField; - private final TextField tenantTextField; - private final TextField pollDelayTextField; - private final TextField pollUrlTextField; - private final TextField gatewayTokenTextField; - private OptionGroup protocolGroup; - private Button buttonOk; - private final boolean dmfEnabled; - - /** - * Creates a new pop window for setting the configuration of simulating - * devices. - * - * @param callback - * the callback which is called when the dialog has been - * successfully confirmed. - * @param dmfEnabled - * indicates if the AMQP/DMF interface is enabled by - * configuration and if the option DMF should be enabled or not - */ - public GenerateDialog(final GenerateDialogCallback callback, final boolean dmfEnabled) { - this.dmfEnabled = dmfEnabled; - formLayout.setSpacing(true); - formLayout.setMargin(true); - - namePrefixTextField = createRequiredTextfield("name prefix", "dmfSimulated", FontAwesome.INFO, - new NullValidator("Must be given", false)); - - amountTextField = createRequiredTextfield("amount", new ObjectProperty(10), FontAwesome.GEAR, - new RangeValidator("Must be between 1 and 30000", Integer.class, 1, 30000)); - - tenantTextField = createRequiredTextfield("tenant", "default", FontAwesome.USER, - new NullValidator("Must be given", false)); - - pollDelayTextField = createRequiredTextfield("poll delay (sec)", new ObjectProperty(10), - FontAwesome.CLOCK_O, new RangeValidator("Must be between 1 and 60", Integer.class, 1, 60)); - - pollUrlTextField = createRequiredTextfield("base poll URL endpoint", "http://localhost:8080", - FontAwesome.FLAG_O, new RegexpValidator( - "^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]", "is not an URL")); - pollUrlTextField.setColumns(50); - pollUrlTextField.setVisible(false); - - gatewayTokenTextField = createRequiredTextfield("gateway token", "", FontAwesome.FLAG_O, null); - gatewayTokenTextField.setColumns(50); - gatewayTokenTextField.setVisible(false); - - createProtocolGroup(); - createOkButton(callback); - - namePrefixTextField.addValueChangeListener(event -> checkValid()); - amountTextField.addValueChangeListener(event -> checkValid()); - tenantTextField.addValueChangeListener(event -> checkValid()); - - formLayout.addComponent(namePrefixTextField); - formLayout.addComponent(amountTextField); - formLayout.addComponent(tenantTextField); - formLayout.addComponent(protocolGroup); - formLayout.addComponent(pollDelayTextField); - formLayout.addComponent(pollUrlTextField); - formLayout.addComponent(gatewayTokenTextField); - formLayout.addComponent(buttonOk); - - setCaption("Simulate Devices"); - setContent(formLayout); - setResizable(false); - center(); - } - - private void checkValid() { - buttonOk.setEnabled(namePrefixTextField.isValid() && amountTextField.isValid() && tenantTextField.isValid() - && pollDelayTextField.isValid()); - - } - - /** - * Callback interface to retrieve the result from the dialog window. - * - * @author Michael Hirsch - * - */ - @FunctionalInterface - interface GenerateDialogCallback { - /** - * Callback method which is called when dialog closes with the OK - * button. - * - * @param namePrefix - * the parameter for name prefix for the simulated devices - * @param tenant - * the tenant for the simulated devices - * @param amount - * the number of simulated devices to be created - * @param pollDelay - * the delay poll time in seconds for DDI devices - * @param basePollURL - * the base http URL endpoint for DDI devices - * @param gatewayToken - * the gateway token header for authentication for DDI - * devices - * @param protocol - * the protocol to be used for the simulated devices to be - * generated - */ - void okButton(final String namePrefix, final String tenant, final int amount, final int pollDelay, - final URL basePollURL, final String gatewayToken, final Protocol protocol); - } - - private void createProtocolGroup() { - - this.protocolGroup = new OptionGroup("Simulated Device Protocol"); - protocolGroup.addItem(Protocol.DMF_AMQP); - protocolGroup.addItem(Protocol.DDI_HTTP); - protocolGroup.select(Protocol.DMF_AMQP); - protocolGroup.setItemCaption(Protocol.DMF_AMQP, "Device Management Federation API (AMQP push)"); - protocolGroup.setItemCaption(Protocol.DDI_HTTP, "Direct Device Interface (HTTP poll)"); - protocolGroup.setNullSelectionAllowed(false); - protocolGroup.addValueChangeListener(event -> { - final boolean directDeviceOptionSelected = event.getProperty().getValue().equals(Protocol.DDI_HTTP); - pollUrlTextField.setVisible(directDeviceOptionSelected); - gatewayTokenTextField.setVisible(directDeviceOptionSelected); - }); - protocolGroup.setItemEnabled(Protocol.DMF_AMQP, dmfEnabled); - if (!dmfEnabled) { - protocolGroup.select(Protocol.DDI_HTTP); - } - } - - private void createOkButton(final GenerateDialogCallback callback) { - - this.buttonOk = new Button("generate"); - buttonOk.setImmediate(true); - buttonOk.setIcon(FontAwesome.GEARS); - buttonOk.addClickListener(event -> { - try { - callback.okButton(namePrefixTextField.getValue(), tenantTextField.getValue(), - Integer.valueOf(amountTextField.getValue().replace(".", "").replace(",", "")), - Integer.valueOf(pollDelayTextField.getValue().replace(".", "")), - new URL(pollUrlTextField.getValue()), gatewayTokenTextField.getValue(), - (Protocol) protocolGroup.getValue()); - } catch (final NumberFormatException | MalformedURLException e) { - LOGGER.info(e.getMessage(), e); - } - GenerateDialog.this.close(); - }); - } - - private static TextField createRequiredTextfield(final String caption, final String value, final Resource icon, - final Validator validator) { - final TextField textField = new TextField(caption, value); - return addTextFieldValues(textField, icon, validator); - } - - private static TextField createRequiredTextfield(final String caption, final Property dataSource, - final Resource icon, final Validator validator) { - final TextField textField = new TextField(caption, dataSource); - return addTextFieldValues(textField, icon, validator); - } - - private static TextField addTextFieldValues(final TextField textField, final Resource icon, - final Validator validator) { - textField.setIcon(icon); - textField.setRequired(true); - if (validator != null) { - textField.addValidator(validator); - } - return textField; - } - -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/ui/SimulatorUI.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/ui/SimulatorUI.java deleted file mode 100644 index 1c09a702d..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/ui/SimulatorUI.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator.ui; - -import org.springframework.beans.factory.annotation.Autowired; - -import com.vaadin.annotations.Push; -import com.vaadin.annotations.Theme; -import com.vaadin.annotations.Title; -import com.vaadin.navigator.Navigator; -import com.vaadin.server.VaadinRequest; -import com.vaadin.shared.communication.PushMode; -import com.vaadin.shared.ui.ui.Transport; -import com.vaadin.spring.annotation.SpringUI; -import com.vaadin.spring.navigator.SpringViewProvider; -import com.vaadin.ui.Panel; -import com.vaadin.ui.UI; -import com.vaadin.ui.VerticalLayout; - -/** - * The vaadin simulator UI which allows to generate simulated devices and show - * their current status and update progress. - * - * @author Michael Hirsch - * - */ -@SpringUI(path = "") -@Title("hawkBit Device Simulator") -@Theme(value = "simulator") -@Push(value = PushMode.AUTOMATIC, transport = Transport.WEBSOCKET) -public class SimulatorUI extends UI { - - private static final long serialVersionUID = 1L; - - private final VerticalLayout rootLayout = new VerticalLayout(); - - @Autowired - private SpringViewProvider viewProvider; - - @Override - protected void init(final VaadinRequest request) { - - rootLayout.setSizeFull(); - - final Panel viewContainer = new Panel(); - viewContainer.setSizeFull(); - rootLayout.addComponent(viewContainer); - rootLayout.setExpandRatio(viewContainer, 1.0F); - - final Navigator navigator = new Navigator(this, viewContainer); - navigator.addProvider(viewProvider); - - setContent(rootLayout); - } - -} diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/ui/SimulatorView.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/ui/SimulatorView.java deleted file mode 100644 index f5dfab452..000000000 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/ui/SimulatorView.java +++ /dev/null @@ -1,359 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.simulator.ui; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Locale; - -import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice; -import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol; -import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Status; -import org.eclipse.hawkbit.simulator.DeviceSimulatorRepository; -import org.eclipse.hawkbit.simulator.SimulatedDeviceFactory; -import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus; -import org.eclipse.hawkbit.simulator.amqp.AmqpProperties; -import org.eclipse.hawkbit.simulator.event.InitUpdate; -import org.eclipse.hawkbit.simulator.event.NextPollCounterUpdate; -import org.eclipse.hawkbit.simulator.event.ProgressUpdate; -import org.springframework.beans.factory.annotation.Autowired; - -import com.google.common.eventbus.EventBus; -import com.google.common.eventbus.Subscribe; -import com.vaadin.data.util.BeanContainer; -import com.vaadin.data.util.BeanItem; -import com.vaadin.data.util.converter.Converter; -import com.vaadin.navigator.View; -import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; -import com.vaadin.server.FontAwesome; -import com.vaadin.spring.annotation.SpringView; -import com.vaadin.ui.Button; -import com.vaadin.ui.ComboBox; -import com.vaadin.ui.Grid; -import com.vaadin.ui.Grid.CellReference; -import com.vaadin.ui.Grid.CellStyleGenerator; -import com.vaadin.ui.Grid.SelectionMode; -import com.vaadin.ui.HorizontalLayout; -import com.vaadin.ui.Label; -import com.vaadin.ui.UI; -import com.vaadin.ui.VerticalLayout; -import com.vaadin.ui.renderers.HtmlRenderer; -import com.vaadin.ui.renderers.ProgressBarRenderer; - -/** - * Vaadin view which allows to generate devices through the DMF API and show the - * current simulated devices in a grid with their current status and update - * progress. - * - */ -@SpringView(name = "") -// The inheritance comes from Vaadin -@SuppressWarnings("squid:MaximumInheritanceDepth") -public class SimulatorView extends VerticalLayout implements View { - - private static final String HTML_SPAN = ";"; - - private static final String NEXT_POLL_COUNTER_SEC_COL = "nextPollCounterSec"; - - private static final String RESPONSE_STATUS_COL = "updateStatus"; - - private static final String PROTOCOL_COL = "protocol"; - - private static final String TENANT_COL = "tenant"; - - private static final String PROGRESS_COL = "progress"; - - private static final String SWVERSION_COL = "swversion"; - - private static final String STATUS_COL = "status"; - - private static final String ID_COL = "id"; - - private static final long serialVersionUID = 1L; - - @Autowired - private transient DeviceSimulatorRepository repository; - - @Autowired - private transient SimulatedDeviceFactory deviceFactory; - - @Autowired - private transient EventBus eventbus; - - @Autowired - private transient AmqpProperties amqpProperties; - - private final Label caption = new Label("DMF/DDI Simulated Devices"); - private final HorizontalLayout toolbar = new HorizontalLayout(); - private final Grid grid = new Grid(); - private final ComboBox responseComboBox = new ComboBox("", - Arrays.asList(ResponseStatus.SUCCESSFUL, ResponseStatus.ERROR)); - - private BeanContainer beanContainer; - - @SuppressWarnings("unchecked") - @Override - public void enter(final ViewChangeEvent event) { - eventbus.register(this); - setSizeFull(); - - // caption - caption.addStyleName("h2"); - - // toolbar - createToolbar(); - - beanContainer = new BeanContainer<>(AbstractSimulatedDevice.class); - beanContainer.setBeanIdProperty(ID_COL); - - grid.setSizeFull(); - grid.setCellStyleGenerator(new CellStyleGenerator() { - - private static final long serialVersionUID = 1L; - - @Override - public String getStyle(final CellReference cellReference) { - return cellReference.getPropertyId().equals(STATUS_COL) ? "centeralign" : null; - } - }); - - grid.setSelectionMode(SelectionMode.NONE); - grid.setContainerDataSource(beanContainer); - grid.appendHeaderRow().getCell(RESPONSE_STATUS_COL).setComponent(responseComboBox); - grid.setColumnOrder(ID_COL, STATUS_COL, SWVERSION_COL, PROGRESS_COL, TENANT_COL, PROTOCOL_COL, - RESPONSE_STATUS_COL, NEXT_POLL_COUNTER_SEC_COL); - // header widths - grid.getColumn(STATUS_COL).setMaximumWidth(80); - grid.getColumn(PROTOCOL_COL).setMaximumWidth(180); - grid.getColumn(RESPONSE_STATUS_COL).setMaximumWidth(240); - grid.getColumn(NEXT_POLL_COUNTER_SEC_COL).setMaximumWidth(210); - - grid.getColumn(NEXT_POLL_COUNTER_SEC_COL).setHeaderCaption("Next Poll in (sec)"); - grid.getColumn(SWVERSION_COL).setHeaderCaption("SW Version"); - grid.getColumn(RESPONSE_STATUS_COL).setHeaderCaption("Response Update Status"); - grid.getColumn(PROGRESS_COL).setRenderer(new ProgressBarRenderer()); - grid.getColumn(PROTOCOL_COL).setConverter(createProtocolConverter()); - grid.getColumn(STATUS_COL).setRenderer(new HtmlRenderer(), createStatusConverter()); - grid.removeColumn(TENANT_COL); - - // grid combobox - responseComboBox.setItemIcon(ResponseStatus.SUCCESSFUL, FontAwesome.CHECK_CIRCLE); - responseComboBox.setItemIcon(ResponseStatus.ERROR, FontAwesome.EXCLAMATION_CIRCLE); - responseComboBox.setNullSelectionAllowed(false); - responseComboBox.setValue(ResponseStatus.SUCCESSFUL); - responseComboBox.addValueChangeListener( - valueChangeEvent -> beanContainer.getItemIds().forEach(itemId -> beanContainer.getItem(itemId) - .getItemProperty(RESPONSE_STATUS_COL).setValue(valueChangeEvent.getProperty().getValue()))); - - // add all components - addComponent(caption); - addComponent(toolbar); - addComponent(grid); - - setExpandRatio(grid, 1.0F); - - // load beans - repository.getAll().forEach(beanContainer::addBean); - } - - @Override - public void detach() { - super.detach(); - eventbus.unregister(this); - } - - @SuppressWarnings("unchecked") - @Subscribe - public void pollCounterUpdate(final NextPollCounterUpdate update) { - final Collection devices = update.getDevices(); - this.getUI().access(() -> devices.forEach(device -> { - final BeanItem item = beanContainer.getItem(device.getId()); - if (item != null) { - item.getItemProperty(NEXT_POLL_COUNTER_SEC_COL).setValue(device.getNextPollCounterSec()); - } - })); - } - - /** - * Method to retrieve {@link InitUpdate} events from the event bus. - * - * @param update - * the update event posted on the event bus - */ - @SuppressWarnings("unchecked") - @Subscribe - public void initUpdate(final InitUpdate update) { - final AbstractSimulatedDevice device = update.getDevice(); - this.getUI().access(() -> { - final BeanItem item = beanContainer.getItem(device.getId()); - if (item == null) { - return; - } - - item.getItemProperty(PROGRESS_COL).setValue(device.getProgress()); - item.getItemProperty(STATUS_COL).setValue(Status.PEDNING); - item.getItemProperty(SWVERSION_COL).setValue(device.getSwversion()); - }); - } - - /** - * Method to retrieve {@link ProgressUpdate} events from the event bus. - * - * @param update - * the update event posted on the event bus - */ - @SuppressWarnings("unchecked") - @Subscribe - public void progessUpdate(final ProgressUpdate update) { - final AbstractSimulatedDevice device = update.getDevice(); - this.getUI().access(() -> { - final BeanItem item = beanContainer.getItem(device.getId()); - if (item != null) { - item.getItemProperty(PROGRESS_COL).setValue(device.getProgress()); - setStatusColumn(device, item); - } - }); - } - - @SuppressWarnings("unchecked") - private void setStatusColumn(final AbstractSimulatedDevice device, final BeanItem item) { - if (device.getProgress() >= 1) { - switch (device.getUpdateStatus().getResponseStatus()) { - case SUCCESSFUL: - item.getItemProperty(STATUS_COL).setValue(Status.FINISH); - break; - case ERROR: - item.getItemProperty(STATUS_COL).setValue(Status.ERROR); - break; - default: - item.getItemProperty(STATUS_COL).setValue(Status.UNKNWON); - } - } else { - item.getItemProperty(STATUS_COL).setValue(Status.PEDNING); - } - } - - private void createToolbar() { - final Button createDevicesButton = new Button("generate..."); - createDevicesButton.setIcon(FontAwesome.GEARS); - createDevicesButton.addClickListener(event -> openGenerateDialog()); - - final Button clearDevicesButton = new Button("clear"); - clearDevicesButton.setIcon(FontAwesome.ERASER); - clearDevicesButton.addClickListener(event -> clearSimulatedDevices()); - - toolbar.addComponent(createDevicesButton); - toolbar.addComponent(clearDevicesButton); - toolbar.setSpacing(true); - } - - private void clearSimulatedDevices() { - repository.clear(); - beanContainer.removeAllItems(); - } - - private void openGenerateDialog() { - UI.getCurrent().addWindow( - new GenerateDialog((namePrefix, tenant, amount, pollDelay, basePollUrl, gatewayToken, protocol) -> { - for (int index = 0; index < amount; index++) { - final String deviceId = namePrefix + index; - beanContainer - .addBean(repository.add(deviceFactory.createSimulatedDeviceWithImmediatePoll(deviceId, - tenant.toLowerCase(), protocol, pollDelay, basePollUrl, gatewayToken))); - } - }, amqpProperties.isEnabled())); - } - - private ProtocolConverter createProtocolConverter() { - return new ProtocolConverter(); - } - - private StatusConverter createStatusConverter() { - return new StatusConverter(); - } - - public static final class ProtocolConverter implements Converter { - private static final long serialVersionUID = 1L; - - @Override - public Protocol convertToModel(final String value, final Class targetType, - final Locale locale) { - return null; - } - - @Override - public String convertToPresentation(final Protocol value, final Class targetType, - final Locale locale) { - switch (value) { - case DDI_HTTP: - return "DDI API (http)"; - case DMF_AMQP: - return "DMF API (amqp)"; - default: - return "unknown"; - } - } - - @Override - public Class getModelType() { - return Protocol.class; - } - - @Override - public Class getPresentationType() { - return String.class; - } - } - - private static final class StatusConverter implements Converter { - private static final long serialVersionUID = 1L; - - @Override - public Status convertToModel(final String value, final Class targetType, - final Locale locale) { - return null; - } - - @Override - public String convertToPresentation(final Status value, final Class targetType, - final Locale locale) { - switch (value) { - case UNKNWON: - return "&#x" + Integer.toHexString(FontAwesome.QUESTION_CIRCLE.getCodepoint()) - + HTML_SPAN; - case PEDNING: - return "&#x" + Integer.toHexString(FontAwesome.REFRESH.getCodepoint()) - + HTML_SPAN; - case FINISH: - return "&#x" + Integer.toHexString(FontAwesome.CHECK_CIRCLE.getCodepoint()) - + HTML_SPAN; - case ERROR: - return "&#x" - + Integer.toHexString(FontAwesome.EXCLAMATION_CIRCLE.getCodepoint()) + HTML_SPAN; - default: - throw new IllegalStateException("unknown value"); - } - } - - @Override - public Class getModelType() { - return Status.class; - } - - @Override - public Class getPresentationType() { - return String.class; - } - } - -} diff --git a/examples/hawkbit-device-simulator/src/main/resources/VAADIN/themes/simulator/styles.scss b/examples/hawkbit-device-simulator/src/main/resources/VAADIN/themes/simulator/styles.scss deleted file mode 100644 index 56ed48c34..000000000 --- a/examples/hawkbit-device-simulator/src/main/resources/VAADIN/themes/simulator/styles.scss +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -// Import valo after setting the parameters -@import "../valo/valo"; - - -.simulator{ - @include valo; - - .yellowicon { - color: orange; - } - .greenicon { - color: green; - } - .grayicon { - color: gray; - } - .redicon { - color: red; - } - - .v-grid-cell.centeralign { - text-align: center; - } -} \ No newline at end of file diff --git a/examples/hawkbit-device-simulator/src/main/resources/application-cloud.properties b/examples/hawkbit-device-simulator/src/main/resources/application-cloud.properties deleted file mode 100644 index 925eea1c8..000000000 --- a/examples/hawkbit-device-simulator/src/main/resources/application-cloud.properties +++ /dev/null @@ -1,27 +0,0 @@ -# -# Copyright (c) 2015 Bosch Software Innovations GmbH and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://www.eclipse.org/legal/epl-v10.html -# - -# SECURITY (SecurityProperties) -security.basic.enabled=true -security.user.name=${BASIC_USERNAME:admin} -security.user.password=${BASIC_PASSWORD:admin} -security.user.role=USER -security.require-ssl=false -security.enable-csrf=false -security.basic.realm=DeviceSimulator -security.basic.path= /** -security.basic.authorize-mode=ROLE -security.filter-order=0 -security.headers.xss=false -security.headers.cache=false -security.headers.frame=false -security.headers.content-type=false -security.headers.hsts=all -security.sessions=stateless -security.ignored=/VAADIN/** \ No newline at end of file diff --git a/examples/hawkbit-device-simulator/src/main/resources/application.properties b/examples/hawkbit-device-simulator/src/main/resources/application.properties deleted file mode 100644 index cc71f9039..000000000 --- a/examples/hawkbit-device-simulator/src/main/resources/application.properties +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright (c) 2015 Bosch Software Innovations GmbH and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://www.eclipse.org/legal/epl-v10.html -# - -## Configuration for DMF communication -hawkbit.device.simulator.amqp.enabled=true -hawkbit.device.simulator.amqp.receiverConnectorQueueFromSp=simulator_receiver -hawkbit.device.simulator.amqp.deadLetterQueue=simulator_deadletter -hawkbit.device.simulator.amqp.deadLetterExchange=simulator.deadletter -hawkbit.device.simulator.amqp.senderForSpExchange=simulator.replyTo - -## Configuration for simulations -hawkbit.device.simulator.autostarts.[0].tenant=DEFAULT - -hawkbit.device.simulator.attributes[0].key=isoCode -hawkbit.device.simulator.attributes[0].random=DE,US,AU,FR,DK,CA -hawkbit.device.simulator.attributes[1].key=hwRevision -hawkbit.device.simulator.attributes[1].value=1.1 -hawkbit.device.simulator.attributes[2].key=serial -hawkbit.device.simulator.attributes[2].value=${random.value} - -endpoints.health.enabled=true - -## Configuration for local RabbitMQ integration -spring.rabbitmq.username=guest -spring.rabbitmq.password=guest -spring.rabbitmq.virtualHost=/ -spring.rabbitmq.host=localhost -spring.rabbitmq.port=5672 -spring.rabbitmq.dynamic=true - -security.basic.enabled=false -server.port=8083 diff --git a/examples/hawkbit-device-simulator/src/main/resources/logback-spring.xml b/examples/hawkbit-device-simulator/src/main/resources/logback-spring.xml deleted file mode 100644 index 9403ee454..000000000 --- a/examples/hawkbit-device-simulator/src/main/resources/logback-spring.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/examples/hawkbit-example-core-feign-client/README.md b/examples/hawkbit-example-core-feign-client/README.md deleted file mode 100644 index 432a31c41..000000000 --- a/examples/hawkbit-example-core-feign-client/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Eclipse.IoT hawkBit - Example Core Feign Client - -This modules contains core beans that are needed to create a [Feign Client](https://github.com/Netflix/feign) with hwakBit. - -# Compile - -#### Build hawkbit-example-core-feign-client - -``` -$ cd hawkbit/examples/hawkbit-example-core-feign-client -$ mvn clean install -``` - diff --git a/examples/hawkbit-example-core-feign-client/pom.xml b/examples/hawkbit-example-core-feign-client/pom.xml deleted file mode 100644 index 38b0754f3..000000000 --- a/examples/hawkbit-example-core-feign-client/pom.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - 4.0.0 - - org.eclipse.hawkbit - hawkbit-examples-parent - 0.2.0-SNAPSHOT - - - hawkbit-example-core-feign-client - hawkBit :: Examples :: Feign Core Client - - - - io.github.openfeign - feign-core - - - org.springframework - spring-web - - - org.springframework.cloud - spring-cloud-netflix-core - - - org.springframework.cloud - spring-cloud-commons - - - org.springframework.cloud - spring-cloud-context - - - org.slf4j - slf4j-api - - - io.github.openfeign - feign-slf4j - - - diff --git a/examples/hawkbit-example-core-feign-client/src/main/java/org/eclipse/hawkbit/feign/core/client/ApplicationJsonRequestHeaderInterceptor.java b/examples/hawkbit-example-core-feign-client/src/main/java/org/eclipse/hawkbit/feign/core/client/ApplicationJsonRequestHeaderInterceptor.java deleted file mode 100644 index e7faca3b7..000000000 --- a/examples/hawkbit-example-core-feign-client/src/main/java/org/eclipse/hawkbit/feign/core/client/ApplicationJsonRequestHeaderInterceptor.java +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.feign.core.client; - -import org.springframework.http.MediaType; - -import feign.RequestInterceptor; -import feign.RequestTemplate; - -/** - * An feign request interceptor to set the defined {@code Accept} and - * {@code Content-Type} headers for each request to {@code application/json}. - */ -public class ApplicationJsonRequestHeaderInterceptor implements RequestInterceptor { - - @Override - public void apply(final RequestTemplate template) { - template.header("Accept", MediaType.APPLICATION_JSON_VALUE); - template.header("Content-Type", MediaType.APPLICATION_JSON_VALUE); - } - -} diff --git a/examples/hawkbit-example-core-feign-client/src/main/java/org/eclipse/hawkbit/feign/core/client/FeignClientConfiguration.java b/examples/hawkbit-example-core-feign-client/src/main/java/org/eclipse/hawkbit/feign/core/client/FeignClientConfiguration.java deleted file mode 100644 index 1512b7f9e..000000000 --- a/examples/hawkbit-example-core-feign-client/src/main/java/org/eclipse/hawkbit/feign/core/client/FeignClientConfiguration.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.feign.core.client; - -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.cloud.netflix.feign.FeignClientsConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; - -import feign.Contract; -import feign.Feign; - -/** - * Spring annotated java configuration class which defines necessary beans for - * configure the feign-client. - */ -@Configuration -@ConditionalOnClass(Feign.class) -@Import(FeignClientsConfiguration.class) -public class FeignClientConfiguration { - - @Bean - public ApplicationJsonRequestHeaderInterceptor jsonHeaderInterceptor() { - return new ApplicationJsonRequestHeaderInterceptor(); - } - - @Bean - public Contract feignContract() { - return new IgnoreMultipleConsumersProducersSpringMvcContract(); - } -} diff --git a/examples/hawkbit-example-core-feign-client/src/main/java/org/eclipse/hawkbit/feign/core/client/IgnoreMultipleConsumersProducersSpringMvcContract.java b/examples/hawkbit-example-core-feign-client/src/main/java/org/eclipse/hawkbit/feign/core/client/IgnoreMultipleConsumersProducersSpringMvcContract.java deleted file mode 100644 index e2ca27077..000000000 --- a/examples/hawkbit-example-core-feign-client/src/main/java/org/eclipse/hawkbit/feign/core/client/IgnoreMultipleConsumersProducersSpringMvcContract.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.feign.core.client; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.LinkedHashMap; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.netflix.feign.support.SpringMvcContract; - -import feign.MethodMetadata; -import feign.Param; - -/** - * Own implementation of the {@link SpringMvcContract} which catches the - * {@link IllegalStateException} which occurs due multiple produces and consumes - * values in the request-mapping - * annoation.https://github.com/spring-cloud/spring-cloud-netflix/issues/808 - */ -public class IgnoreMultipleConsumersProducersSpringMvcContract extends SpringMvcContract { - - private static final Logger LOGGER = LoggerFactory - .getLogger(IgnoreMultipleConsumersProducersSpringMvcContract.class); - - @Override - protected void processAnnotationOnMethod(final MethodMetadata data, final Annotation methodAnnotation, - final Method method) { - try { - super.processAnnotationOnMethod(data, methodAnnotation, method); - } catch (final IllegalStateException e) { - // ignore illegalstateexception here because it's thrown because of - // multiple consumers and produces, see - // https://github.com/spring-cloud/spring-cloud-netflix/issues/808 - LOGGER.trace(e.getMessage(), e); - - // This line from super is mandatory to avoid that access to the - // expander causes a nullpointer. - data.indexToExpander(new LinkedHashMap()); - } - } -} diff --git a/examples/hawkbit-example-ddi-feign-client/README.md b/examples/hawkbit-example-ddi-feign-client/README.md deleted file mode 100644 index 0eae90c23..000000000 --- a/examples/hawkbit-example-ddi-feign-client/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# Eclipse.IoT hawkBit - Example DDI Feign Client API - -This modules contains the declarative client binding resources of the DDI API. -For more information see 'Feign Inheritance Support' at [Spring Cloud] (http://projects.spring.io/spring-cloud/spring-cloud.html). -Powered by [Feign](https://github.com/Netflix/feign). - -# Compile - -#### Build hawkbit-example-ddi-feign-client - -``` -$ cd hawkbit/examples/hawkbit-example-ddi-feign-client -$ mvn clean install -``` diff --git a/examples/hawkbit-example-ddi-feign-client/pom.xml b/examples/hawkbit-example-ddi-feign-client/pom.xml deleted file mode 100644 index bbd39535e..000000000 --- a/examples/hawkbit-example-ddi-feign-client/pom.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - 4.0.0 - - org.eclipse.hawkbit - hawkbit-examples-parent - 0.2.0-SNAPSHOT - - hawkbit-example-ddi-feign-client - - hawkBit :: Examples :: DDI Feign Client - - - - org.eclipse.hawkbit - hawkbit-example-core-feign-client - ${project.version} - - - org.eclipse.hawkbit - hawkbit-ddi-api - ${project.version} - - - com.google.guava - guava - - - io.github.openfeign - feign-core - - - io.github.openfeign - feign-jackson - - - com.fasterxml.jackson.core - jackson-databind - - - diff --git a/examples/hawkbit-example-ddi-feign-client/src/main/java/org/eclipse/hawkbit/ddi/client/resource/RootControllerResourceClient.java b/examples/hawkbit-example-ddi-feign-client/src/main/java/org/eclipse/hawkbit/ddi/client/resource/RootControllerResourceClient.java deleted file mode 100644 index ab060d2cc..000000000 --- a/examples/hawkbit-example-ddi-feign-client/src/main/java/org/eclipse/hawkbit/ddi/client/resource/RootControllerResourceClient.java +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.ddi.client.resource; - -import org.eclipse.hawkbit.ddi.rest.api.DdiRootControllerRestApi; -import org.springframework.cloud.netflix.feign.FeignClient; - -/** - * Client binding for the Rootcontroller resource of the DDI API. - */ -@FeignClient(name = "RootControllerClient", url = "${hawkbit.url:localhost:8080}") -public interface RootControllerResourceClient extends DdiRootControllerRestApi { - -} diff --git a/examples/hawkbit-example-mgmt-feign-client/.gitignore b/examples/hawkbit-example-mgmt-feign-client/.gitignore deleted file mode 100644 index 4b9b73073..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/target/ -/bin/ -/.apt_generated/ diff --git a/examples/hawkbit-example-mgmt-feign-client/README.md b/examples/hawkbit-example-mgmt-feign-client/README.md deleted file mode 100644 index b5b7eb3d2..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Eclipse.IoT hawkBit - Example Management Feign Client API - -This modules contains the declarative client binding resources of the Management API. -For more information see 'Feign Inheritance Support' at [Spring Cloud] (http://projects.spring.io/spring-cloud/spring-cloud.html). -Powered by [Feign](https://github.com/Netflix/feign). - -# Compile - -#### Build hawkbit-example-mgmt-feign-client - -``` -$ cd hawkbit/examples/hawkbit-example-mgmt-feign-client -$ mvn clean install -``` - diff --git a/examples/hawkbit-example-mgmt-feign-client/pom.xml b/examples/hawkbit-example-mgmt-feign-client/pom.xml deleted file mode 100644 index 36c531ad6..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/pom.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - 4.0.0 - - org.eclipse.hawkbit - hawkbit-examples-parent - 0.2.0-SNAPSHOT - - jar - hawkbit-example-mgmt-feign-client - hawkBit :: Examples :: Management client API - - - - org.eclipse.hawkbit - hawkbit-example-core-feign-client - ${project.version} - - - org.eclipse.hawkbit - hawkbit-mgmt-api - ${project.version} - - - com.google.guava - guava - - - io.github.openfeign - feign-core - - - io.github.openfeign - feign-jackson - - - com.fasterxml.jackson.core - jackson-databind - - - hibernate-validator - org.hibernate - - - \ No newline at end of file diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetClientResource.java deleted file mode 100644 index b38fc8edc..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetClientResource.java +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource; - -import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetRestApi; -import org.springframework.cloud.netflix.feign.FeignClient; - -/** - * Client binding for the DistributionSet resource of the management API. - */ -@FeignClient(name = "MgmtDistributionSetClient", url = "${hawkbit.url:localhost:8080}") -public interface MgmtDistributionSetClientResource extends MgmtDistributionSetRestApi { - -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetTagClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetTagClientResource.java deleted file mode 100644 index c08894cca..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetTagClientResource.java +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource; - -import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetTagRestApi; -import org.springframework.cloud.netflix.feign.FeignClient; - -/** - * Client binding for the DistributionSetTag resource of the management API. - */ -@FeignClient(name = "MgmtDistributionSetTagClient", url = "${hawkbit.url:localhost:8080}") -public interface MgmtDistributionSetTagClientResource extends MgmtDistributionSetTagRestApi { -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetTypeClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetTypeClientResource.java deleted file mode 100644 index d7cb509d8..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetTypeClientResource.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource; - -import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetTypeRestApi; -import org.springframework.cloud.netflix.feign.FeignClient; - -/** - * Client binding for the DistributionSetType resource of the management API. - * - */ -@FeignClient(name = "MgmtDistributionSetTypeClient", url = "${hawkbit.url:localhost:8080}") -public interface MgmtDistributionSetTypeClientResource extends MgmtDistributionSetTypeRestApi { - -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDownloadArtifactClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDownloadArtifactClientResource.java deleted file mode 100644 index 831b17a5f..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDownloadArtifactClientResource.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource; - -import org.eclipse.hawkbit.mgmt.rest.api.MgmtDownloadArtifactRestApi; -import org.springframework.cloud.netflix.feign.FeignClient; - -/** - * A feign-client interface declaration which allows to build a feign-client - * stub. - */ -@FeignClient(name = "MgmtDownloadArtifactClient", url = "${hawkbit.url:localhost:8080}") -public interface MgmtDownloadArtifactClientResource extends MgmtDownloadArtifactRestApi { - -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDownloadClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDownloadClientResource.java deleted file mode 100644 index 0a4d1f500..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDownloadClientResource.java +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource; - -import org.eclipse.hawkbit.mgmt.rest.api.MgmtDownloadRestApi; -import org.springframework.cloud.netflix.feign.FeignClient; - -/** - * - */ -@FeignClient(name = "MgmtDownloadClient", url = "${hawkbit.url:localhost:8080}") -public interface MgmtDownloadClientResource extends MgmtDownloadRestApi { -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtRolloutClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtRolloutClientResource.java deleted file mode 100644 index 0d6856d98..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtRolloutClientResource.java +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource; - -import org.eclipse.hawkbit.mgmt.rest.api.MgmtRolloutRestApi; -import org.springframework.cloud.netflix.feign.FeignClient; - -/** - * Client binding for the Rollout resource of the management API. - */ -@FeignClient(name = "MgmtRolloutClient", url = "${hawkbit.url:localhost:8080}") -public interface MgmtRolloutClientResource extends MgmtRolloutRestApi { -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSoftwareModuleClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSoftwareModuleClientResource.java deleted file mode 100644 index c5d019e78..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSoftwareModuleClientResource.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource; - -import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifact; -import org.eclipse.hawkbit.mgmt.rest.api.MgmtSoftwareModuleRestApi; -import org.springframework.cloud.netflix.feign.FeignClient; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.multipart.MultipartFile; - -import feign.Param; - -/** - * Client binding for the SoftwareModule resource of the management API. - */ -@FeignClient(name = "MgmtSoftwareModuleClient", url = "${hawkbit.url:localhost:8080}") -public interface MgmtSoftwareModuleClientResource extends MgmtSoftwareModuleRestApi { - - @Override - @RequestMapping(method = RequestMethod.POST, value = "/{softwareModuleId}/artifacts") - ResponseEntity uploadArtifact(@PathVariable("softwareModuleId") final Long softwareModuleId, - @Param("file") final MultipartFile file, - @RequestParam(value = "filename", required = false) final String optionalFileName, - @RequestParam(value = "md5sum", required = false) final String md5Sum, - @RequestParam(value = "sha1sum", required = false) final String sha1Sum); -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSoftwareModuleTypeClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSoftwareModuleTypeClientResource.java deleted file mode 100644 index 582ec1821..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSoftwareModuleTypeClientResource.java +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource; - -import org.eclipse.hawkbit.mgmt.rest.api.MgmtSoftwareModuleTypeRestApi; -import org.springframework.cloud.netflix.feign.FeignClient; - -/** - * Client binding for the SoftwareModuleType resource of the management API. - */ -@FeignClient(name = "MgmtSoftwareModuleTypeClient", url = "${hawkbit.url:localhost:8080}") -public interface MgmtSoftwareModuleTypeClientResource extends MgmtSoftwareModuleTypeRestApi { -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSystemManagementClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSystemManagementClientResource.java deleted file mode 100644 index 8cb293ea7..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSystemManagementClientResource.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource; - -import org.eclipse.hawkbit.mgmt.rest.api.MgmtSystemManagementRestApi; -import org.springframework.cloud.netflix.feign.FeignClient; - -/** - * Client binding for the {@link MgmtSystemManagementRestApi}. - * - */ -@FeignClient(name = "MgmtSystemManagementClient", url = "${hawkbit.url:localhost:8080}") -public interface MgmtSystemManagementClientResource extends MgmtSystemManagementRestApi { - -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTargetClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTargetClientResource.java deleted file mode 100644 index a64509340..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTargetClientResource.java +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource; - -import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetRestApi; -import org.springframework.cloud.netflix.feign.FeignClient; - -/** - * Client binding for the Target resource of the management API. - */ -@FeignClient(name = "MgmtTargetClient", url = "${hawkbit.url:localhost:8080}") -public interface MgmtTargetClientResource extends MgmtTargetRestApi { -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTargetFilterQueryClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTargetFilterQueryClientResource.java deleted file mode 100644 index 8881e6476..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTargetFilterQueryClientResource.java +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource; - -import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetFilterQueryRestApi; -import org.springframework.cloud.netflix.feign.FeignClient; - -/** - * Client binding for the Target filter query resource of the management API. - */ -@FeignClient(name = "MgmtTargetFilterQueryClient", url = "${hawkbit.url:localhost:8080}") -public interface MgmtTargetFilterQueryClientResource extends MgmtTargetFilterQueryRestApi { -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTargetTagClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTargetTagClientResource.java deleted file mode 100644 index b1d264e78..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTargetTagClientResource.java +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource; - -import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetTagRestApi; -import org.springframework.cloud.netflix.feign.FeignClient; - -/** - * Client binding for the TargetTag resource of the management API. - */ -@FeignClient(name = "MgmtTargetTagClient", url = "${hawkbit.url:localhost:8080}") -public interface MgmtTargetTagClientResource extends MgmtTargetTagRestApi { -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTenantManagementClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTenantManagementClientResource.java deleted file mode 100644 index 748eac617..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTenantManagementClientResource.java +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource; - -import org.eclipse.hawkbit.mgmt.rest.api.MgmtTenantManagementRestApi; -import org.springframework.cloud.netflix.feign.FeignClient; - -/** - * Client binding for the {@link MgmtTenantManagementRestApi}. - * - */ -@FeignClient(name = "MgmtTenantManagementClient", url = "${hawkbit.url:localhost:8080}") -public interface MgmtTenantManagementClientResource extends MgmtTenantManagementRestApi { -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetBuilder.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetBuilder.java deleted file mode 100644 index 400f259fe..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetBuilder.java +++ /dev/null @@ -1,134 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource.builder; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSetRequestBodyPost; -import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleAssigment; - -/** - * Builder pattern for building {@link MgmtDistributionSetRequestBodyPost}. - */ -// Exception squid:S1701 - builder pattern -@SuppressWarnings({ "squid:S1701" }) -public class DistributionSetBuilder { - - private String name; - private String version; - private String type; - private String description; - private final List modules = new ArrayList<>(); - - /** - * @param name - * the name of the distribution set - * @return the builder itself - */ - public DistributionSetBuilder name(final String name) { - this.name = name; - return this; - } - - public DistributionSetBuilder moduleByID(final Long id) { - final MgmtSoftwareModuleAssigment softwareModuleAssigmentRest = new MgmtSoftwareModuleAssigment(); - softwareModuleAssigmentRest.setId(id); - modules.add(softwareModuleAssigmentRest); - return this; - } - - /** - * @param version - * the version of the distribution set - * @return the builder itself - */ - public DistributionSetBuilder version(final String version) { - this.version = version; - return this; - } - - /** - * @param type - * the distribution set type name for this distribution set - * @return the builder itself - */ - public DistributionSetBuilder type(final String type) { - this.type = type; - return this; - } - - /** - * @param description - * the description - * @return the builder itself - */ - public DistributionSetBuilder description(final String description) { - this.description = description; - return this; - } - - /** - * Builds a list with a single entry of - * {@link MgmtDistributionSetRequestBodyPost} which can directly be used to - * post on the RESTful-API. - * - * @return a single entry list of {@link MgmtDistributionSetRequestBodyPost} - */ - public List build() { - return Arrays.asList(doBuild("")); - } - - /** - * Builds a list of multiple {@link MgmtDistributionSetRequestBodyPost} to - * create multiple distribution sets at once. An increasing number will be - * used for version of the distribution set. The name and type will remain - * the same. - * - * @param count - * the amount of distribution sets body which should be created - * @return a list of {@link MgmtDistributionSetRequestBodyPost} - */ - public List buildAsList(final int count) { - return buildAsList(0, count); - } - - /** - * Builds a list of multiple {@link MgmtDistributionSetRequestBodyPost} to - * create multiple distribution sets at once. An increasing number will be - * used for version of the distribution set starting from given offset. The - * name and type will remain the same. - * - * @param count - * the amount of distribution sets body which should be created - * @param offset - * for for index start - * @return a list of {@link MgmtDistributionSetRequestBodyPost} - */ - public List buildAsList(final int offset, final int count) { - final List bodyList = new ArrayList<>(); - for (int index = offset; index < count + offset; index++) { - bodyList.add(doBuild(String.valueOf(index))); - } - - return bodyList; - } - - private MgmtDistributionSetRequestBodyPost doBuild(final String suffix) { - final MgmtDistributionSetRequestBodyPost body = new MgmtDistributionSetRequestBodyPost(); - body.setName(name); - body.setVersion(version + suffix); - body.setType(type); - body.setDescription(description); - body.setModules(modules); - return body; - } - -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetTypeBuilder.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetTypeBuilder.java deleted file mode 100644 index a4ea4da64..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetTypeBuilder.java +++ /dev/null @@ -1,136 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource.builder; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.eclipse.hawkbit.mgmt.json.model.distributionsettype.MgmtDistributionSetTypeRequestBodyPost; -import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleTypeAssigment; - -/** - * - * Builder pattern for building {@link MgmtDistributionSetTypeRequestBodyPost}. - * - */ -// Exception squid:S1701 - builder pattern -@SuppressWarnings({ "squid:S1701" }) -public class DistributionSetTypeBuilder { - - private String key; - private String name; - private String description; - private final List mandatorymodules = new ArrayList<>(); - private final List optionalmodules = new ArrayList<>(); - - /** - * @param key - * the key of the distribution set type - * @return the builder itself - */ - public DistributionSetTypeBuilder key(final String key) { - this.key = key; - return this; - } - - /** - * @param name - * the name of the distribution set type - * @return the builder itself - */ - public DistributionSetTypeBuilder name(final String name) { - this.name = name; - return this; - } - - /** - * @param description - * the description - * @return the builder itself - */ - public DistributionSetTypeBuilder description(final String description) { - this.description = description; - return this; - } - - /** - * @param softwareModuleTypeIds - * the IDs of the software module types which should be mandatory - * for the distribution set type - * @return the builder itself - */ - public DistributionSetTypeBuilder mandatorymodules(final Long... softwareModuleTypeIds) { - for (final Long id : softwareModuleTypeIds) { - final MgmtSoftwareModuleTypeAssigment softwareModuleTypeAssigmentRest = new MgmtSoftwareModuleTypeAssigment(); - softwareModuleTypeAssigmentRest.setId(id); - this.mandatorymodules.add(softwareModuleTypeAssigmentRest); - } - return this; - } - - /** - * - * @param softwareModuleTypeIds - * the IDs of the software module types which should be optional - * for the distribution set type - * @return the builder itself - */ - public DistributionSetTypeBuilder optionalmodules(final Long... softwareModuleTypeIds) { - for (final Long id : softwareModuleTypeIds) { - final MgmtSoftwareModuleTypeAssigment softwareModuleTypeAssigmentRest = new MgmtSoftwareModuleTypeAssigment(); - softwareModuleTypeAssigmentRest.setId(id); - this.optionalmodules.add(softwareModuleTypeAssigmentRest); - } - return this; - } - - /** - * Builds a list with a single entry of - * {@link MgmtDistributionSetTypeRequestBodyPost} which can directly be used - * in the RESTful-API. - * - * @return a single entry list of - * {@link MgmtDistributionSetTypeRequestBodyPost} - */ - public List build() { - return Arrays.asList(doBuild("")); - } - - /** - * Builds a list of multiple {@link MgmtDistributionSetTypeRequestBodyPost} - * to create multiple distribution set types at once. An increasing number - * will be added to the name and key of the distribution set type. The - * optional and mandatory software module types will remain the same. - * - * @param count - * the amount of distribution sets type body which should be - * created - * @return a list of {@link MgmtDistributionSetTypeRequestBodyPost} - */ - public List buildAsList(final int count) { - final List bodyList = new ArrayList<>(); - for (int index = 0; index < count; index++) { - bodyList.add(doBuild(String.valueOf(index))); - } - return bodyList; - - } - - private MgmtDistributionSetTypeRequestBodyPost doBuild(final String suffix) { - final MgmtDistributionSetTypeRequestBodyPost body = new MgmtDistributionSetTypeRequestBodyPost(); - body.setKey(key + suffix); - body.setName(name + suffix); - body.setDescription(description); - body.setMandatorymodules(mandatorymodules); - body.setOptionalmodules(optionalmodules); - return body; - } - -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/RolloutBuilder.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/RolloutBuilder.java deleted file mode 100644 index d2d291128..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/RolloutBuilder.java +++ /dev/null @@ -1,142 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource.builder; - -import java.util.List; - -import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutCondition; -import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutCondition.Condition; -import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutRestRequestBody; -import org.eclipse.hawkbit.mgmt.json.model.rolloutgroup.MgmtRolloutGroup; - -/** - * - * Builder pattern for building {@link MgmtRolloutRestRequestBody}. - * - */ -// Exception squid:S1701 - builder pattern -@SuppressWarnings({ "squid:S1701" }) -public class RolloutBuilder { - - private String name; - private int groupSize; - private String targetFilterQuery; - private long distributionSetId; - private String successThreshold; - private String errorThreshold; - private String description; - private List semiAutomaticGroups; - - /** - * @param name - * the name of the rollout - * @return the builder itself - */ - public RolloutBuilder name(final String name) { - this.name = name; - return this; - } - - /** - * @param semiAutomaticGroups - * as alternative to full automatic, i.e. {@link #groupSize(int)} - * @return the builder itself - */ - public RolloutBuilder semiAutomaticGroups(final List semiAutomaticGroups) { - this.semiAutomaticGroups = semiAutomaticGroups; - return this; - } - - /** - * @param groupSize - * the amount of groups the rollout should be split into - * @return the builder itself - */ - public RolloutBuilder groupSize(final int groupSize) { - this.groupSize = groupSize; - return this; - } - - /** - * @param targetFilterQuery - * the FIQL query language to filter targets to contain in the - * rollout - * @return the builder itself - */ - public RolloutBuilder targetFilterQuery(final String targetFilterQuery) { - this.targetFilterQuery = targetFilterQuery; - return this; - } - - /** - * @param description - * the description - * @return the builder itself - */ - public RolloutBuilder description(final String description) { - this.description = description; - return this; - } - - /** - * @param distributionSetId - * the ID of the distribution set to assign to the target in the - * rollout - * @return the builder itself - */ - public RolloutBuilder distributionSetId(final long distributionSetId) { - this.distributionSetId = distributionSetId; - return this; - } - - /** - * @param successThreshold - * the threshold to be used to indicate if a deployment group is - * successful, to trigger the success action - * @return the builder itself - */ - public RolloutBuilder successThreshold(final String successThreshold) { - this.successThreshold = successThreshold; - return this; - } - - /** - * @param errorThreshold - * the threshold to be used to indicate if a deployment group is - * failing, to trigger the error action - * @return the builder itself - */ - public RolloutBuilder errorThreshold(final String errorThreshold) { - this.errorThreshold = errorThreshold; - return this; - } - - /** - * Builds the rollout rest body to creating a rollout. - * - * @return the rest request body for creating a rollout - */ - public MgmtRolloutRestRequestBody build() { - return doBuild(); - } - - private MgmtRolloutRestRequestBody doBuild() { - final MgmtRolloutRestRequestBody body = new MgmtRolloutRestRequestBody(); - body.setName(name); - body.setAmountGroups(groupSize); - body.setTargetFilterQuery(targetFilterQuery); - body.setDistributionSetId(distributionSetId); - body.setDescription(description); - body.setSuccessCondition(new MgmtRolloutCondition(Condition.THRESHOLD, successThreshold)); - body.setErrorCondition(new MgmtRolloutCondition(Condition.THRESHOLD, errorThreshold)); - body.setGroups(semiAutomaticGroups); - return body; - } - -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleAssigmentBuilder.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleAssigmentBuilder.java deleted file mode 100644 index b9fbcb498..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleAssigmentBuilder.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource.builder; - -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleAssigment; - -/** - * - * Builder pattern for building {@link MgmtSoftwareModuleAssigment}. - * - */ -// Exception squid:S1701 - builder pattern -@SuppressWarnings({ "squid:S1701" }) -public class SoftwareModuleAssigmentBuilder { - - private final List ids; - - public SoftwareModuleAssigmentBuilder() { - ids = new ArrayList<>(); - } - - /** - * @param id - * the id of the software module - * @return the builder itself - */ - public SoftwareModuleAssigmentBuilder id(final Long id) { - ids.add(id); - return this; - } - - /** - * Builds a list with a single entry of {@link MgmtSoftwareModuleAssigment} - * which can directly be used in the RESTful-API. - * - * @return a single entry list of {@link MgmtSoftwareModuleAssigment} - */ - public List build() { - final List softwareModuleAssigmentRestList = new ArrayList<>(); - for (final Long id : ids) { - final MgmtSoftwareModuleAssigment softwareModuleAssigmentRest = new MgmtSoftwareModuleAssigment(); - softwareModuleAssigmentRest.setId(id); - softwareModuleAssigmentRestList.add(softwareModuleAssigmentRest); - } - return softwareModuleAssigmentRestList; - } - -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleBuilder.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleBuilder.java deleted file mode 100644 index 4bc803890..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleBuilder.java +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource.builder; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.eclipse.hawkbit.mgmt.json.model.distributionsettype.MgmtDistributionSetTypeRequestBodyPost; -import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleRequestBodyPost; - -/** - * - * Builder pattern for building {@link MgmtSoftwareModuleRequestBodyPost}. - * - */ -// Exception squid:S1701 - builder pattern -@SuppressWarnings({ "squid:S1701" }) -public class SoftwareModuleBuilder { - - private String name; - private String version; - private String type; - private String vendor; - private String description; - - /** - * @param name - * the name of the software module - * @return the builder itself - */ - public SoftwareModuleBuilder name(final String name) { - this.name = name; - return this; - } - - /** - * @param version - * the version of the software module - * @return the builder itsefl - */ - public SoftwareModuleBuilder version(final String version) { - this.version = version; - return this; - } - - /** - * @param type - * the key of the software module type to be used for this - * software module - * @return the builder itself - */ - public SoftwareModuleBuilder type(final String type) { - this.type = type; - return this; - } - - /** - * @param vendor - * the vendor - * @return the builder itself - */ - public SoftwareModuleBuilder vendor(final String vendor) { - this.vendor = vendor; - return this; - } - - /** - * @param description - * the description - * @return the builder itself - */ - public SoftwareModuleBuilder description(final String description) { - this.description = description; - return this; - } - - /** - * Builds a list with a single entry of - * {@link MgmtSoftwareModuleRequestBodyPost} which can directly be used in - * the RESTful-API. - * - * @return a single entry list of {@link MgmtSoftwareModuleRequestBodyPost} - */ - public List build() { - return Arrays.asList(doBuild("")); - } - - /** - * Builds a list of multiple {@link MgmtSoftwareModuleRequestBodyPost} to - * create multiple software module at once. An increasing number will be - * added to the version of the software module. The name and type will - * remain the same. - * - * @param count - * the amount of software module body which should be created - * @return a list of {@link MgmtDistributionSetTypeRequestBodyPost} - */ - public List buildAsList(final int count) { - final List bodyList = new ArrayList<>(); - for (int index = 0; index < count; index++) { - bodyList.add(doBuild(String.valueOf(index))); - } - - return bodyList; - } - - private MgmtSoftwareModuleRequestBodyPost doBuild(final String suffix) { - final MgmtSoftwareModuleRequestBodyPost body = new MgmtSoftwareModuleRequestBodyPost(); - body.setName(name); - body.setVersion(version + suffix); - body.setType(type); - body.setVendor(vendor); - body.setDescription(description); - return body; - } - -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleTypeBuilder.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleTypeBuilder.java deleted file mode 100644 index ca3267ed6..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleTypeBuilder.java +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource.builder; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleRequestBodyPost; -import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleTypeRequestBodyPost; - -/** - * - * Builder pattern for building {@link MgmtSoftwareModuleRequestBodyPost}. - * - */ -// Exception squid:S1701 - builder pattern -@SuppressWarnings({ "squid:S1701" }) -public class SoftwareModuleTypeBuilder { - - private String key; - private String name; - private String description; - private int maxAssignments; - - /** - * @param key - * the key of the software module type - * @return the builder itself - */ - public SoftwareModuleTypeBuilder key(final String key) { - this.key = key; - return this; - } - - /** - * @param name - * the name of the software module type - * @return the builder itself - */ - public SoftwareModuleTypeBuilder name(final String name) { - this.name = name; - return this; - } - - /** - * @param description - * of the module - * @return the builder itself - */ - public SoftwareModuleTypeBuilder description(final String description) { - this.description = description; - return this; - } - - /** - * @param maxAssignments - * of a module of that type to the same distribution set - * @return the builder itself - */ - public SoftwareModuleTypeBuilder maxAssignments(final int maxAssignments) { - this.maxAssignments = maxAssignments; - return this; - } - - /** - * Builds a list with a single entry of - * {@link MgmtSoftwareModuleTypeRequestBodyPost} which can directly be used - * in the RESTful-API. - * - * @return a single entry list of - * {@link MgmtSoftwareModuleTypeRequestBodyPost} - */ - public List build() { - return Arrays.asList(doBuild("")); - } - - /** - * Builds a list of multiple {@link MgmtSoftwareModuleTypeRequestBodyPost} - * to create multiple software module types at once. An increasing number - * will be added to the name and key of the software module type. - * - * @param count - * the amount of software module type bodies which should be - * created - * @return a list of {@link MgmtSoftwareModuleTypeRequestBodyPost} - */ - public List buildAsList(final int count) { - final List bodyList = new ArrayList<>(); - for (int index = 0; index < count; index++) { - bodyList.add(doBuild(String.valueOf(index))); - } - return bodyList; - } - - private MgmtSoftwareModuleTypeRequestBodyPost doBuild(final String suffix) { - final MgmtSoftwareModuleTypeRequestBodyPost body = new MgmtSoftwareModuleTypeRequestBodyPost(); - body.setKey(key + suffix); - body.setName(name + suffix); - body.setDescription(description); - body.setMaxAssignments(maxAssignments); - return body; - } - -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TagBuilder.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TagBuilder.java deleted file mode 100644 index 00213704a..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TagBuilder.java +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource.builder; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtTagRequestBodyPut; - -/** - * Builder pattern for building {@link MgmtTagRequestBodyPut}. - * - */ -// Exception squid:S1701 - builder pattern -@SuppressWarnings({ "squid:S1701" }) -public class TagBuilder { - - private String name; - private String description; - private String color; - - /** - * @param name - * the name of the tag - * @return the builder itself - */ - public TagBuilder name(final String name) { - this.name = name; - return this; - } - - /** - * @param description - * the description of the tag - * @return the builder itself - */ - public TagBuilder description(final String description) { - this.description = description; - return this; - } - - /** - * @param color - * the colour of the tag - * @return the builder itself - */ - public TagBuilder color(final String color) { - this.color = color; - return this; - } - - /** - * Builds a list with a single entry of {@link MgmtTagRequestBodyPut} which - * can directly be used in the RESTful-API. - * - * @return a single entry list of {@link MgmtTagRequestBodyPut} - */ - public List build() { - return Arrays.asList(doBuild(name)); - } - - /** - * Builds a list of multiple {@link MgmtTagRequestBodyPut} to create - * multiple tags at once. An increasing number will be added to the name of - * the tag. The color and description will remain the same. - * - * @param count - * the amount of distribution sets body which should be created - * @return a list of {@link MgmtTagRequestBodyPut} - */ - public List buildAsList(final int count) { - final List bodyList = new ArrayList<>(); - for (int index = 0; index < count; index++) { - bodyList.add(doBuild(name + index)); - } - - return bodyList; - } - - private MgmtTagRequestBodyPut doBuild(final String prefixName) { - final MgmtTagRequestBodyPut body = new MgmtTagRequestBodyPut(); - body.setName(prefixName); - body.setDescription(description); - body.setColour(color); - return body; - } - -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TargetBuilder.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TargetBuilder.java deleted file mode 100644 index ff637faf0..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TargetBuilder.java +++ /dev/null @@ -1,128 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource.builder; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleTypeRequestBodyPost; -import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTargetRequestBody; - -/** - * - * Builder pattern for building {@link MgmtTargetRequestBody}. - * - */ -// Exception squid:S1701 - builder pattern -@SuppressWarnings({ "squid:S1701" }) -public class TargetBuilder { - - private String controllerId; - private String name; - private String description; - private String address; - - /** - * @param controllerId - * the ID of the controller/target - * @return the builder itself - */ - public TargetBuilder controllerId(final String controllerId) { - this.controllerId = controllerId; - return this; - } - - /** - * @param name - * the name of the target - * @return the builder itself - */ - public TargetBuilder name(final String name) { - this.name = name; - return this; - } - - /** - * @param address - * the address of the target - * @return the builder itself - */ - public TargetBuilder address(final String address) { - this.address = address; - return this; - } - - /** - * @param description - * the description of the target - * @return the builder itself - */ - public TargetBuilder description(final String description) { - this.description = description; - return this; - } - - /** - * Builds a list with a single entry of {@link MgmtTargetRequestBody} which - * can directly be used in the RESTful-API. - * - * @return a single entry list of {@link MgmtTargetRequestBody} - */ - public List build() { - return Arrays.asList(doBuild("")); - } - - /** - * Builds a list of multiple {@link MgmtTargetRequestBody} to create - * multiple targets at once. An increasing number will be added to the - * controllerId and name of the target. The description will remain. - * - * @param count - * the amount of target bodies which should be created - * @return a list of {@link MgmtSoftwareModuleTypeRequestBodyPost} - */ - public List buildAsList(final int count) { - - return buildAsList(0, count); - } - - /** - * Builds a list of multiple {@link MgmtTargetRequestBody} to create - * multiple targets at once. An increasing number will be added to the - * controllerId and name of the target starting from the provided offset. - * The description will remain. - * - * @param count - * the amount of target bodies which should be created - * @param offset - * for for index start - * @return a list of {@link MgmtSoftwareModuleTypeRequestBodyPost} - */ - public List buildAsList(final int offset, final int count) { - final List bodyList = new ArrayList<>(); - for (int index = offset; index < count + offset; index++) { - bodyList.add(doBuild(String.format("%06d", index))); - } - return bodyList; - } - - private MgmtTargetRequestBody doBuild(final String suffix) { - final MgmtTargetRequestBody body = new MgmtTargetRequestBody(); - body.setControllerId(controllerId + suffix); - if (name == null) { - name = controllerId; - } - body.setName(name + suffix); - body.setDescription(description); - body.setAddress(address); - return body; - } - -} diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TargetFilterQueryBuilder.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TargetFilterQueryBuilder.java deleted file mode 100644 index ddda6dcac..000000000 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TargetFilterQueryBuilder.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.resource.builder; - -import org.eclipse.hawkbit.mgmt.json.model.targetfilter.MgmtTargetFilterQueryRequestBody; - -/** - * Builder pattern for building {@link MgmtTargetFilterQueryRequestBody}. - */ -// Exception squid:S1701 - builder pattern -@SuppressWarnings({ "squid:S1701" }) -public class TargetFilterQueryBuilder { - - private String name; - private String query; - - /** - * @param name - * the name of the filter - * @return the builder itself - */ - public TargetFilterQueryBuilder name(final String name) { - this.name = name; - return this; - } - - /** - * @param query - * the query filter - * @return the builder itself - */ - public TargetFilterQueryBuilder query(final String query) { - this.query = query; - return this; - } - - /** - * Builds a single entry of {@link MgmtTargetFilterQueryRequestBody} which - * can directly be used to post on the RESTful-API. - * - * @return a single entry of {@link MgmtTargetFilterQueryRequestBody} - */ - public MgmtTargetFilterQueryRequestBody build() { - final MgmtTargetFilterQueryRequestBody body = new MgmtTargetFilterQueryRequestBody(); - body.setName(name); - body.setQuery(query); - return body; - } -} diff --git a/examples/hawkbit-example-mgmt-simulator/.gitignore b/examples/hawkbit-example-mgmt-simulator/.gitignore deleted file mode 100644 index b5c3eb864..000000000 --- a/examples/hawkbit-example-mgmt-simulator/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/target/ -/bin/ -/.apt_generated/ -/.springBeans diff --git a/examples/hawkbit-example-mgmt-simulator/README.md b/examples/hawkbit-example-mgmt-simulator/README.md deleted file mode 100644 index e8003b5c8..000000000 --- a/examples/hawkbit-example-mgmt-simulator/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# Eclipse.IoT hawkBit - Example Management Feign Client - -Example Spring Boot client that shows how to efficiently use the hawkBit Example Management Feign Client and the hawkBit Management API. - -Powered by [Feign](https://github.com/Netflix/feign). - -## How to run the example client - -Run getting started example - - - - $ java -jar hawkbit-example-mgmt-simulator-#version#-exec.jar - - -Run create and start rollout example - - - $ java -jar hawkbit-example-mgmt-simulator-#version#-exec.jar --createrollout - - -## This example shows - -In getting started example: -* creating software modules type -* creating distribution set type -* creating distribution sets -* creating software modules -* assigning software modules to distribution sets - -In create rollout example: -* creating software modules type -* creating distribution set type -* creating distribution sets -* creating software modules -* assigning software modules to distribution sets -* creating a rollout -* starting a rollout diff --git a/examples/hawkbit-example-mgmt-simulator/pom.xml b/examples/hawkbit-example-mgmt-simulator/pom.xml deleted file mode 100644 index d7e7b38e9..000000000 --- a/examples/hawkbit-example-mgmt-simulator/pom.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - 4.0.0 - - org.eclipse.hawkbit - hawkbit-examples-parent - 0.2.0-SNAPSHOT - - jar - hawkbit-example-mgmt-simulator - hawkBit :: Examples :: Management feign client simulator - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - repackage - - - ${baseDir} - exec - false - org.eclipse.hawkbit.mgmt.client.Application - JAR - - - - - - - - - - org.eclipse.hawkbit - hawkbit-example-mgmt-feign-client - ${project.version} - - - org.springframework.boot - spring-boot-starter - - - org.springframework.cloud - spring-cloud-starter-feign - - - org.springframework.boot - spring-boot-starter-logging - - - \ No newline at end of file diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java deleted file mode 100644 index 1bdbbb136..000000000 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client; - -import org.eclipse.hawkbit.feign.core.client.FeignClientConfiguration; -import org.eclipse.hawkbit.feign.core.client.IgnoreMultipleConsumersProducersSpringMvcContract; -import org.eclipse.hawkbit.mgmt.client.resource.MgmtDistributionSetClientResource; -import org.eclipse.hawkbit.mgmt.client.resource.MgmtDistributionSetTagClientResource; -import org.eclipse.hawkbit.mgmt.client.resource.MgmtRolloutClientResource; -import org.eclipse.hawkbit.mgmt.client.resource.MgmtSoftwareModuleClientResource; -import org.eclipse.hawkbit.mgmt.client.resource.MgmtTargetClientResource; -import org.eclipse.hawkbit.mgmt.client.resource.MgmtTargetTagClientResource; -import org.eclipse.hawkbit.mgmt.client.scenarios.ConfigurableScenario; -import org.eclipse.hawkbit.mgmt.client.scenarios.upload.FeignMultipartEncoder; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.Banner.Mode; -import org.springframework.boot.CommandLineRunner; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.netflix.feign.EnableFeignClients; -import org.springframework.cloud.netflix.feign.support.ResponseEntityDecoder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Import; -import org.springframework.hateoas.hal.Jackson2HalModule; - -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; - -import feign.Feign; -import feign.Logger; -import feign.auth.BasicAuthRequestInterceptor; -import feign.jackson.JacksonDecoder; -import feign.slf4j.Slf4jLogger; - -@SpringBootApplication -@EnableFeignClients("org.eclipse.hawkbit.mgmt.client.resource") -@EnableConfigurationProperties(ClientConfigurationProperties.class) -@AutoConfigureAfter(FeignClientConfiguration.class) -@Import(FeignClientConfiguration.class) -public class Application implements CommandLineRunner { - - @Autowired - private ConfigurableScenario configuredScenario; - - public static void main(final String[] args) { - new SpringApplicationBuilder().bannerMode(Mode.OFF).sources(Application.class).run(args); - } - - @Override - public void run(final String... args) throws Exception { - if (containsArg("--createrollout", args)) { - // run the create and start rollout example - configuredScenario.runWithRollout(); - } else { - // run the configured scenario from properties - configuredScenario.run(); - } - } - - @Bean - public BasicAuthRequestInterceptor basicAuthRequestInterceptor(final ClientConfigurationProperties configuration) { - return new BasicAuthRequestInterceptor(configuration.getUsername(), configuration.getPassword()); - } - - @Bean - public ConfigurableScenario configurableScenario(final MgmtDistributionSetClientResource distributionSetResource, - final MgmtSoftwareModuleClientResource softwareModuleResource, - final MgmtTargetClientResource targetResource, final MgmtRolloutClientResource rolloutResource, - final MgmtTargetTagClientResource targetTagResource, - final MgmtDistributionSetTagClientResource distributionSetTagResource, - final ClientConfigurationProperties clientConfigurationProperties) { - return new ConfigurableScenario(distributionSetResource, softwareModuleResource, - uploadSoftwareModule(clientConfigurationProperties), targetResource, rolloutResource, targetTagResource, - distributionSetTagResource, clientConfigurationProperties); - } - - private static MgmtSoftwareModuleClientResource uploadSoftwareModule( - final ClientConfigurationProperties configuration) { - final ObjectMapper mapper = new ObjectMapper() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .registerModule(new Jackson2HalModule()); - return Feign.builder().contract(new IgnoreMultipleConsumersProducersSpringMvcContract()).decode404() - .requestInterceptor( - new BasicAuthRequestInterceptor(configuration.getUsername(), configuration.getPassword())) - .logger(new Slf4jLogger()).encoder(new FeignMultipartEncoder()) - .decoder(new ResponseEntityDecoder(new JacksonDecoder(mapper))) - .target(MgmtSoftwareModuleClientResource.class, configuration.getUrl()); - } - - @Bean - public Logger.Level feignLoggerLevel() { - return Logger.Level.FULL; - } - - private static boolean containsArg(final String containsArg, final String... args) { - for (final String arg : args) { - if (arg.equalsIgnoreCase(containsArg)) { - return true; - } - } - return false; - } -} diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java deleted file mode 100644 index aff70ba85..000000000 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java +++ /dev/null @@ -1,266 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.springframework.boot.context.properties.ConfigurationProperties; - -/** - * Configuration bean which holds the configuration of the client e.g. the base - * URL of the hawkbit-server and the credentials to use the RESTful Management - * API. - */ -@ConfigurationProperties(prefix = "hawkbit") -public class ClientConfigurationProperties { - - /** - * Update server URI. - */ - private String url = "localhost:8080"; - - /** - * Update server user name. - */ - private String username = "admin"; - - /** - * Update server password. - */ - private String password = "admin"; // NOSONAR this password is only used for - // examples - - private final List scenarios = new ArrayList<>(); - - /** - * Simulation {@link Scenario}. - * - */ - public static class Scenario { - private boolean cleanRepository; - private boolean waitTillRolloutComplete = true; - private int targets = 100; - private int distributionSets = 10; - private int appModulesPerDistributionSet = 2; - private String dsName = "Package"; - private String smSwName = "Application"; - private String smFwName = "Firmware"; - private String targetName = "Device"; - private int artifactsPerSM = 1; - private String targetAddress = "amqp:/simulator.replyTo"; - private boolean runRollouts = true; - private boolean runSemiAutomaticRollouts = true; - private short rolloutSuccessThreshold = 80; - private int rolloutDeploymentGroups = 4; - private List deviceGroups = Arrays.asList("EU", "AM", "APAC"); - - /** - * Targets tags per page. - */ - private int targetTags; - - /** - * Distribution Set tags per set - */ - private int dsTags = 5; - - /** - * Artifact size. Values can use the suffixed "MB" or "KB" to indicate a - * Megabyte or Kilobyte size. - */ - private String artifactSize = "1MB"; - - public boolean isRunSemiAutomaticRollouts() { - return runSemiAutomaticRollouts; - } - - public void setRunSemiAutomaticRollouts(final boolean runSemiAutomaticRollouts) { - this.runSemiAutomaticRollouts = runSemiAutomaticRollouts; - } - - public List getDeviceGroups() { - return deviceGroups; - } - - public void setDeviceGroups(final List deviceGroups) { - this.deviceGroups = deviceGroups; - } - - public boolean isCleanRepository() { - return cleanRepository; - } - - public void setCleanRepository(final boolean cleanRepository) { - this.cleanRepository = cleanRepository; - } - - public boolean isWaitTillRolloutComplete() { - return waitTillRolloutComplete; - } - - public void setWaitTillRolloutComplete(final boolean waitTillRolloutComplete) { - this.waitTillRolloutComplete = waitTillRolloutComplete; - } - - public int getRolloutDeploymentGroups() { - return rolloutDeploymentGroups; - } - - public void setRolloutDeploymentGroups(final int rolloutDeploymentGroups) { - this.rolloutDeploymentGroups = rolloutDeploymentGroups; - } - - public boolean isRunRollouts() { - return runRollouts; - } - - public void setRunRollouts(final boolean runRollouts) { - this.runRollouts = runRollouts; - } - - public String getTargetAddress() { - return targetAddress; - } - - public void setTargetAddress(final String targetAddress) { - this.targetAddress = targetAddress; - } - - public int getArtifactsPerSM() { - return artifactsPerSM; - } - - public void setArtifactsPerSM(final int artifactsPerSM) { - this.artifactsPerSM = artifactsPerSM; - } - - public String getArtifactSize() { - return artifactSize; - } - - public void setArtifactSize(final String artifactSize) { - this.artifactSize = artifactSize; - } - - public String getTargetName() { - return targetName; - } - - public void setTargetName(final String targetName) { - this.targetName = targetName; - } - - public String getDsName() { - return dsName; - } - - public void setDsName(final String dsName) { - this.dsName = dsName; - } - - public String getSmSwName() { - return smSwName; - } - - public void setSmSwName(final String smSwName) { - this.smSwName = smSwName; - } - - public String getSmFwName() { - return smFwName; - } - - public void setSmFwName(final String smFwName) { - this.smFwName = smFwName; - } - - public int getTargets() { - return targets; - } - - public int getDistributionSets() { - return distributionSets; - } - - public int getAppModulesPerDistributionSet() { - return appModulesPerDistributionSet; - } - - public void setTargets(final int targets) { - this.targets = targets; - } - - public void setDistributionSets(final int distributionSets) { - this.distributionSets = distributionSets; - } - - public void setAppModulesPerDistributionSet(final int appModulesPerDistributionSet) { - this.appModulesPerDistributionSet = appModulesPerDistributionSet; - } - - public void setTargetTags(final int targetTags) { - this.targetTags = targetTags; - } - - public int getTargetTags() { - return targetTags; - } - - public int getDsTags() { - return dsTags; - } - - public void setDsTags(final int dsTags) { - this.dsTags = dsTags; - } - - public short getRolloutSuccessThreshold() { - return rolloutSuccessThreshold; - } - - public void setRolloutSuccessThreshold(final short rolloutSuccessThreshold) { - this.rolloutSuccessThreshold = rolloutSuccessThreshold; - } - - } - - public List getScenarios() { - return scenarios; - } - - public void addScenarios(final Scenario scenario) { - scenarios.add(scenario); - } - - public String getUrl() { - return url; - } - - public void setUrl(final String url) { - this.url = url; - } - - public String getUsername() { - return username; - } - - public void setUsername(final String username) { - this.username = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(final String password) { - this.password = password; - } -} diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java deleted file mode 100644 index 3e9299d19..000000000 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java +++ /dev/null @@ -1,497 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.scenarios; - -import java.math.BigDecimal; -import java.security.SecureRandom; -import java.util.List; -import java.util.Random; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import org.eclipse.hawkbit.mgmt.client.ClientConfigurationProperties; -import org.eclipse.hawkbit.mgmt.client.ClientConfigurationProperties.Scenario; -import org.eclipse.hawkbit.mgmt.client.resource.MgmtDistributionSetClientResource; -import org.eclipse.hawkbit.mgmt.client.resource.MgmtDistributionSetTagClientResource; -import org.eclipse.hawkbit.mgmt.client.resource.MgmtRolloutClientResource; -import org.eclipse.hawkbit.mgmt.client.resource.MgmtSoftwareModuleClientResource; -import org.eclipse.hawkbit.mgmt.client.resource.MgmtTargetClientResource; -import org.eclipse.hawkbit.mgmt.client.resource.MgmtTargetTagClientResource; -import org.eclipse.hawkbit.mgmt.client.resource.builder.DistributionSetBuilder; -import org.eclipse.hawkbit.mgmt.client.resource.builder.RolloutBuilder; -import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleAssigmentBuilder; -import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleBuilder; -import org.eclipse.hawkbit.mgmt.client.resource.builder.TagBuilder; -import org.eclipse.hawkbit.mgmt.client.resource.builder.TargetBuilder; -import org.eclipse.hawkbit.mgmt.client.scenarios.upload.ArtifactFile; -import org.eclipse.hawkbit.mgmt.json.model.PagedList; -import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSet; -import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutResponseBody; -import org.eclipse.hawkbit.mgmt.json.model.rolloutgroup.MgmtRolloutGroup; -import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule; -import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtAssignedDistributionSetRequestBody; -import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtAssignedTargetRequestBody; -import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtTag; -import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTarget; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.HttpStatus; - -import com.google.common.collect.Lists; - -/** - * - * A configurable scenario which runs the configured scenarios. - * - * @see {@link ClientConfigurationProperties#getScenarios()} - * - */ -public class ConfigurableScenario { - - private static final int PAGE_SIZE = 500; - - private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurableScenario.class); - - private final MgmtDistributionSetClientResource distributionSetResource; - - private final MgmtSoftwareModuleClientResource softwareModuleResource; - - private final MgmtTargetClientResource targetResource; - - private final MgmtTargetTagClientResource targetTagResource; - - private final MgmtDistributionSetTagClientResource distributionSetTagResource; - - private final MgmtRolloutClientResource rolloutResource; - - private final ClientConfigurationProperties clientConfigurationProperties; - - private final MgmtSoftwareModuleClientResource uploadSoftwareModule; - - public ConfigurableScenario(final MgmtDistributionSetClientResource distributionSetResource, - final MgmtSoftwareModuleClientResource softwareModuleResource, - final MgmtSoftwareModuleClientResource uploadSoftwareModule, final MgmtTargetClientResource targetResource, - final MgmtRolloutClientResource rolloutResource, final MgmtTargetTagClientResource targetTagResource, - final MgmtDistributionSetTagClientResource distributionSetTagResource, - final ClientConfigurationProperties clientConfigurationProperties) { - this.targetTagResource = targetTagResource; - this.distributionSetResource = distributionSetResource; - this.softwareModuleResource = softwareModuleResource; - this.uploadSoftwareModule = uploadSoftwareModule; - this.targetResource = targetResource; - this.rolloutResource = rolloutResource; - this.distributionSetTagResource = distributionSetTagResource; - this.clientConfigurationProperties = clientConfigurationProperties; - } - - /** - * Run the default getting started scenario. - */ - public void run() { - - LOGGER.info("Running Configurable Scenario..."); - - clientConfigurationProperties.getScenarios().forEach(this::createScenario); - } - - /** - * Run the default getting started scenario including rollout - */ - public void runWithRollout() { - - LOGGER.info("Running Configurable Scenario..."); - - clientConfigurationProperties.getScenarios().forEach(scenario -> { - scenario.setRunRollouts(true); - createScenario(scenario); - }); - } - - private void createScenario(final Scenario scenario) { - if (scenario.isCleanRepository()) { - cleanRepository(); - } - - final List deviceGroupTags = createDeviceGroupTags(scenario.getDeviceGroups()); - createTargets(scenario, deviceGroupTags); - createDistributionSets(scenario); - - if (scenario.isRunRollouts()) { - runRollouts(scenario); - } - - if (scenario.isRunSemiAutomaticRollouts() && !scenario.getDeviceGroups().isEmpty()) { - runSemiAutomaticRollouts(scenario); - } - } - - private List createDeviceGroupTags(final List deviceGroups) { - return deviceGroups.stream() - .map(group -> targetTagResource - .createTargetTags(new TagBuilder().name(group).description("Group " + group).build()).getBody() - .get(0).getTagId()) - .collect(Collectors.toList()); - } - - private void cleanRepository() { - LOGGER.info("Cleaning repository"); - deleteTargets(); - deleteRollouts(); - deleteDistributionSets(); - deleteSoftwareModules(); - LOGGER.info("Cleaning repository -> Done"); - } - - private void deleteRollouts() { - LOGGER.info("Delete Rollouts"); - - PagedList rollouts; - - while ((rollouts = rolloutResource.getRollouts(0, PAGE_SIZE, null, null).getBody()).getTotal() > 0) { - rollouts.getContent().parallelStream().forEach(rollout -> { - rolloutResource.delete(rollout.getRolloutId()); - waitUntilRolloutNoLongerExists(rollout.getRolloutId()); - }); - } - } - - private void deleteSoftwareModules() { - LOGGER.info("Delete SoftwareModules"); - PagedList modules; - do { - modules = softwareModuleResource.getSoftwareModules(0, PAGE_SIZE, null, null).getBody(); - modules.getContent().parallelStream() - .forEach(module -> softwareModuleResource.deleteSoftwareModule(module.getModuleId())); - } while (modules.getTotal() > PAGE_SIZE); - } - - private void deleteDistributionSets() { - LOGGER.info("Delete DistributionSets"); - - PagedList distributionSets; - do { - distributionSets = distributionSetResource.getDistributionSets(0, PAGE_SIZE, null, null).getBody(); - distributionSets.getContent().parallelStream() - .forEach(set -> distributionSetResource.deleteDistributionSet(set.getDsId())); - } while (distributionSets.getTotal() > PAGE_SIZE); - - deleteDistributionSetTags(); - } - - private void deleteDistributionSetTags() { - PagedList dsTags; - do { - dsTags = distributionSetTagResource.getDistributionSetTags(0, PAGE_SIZE, null, null).getBody(); - dsTags.getContent().parallelStream() - .forEach(ds -> distributionSetTagResource.deleteDistributionSetTag(ds.getTagId())); - } while (dsTags.getTotal() > PAGE_SIZE); - } - - private void deleteTargets() { - LOGGER.info("Delete Targets"); - - PagedList targets; - do { - targets = targetResource.getTargets(0, PAGE_SIZE, null, null).getBody(); - targets.getContent().parallelStream() - .forEach(target -> targetResource.deleteTarget(target.getControllerId())); - } while (targets.getTotal() > PAGE_SIZE); - - deleteTargetTags(); - } - - private void deleteTargetTags() { - PagedList targetTags; - do { - targetTags = targetTagResource.getTargetTags(0, PAGE_SIZE, null, null).getBody(); - targetTags.getContent().parallelStream() - .forEach(target -> targetTagResource.deleteTargetTag(target.getTagId())); - } while (targetTags.getTotal() > PAGE_SIZE); - } - - private void runRollouts(final Scenario scenario) { - if (scenario.getDistributionSets() <= 0) { - return; - } - - distributionSetResource.getDistributionSets(0, scenario.getDistributionSets(), null, null).getBody() - .getContent().forEach(set -> runRollout(set, scenario)); - } - - private void runSemiAutomaticRollouts(final Scenario scenario) { - if (scenario.getDistributionSets() <= 0) { - return; - } - - distributionSetResource.getDistributionSets(0, scenario.getDistributionSets(), null, null).getBody() - .getContent().forEach(set -> runSemiAutomaticRollout(set, scenario)); - } - - private void runSemiAutomaticRollout(final MgmtDistributionSet set, final Scenario scenario) { - LOGGER.info("Run semi automatic rollout for set {}", set.getDsId()); - // create a Rollout - final MgmtRolloutResponseBody rolloutResponseBody = rolloutResource.create(new RolloutBuilder() - .name("SemiAutomaticRollout" + set.getName() + set.getVersion()) - .semiAutomaticGroups(createRolloutGroups(scenario)).targetFilterQuery("name==*") - .distributionSetId(set.getDsId()) - .successThreshold(String.valueOf(scenario.getRolloutSuccessThreshold())).errorThreshold("5").build()) - .getBody(); - - waitUntilRolloutIsReady(rolloutResponseBody.getRolloutId()); - - // start the created Rollout - rolloutResource.start(rolloutResponseBody.getRolloutId()); - - waitUntilRolloutIsComplete(rolloutResponseBody.getRolloutId()); - LOGGER.info("Run rollout for set {} -> Done", set.getDsId()); - } - - private static List createRolloutGroups(final Scenario scenario) { - final List result = Lists - .newArrayListWithExpectedSize((scenario.getDeviceGroups().size() * 3) + 1); - - scenario.getDeviceGroups().forEach(groupname -> { - result.add(createGroup(1, groupname, 10F)); - result.add(createGroup(2, groupname, 50F)); - result.add(createGroup(3, groupname, 100F)); - }); - result.add(createFinalGroup()); - - return result; - } - - private static MgmtRolloutGroup createGroup(final int number, final String groupname, final Float percent) { - final MgmtRolloutGroup one = new MgmtRolloutGroup(); - one.setName(groupname + "-" + number); - one.setDescription("Group of " + groupname); - one.setTargetFilterQuery("tag==" + groupname); - one.setTargetPercentage(percent); - return one; - } - - private static MgmtRolloutGroup createFinalGroup() { - final MgmtRolloutGroup one = new MgmtRolloutGroup(); - one.setName("final"); - one.setDescription("Group of non tagged devices"); - one.setTargetFilterQuery("name==*"); - one.setTargetPercentage(100F); - return one; - } - - private void runRollout(final MgmtDistributionSet set, final Scenario scenario) { - LOGGER.info("Run rollout for set {}", set.getDsId()); - // create a Rollout - final MgmtRolloutResponseBody rolloutResponseBody = rolloutResource.create(new RolloutBuilder() - .name("Rollout" + set.getName() + set.getVersion()).groupSize(scenario.getRolloutDeploymentGroups()) - .targetFilterQuery("name==*").distributionSetId(set.getDsId()) - .successThreshold(String.valueOf(scenario.getRolloutSuccessThreshold())).errorThreshold("5").build()) - .getBody(); - - waitUntilRolloutIsReady(rolloutResponseBody.getRolloutId()); - - // start the created Rollout - rolloutResource.start(rolloutResponseBody.getRolloutId()); - - if (scenario.isWaitTillRolloutComplete()) { - waitUntilRolloutIsComplete(rolloutResponseBody.getRolloutId()); - } - LOGGER.info("Run rollout for set {} -> Done", set.getDsId()); - } - - private void waitUntilRolloutNoLongerExists(final Long id) { - - do { - try { - TimeUnit.SECONDS.sleep(5); - } catch (final InterruptedException e) { - LOGGER.warn("Interrupted!"); - Thread.currentThread().interrupt(); - } - } while (rolloutResource.getRollout(id).getStatusCode() != HttpStatus.NOT_FOUND); - } - - private void waitUntilRolloutIsComplete(final Long id) { - do { - try { - TimeUnit.SECONDS.sleep(5); - } catch (final InterruptedException e) { - LOGGER.warn("Interrupted!"); - Thread.currentThread().interrupt(); - } - } while (!"FINISHED".equalsIgnoreCase(rolloutResource.getRollout(id).getBody().getStatus())); - } - - private void waitUntilRolloutIsReady(final Long id) { - do { - try { - TimeUnit.SECONDS.sleep(5); - } catch (final InterruptedException e) { - LOGGER.warn("Interrupted!"); - Thread.currentThread().interrupt(); - } - } while (!"READY".equalsIgnoreCase(rolloutResource.getRollout(id).getBody().getStatus())); - } - - private void createDistributionSets(final Scenario scenario) { - if (scenario.getDistributionSets() <= 0) { - return; - } - - LOGGER.info("Creating {} distribution sets", scenario.getDistributionSets()); - final BigDecimal pages = new BigDecimal(scenario.getDistributionSets()) - .divide(new BigDecimal(PAGE_SIZE), BigDecimal.ROUND_UP).max(new BigDecimal(1)); - - IntStream.range(0, pages.intValue()).parallel().forEach(i -> createDistributionSetPage(scenario, i)); - LOGGER.info("Creating {} distribution sets -> Done", scenario.getDistributionSets()); - } - - private void createDistributionSetPage(final Scenario scenario, final int page) { - - final List sets = distributionSetResource - .createDistributionSets(new DistributionSetBuilder().name(scenario.getDsName()).type("os_app") - .version("1.0.").buildAsList(calculateOffset(page), - (page + 1) * PAGE_SIZE > scenario.getDistributionSets() - ? (scenario.getDistributionSets() - calculateOffset(page)) : PAGE_SIZE)) - .getBody(); - - assignSoftwareModulesTo(scenario, sets); - - tagDistributionSets(page, sets); - - } - - private void tagDistributionSets(final int page, final List sets) { - final MgmtTag tag = distributionSetTagResource - .createDistributionSetTags( - new TagBuilder().name("Page " + page).description("DS tag for DS page" + page).build()) - .getBody().get(0); - - distributionSetTagResource.assignDistributionSets(tag.getTagId(), - sets.stream() - .map(set -> new MgmtAssignedDistributionSetRequestBody().setDistributionSetId(set.getDsId())) - .collect(Collectors.toList())); - } - - private void assignSoftwareModulesTo(final Scenario scenario, final List sets) { - final byte[] artifact = generateArtifact(scenario); - sets.forEach(dsSet -> { - final List modules = addModules(scenario, dsSet, artifact); - - final SoftwareModuleAssigmentBuilder assign = new SoftwareModuleAssigmentBuilder(); - modules.forEach(module -> assign.id(module.getModuleId())); - distributionSetResource.assignSoftwareModules(dsSet.getDsId(), assign.build()); - }); - } - - private List addModules(final Scenario scenario, final MgmtDistributionSet dsSet, - final byte[] artifact) { - final List modules = softwareModuleResource - .createSoftwareModules(new SoftwareModuleBuilder().name(scenario.getSmFwName() + "-os") - .version(dsSet.getVersion()).type("os").build()) - .getBody(); - modules.addAll(softwareModuleResource.createSoftwareModules( - new SoftwareModuleBuilder().name(scenario.getSmSwName() + "-app").version(dsSet.getVersion() + ".") - .type("application").buildAsList(scenario.getAppModulesPerDistributionSet())) - .getBody()); - - for (int iArtifact = 0; iArtifact < scenario.getArtifactsPerSM(); iArtifact++) { - final int count = iArtifact; - modules.forEach(module -> { - final ArtifactFile file = new ArtifactFile("dummyfile.dummy" + count, null, "multipart/form-data", - artifact); - uploadSoftwareModule.uploadArtifact(module.getModuleId(), file, null, null, null); - }); - } - - return modules; - } - - private void createTargets(final Scenario scenario, final List deviceGroupTags) { - if (scenario.getTargets() <= 0) { - return; - } - - LOGGER.info("Creating {} targets", scenario.getTargets()); - final BigDecimal pages = new BigDecimal(scenario.getTargets()) - .divide(new BigDecimal(PAGE_SIZE), BigDecimal.ROUND_UP).max(new BigDecimal(1)); - - IntStream.range(0, pages.intValue()).parallel().forEach(i -> createTargetPage(scenario, i, deviceGroupTags)); - LOGGER.info("Creating {} targets -> Done", scenario.getTargets()); - } - - private void createTargetPage(final Scenario scenario, final int page, final List deviceGroupTags) { - final List targets = createTargets(scenario, page); - - tagTargets(scenario, page, targets, deviceGroupTags); - - } - - private List createTargets(final Scenario scenario, final int page) { - return targetResource - .createTargets( - new TargetBuilder().controllerId(scenario.getTargetName()).address(scenario.getTargetAddress()) - .buildAsList(calculateOffset(page), - (page + 1) * PAGE_SIZE > scenario.getTargets() - ? (scenario.getTargets() - calculateOffset(page)) : PAGE_SIZE)) - .getBody(); - } - - private void tagTargets(final Scenario scenario, final int page, final List targets, - final List deviceGroupTags) { - if (scenario.getTargetTags() > 0) { - targetTagResource - .createTargetTags(new TagBuilder().name("Page " + page) - .description("Target tag for target page " + page).buildAsList(scenario.getTargetTags())) - .getBody() - .forEach(tag -> targetTagResource.assignTargets(tag.getTagId(), targets.stream().map( - target -> new MgmtAssignedTargetRequestBody().setControllerId(target.getControllerId())) - .collect(Collectors.toList()))); - } - - if (!deviceGroupTags.isEmpty()) { - final Long tagid = deviceGroupTags.get(new SecureRandom().nextInt(deviceGroupTags.size())); - - targetTagResource.assignTargets(tagid, - targets.stream().map( - target -> new MgmtAssignedTargetRequestBody().setControllerId(target.getControllerId())) - .collect(Collectors.toList())); - } - } - - private static int calculateOffset(final int page) { - return page * PAGE_SIZE; - } - - private static int parseSize(final String s) { - final String size = s.toUpperCase(); - if (size.endsWith("KB")) { - return Integer.valueOf(size.substring(0, size.length() - 2)) * 1024; - } - if (size.endsWith("MB")) { - return Integer.valueOf(size.substring(0, size.length() - 2)) * 1024 * 1024; - } - return Integer.valueOf(size); - } - - private static byte[] generateArtifact(final Scenario scenario) { - - // Exception squid:S2245 - not used for cryptographic function - @SuppressWarnings("squid:S2245") - final Random random = new Random(); - - // create byte array - final byte[] nbyte = new byte[parseSize(scenario.getArtifactSize())]; - - // put the next byte in the array - random.nextBytes(nbyte); - - return nbyte; - } -} diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/ArtifactFile.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/ArtifactFile.java deleted file mode 100644 index 379455580..000000000 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/ArtifactFile.java +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.scenarios.upload; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.Optional; - -import org.springframework.util.Assert; -import org.springframework.util.FileCopyUtils; -import org.springframework.web.multipart.MultipartFile; - -/** - * Implementation for {@link MultipartFile} for hawkBit artifact upload. - * - */ -public class ArtifactFile implements MultipartFile { - - private final String name; - - private final String originalFilename; - - private final String contentType; - - private final byte[] content; - - /** - * Create a new ArtifactFile with the given content. - * - * @param name - * the name of the file - * @param content - * the content of the file - */ - public ArtifactFile(final String name, final byte[] content) { - this(name, "", null, content); - } - - /** - * Create a new ArtifactFile with the given content. - * - * @param name - * of the file - * @param originalFilename - * the original filename (as on the client's machine) - * @param contentType - * the content type - * @param content - * of the file - */ - public ArtifactFile(final String name, final String originalFilename, final String contentType, - final byte[] content) { - Assert.hasLength(name, "Name must not be null"); - this.name = name; - this.originalFilename = Optional.ofNullable(originalFilename).orElse(""); - this.contentType = contentType; - this.content = Optional.ofNullable(content).orElse(new byte[0]); - } - - @Override - public String getName() { - return this.name; - } - - @Override - public String getOriginalFilename() { - return this.originalFilename; - } - - @Override - public String getContentType() { - return this.contentType; - } - - @Override - public boolean isEmpty() { - return this.content.length == 0; - } - - @Override - public long getSize() { - return this.content.length; - } - - @Override - public byte[] getBytes() throws IOException { - return this.content; - } - - @Override - public InputStream getInputStream() throws IOException { - return new ByteArrayInputStream(this.content); - } - - @Override - public void transferTo(final File dest) throws IOException { - FileCopyUtils.copy(this.content, dest); - } - -} diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/FeignMultipartEncoder.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/FeignMultipartEncoder.java deleted file mode 100644 index 5d1e43e96..000000000 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/FeignMultipartEncoder.java +++ /dev/null @@ -1,155 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.mgmt.client.scenarios.upload; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.reflect.Type; -import java.nio.charset.Charset; -import java.util.List; -import java.util.Map.Entry; - -import org.springframework.core.io.InputStreamResource; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpOutputMessage; -import org.springframework.http.MediaType; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; -import org.springframework.web.multipart.MultipartFile; - -import feign.RequestTemplate; -import feign.codec.EncodeException; -import feign.codec.Encoder; - -/** - * A feign encoder implementation which handles {@link MultipartFile} body. - */ -public class FeignMultipartEncoder implements Encoder { - - private final List> converters = new RestTemplate().getMessageConverters(); - private final HttpHeaders multipartHeaders = new HttpHeaders(); - private final HttpHeaders jsonHeaders = new HttpHeaders(); - - private static final Charset UTF_8 = Charset.forName("UTF-8"); - - public FeignMultipartEncoder() { - multipartHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); - jsonHeaders.setContentType(MediaType.APPLICATION_JSON); - } - - @Override - public void encode(final Object object, final Type bodyType, final RequestTemplate template) { - encodeMultipartFormRequest(object, template); - } - - private void encodeMultipartFormRequest(final Object value, final RequestTemplate template) { - if (value == null) { - throw new EncodeException("Cannot encode request with null value."); - } - if (!isMultipartFile(value)) { - throw new EncodeException("Only multipart can be handled by this encoder"); - } - encodeRequest(encodeMultipartFile((MultipartFile) value), multipartHeaders, template); - } - - @SuppressWarnings("unchecked") - private void encodeRequest(final Object value, final HttpHeaders requestHeaders, final RequestTemplate template) { - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - final HttpOutputMessage dummyRequest = new HttpOutputMessageImpl(outputStream, requestHeaders); - try { - final Class requestType = value.getClass(); - final MediaType requestContentType = requestHeaders.getContentType(); - for (final HttpMessageConverter messageConverter : converters) { - if (messageConverter.canWrite(requestType, requestContentType)) { - ((HttpMessageConverter) messageConverter).write(value, requestContentType, dummyRequest); - break; - } - } - } catch (final IOException ex) { - throw new EncodeException("Cannot encode request.", ex); - } - final HttpHeaders headers = dummyRequest.getHeaders(); - if (headers != null) { - for (final Entry> entry : headers.entrySet()) { - template.header(entry.getKey(), entry.getValue()); - } - } - /* - * we should use a template output stream... this will cause issues if - * files are too big, since the whole request will be in memory. - */ - template.body(outputStream.toByteArray(), UTF_8); - } - - private MultiValueMap encodeMultipartFile(final MultipartFile file) { - try { - final MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); - multiValueMap.add("file", new MultipartFileResource(file.getName(), file.getSize(), file.getInputStream())); - return multiValueMap; - } catch (final IOException ex) { - throw new EncodeException("Cannot encode request.", ex); - } - } - - private static boolean isMultipartFile(final Object object) { - return object instanceof MultipartFile; - } - - private static final class HttpOutputMessageImpl implements HttpOutputMessage { - - private final OutputStream body; - private final HttpHeaders headers; - - private HttpOutputMessageImpl(final OutputStream body, final HttpHeaders headers) { - this.body = body; - this.headers = headers; - } - - @Override - public OutputStream getBody() throws IOException { - return body; - } - - @Override - public HttpHeaders getHeaders() { - return headers; - } - - } - - /** - * Dummy resource class. Wraps file content and its original name. - */ - static class MultipartFileResource extends InputStreamResource { - - private final String filename; - private final long size; - - public MultipartFileResource(final String filename, final long size, final InputStream inputStream) { - super(inputStream); - this.size = size; - this.filename = filename; - } - - @Override - public String getFilename() { - return this.filename; - } - - @Override - public long contentLength() throws IOException { - return size; - } - - } -} diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties b/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties deleted file mode 100644 index e61334255..000000000 --- a/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties +++ /dev/null @@ -1,26 +0,0 @@ -# -# Copyright (c) 2015 Bosch Software Innovations GmbH and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://www.eclipse.org/legal/epl-v10.html -# - -hawkbit.url=http://localhost:8080 -hawkbit.username=admin -hawkbit.password=admin - -spring.main.banner-mode=off - -feign.hystrix.enabled=false - -hawkbit.scenarios.[0].cleanRepository=false -hawkbit.scenarios.[0].targets=0 -hawkbit.scenarios.[0].ds-name=gettingstarted-example -hawkbit.scenarios.[0].distribution-sets=3 -hawkbit.scenarios.[0].sm-fw-name=gettingstarted-example -hawkbit.scenarios.[0].sm-sw-name=gettingstarted-example -hawkbit.scenarios.[0].runRollouts=false -hawkbit.scenarios.[0].runSemiAutomaticRollouts=false -hawkbit.scenarios.[0].artifactsPerSM=0 diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/resources/logback-spring.xml b/examples/hawkbit-example-mgmt-simulator/src/main/resources/logback-spring.xml deleted file mode 100644 index 0eab7ae31..000000000 --- a/examples/hawkbit-example-mgmt-simulator/src/main/resources/logback-spring.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/examples/pom.xml b/examples/pom.xml deleted file mode 100644 index 25c22c9fc..000000000 --- a/examples/pom.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - 4.0.0 - - - org.eclipse.hawkbit - hawkbit-parent - 0.2.0-SNAPSHOT - - - hawkbit-examples-parent - hawkBit :: Examples - pom - - - - eclipserel - hawkBit Repository - Release - https://repo.eclipse.org/content/repositories/hawkbit-releases - - - eclipsesnap - hawkBit Repository - Snapshots - https://repo.eclipse.org/content/repositories/hawkbit-snapshots - - - - - hawkbit-device-simulator - hawkbit-example-core-feign-client - hawkbit-example-ddi-feign-client - hawkbit-example-mgmt-feign-client - hawkbit-example-mgmt-simulator - - - - 9.3.1 - - - - - - io.github.openfeign - feign-jackson - ${feign.extension.version} - - - io.github.openfeign - feign-gson - ${feign.extension.version} - - - io.github.openfeign - feign-jaxrs - ${feign.extension.version} - - - com.vaadin - vaadin-spring-boot-starter - ${vaadin.spring.version} - - - - diff --git a/extensions/README.md b/extensions/README.md deleted file mode 100644 index 5613013c4..000000000 --- a/extensions/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# hawkBit Extensions - -hawkBit extensions are implementations to extend the functionality of hawkBit which are maintained by the hawkBit community. The extensions can be used to integrate in a hawkBit application to exchange or extend hawkBit functionality. Extensions should work with the hawkBit example application. All extensions provide a `README.md` which explains the use of the extension and how to use them. - -hawkBit extensions are implementations which are not included in the default implementation of hawkBit's security and auto-configuration mechanism or extending functionality by e.g. integrating third-party services to hawkBit. - -hawkBit makes use of the spring-bean and configuration mechanism which allows an flexible configuration and the exchange of beans in spring-configurations. Many beans are `@Conditional` annotated in hawkBit so they can be overwritten. Extensions can also leverage and implemented functionalities based on hawkBit's event mechanism by subscribing to events and implement additional functionality. - -### hawkBit Extension follows -* Containing a `README.md` which explains the extension in detail and how to use it -* Working with the hawkBit example application -* Following the maven-artifact-id `hawkbit-extension-` diff --git a/extensions/hawkbit-extension-artifact-repository-mongo/README.md b/extensions/hawkbit-extension-artifact-repository-mongo/README.md deleted file mode 100644 index fcae911d5..000000000 --- a/extensions/hawkbit-extension-artifact-repository-mongo/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Eclipse.IoT hawkBit - Artifact Repository MongoDB -HawkBit Artifact Repository is a library for storing binary artifacts and metadata into MongoDB. - - -## Using Artifact Repository MongoDB Extension -The module contains a spring-boot autoconfiguration for easily integration into spring-boot projects. -For using this extension in the hawkbit-example-application you just need to add the maven dependency. -``` - - org.eclipse.hawkbit - hawkbit-extension-artifact-repository-mongo - ${project.version} - -``` - -If you do not have a mongoDB running you can use the the flapdoodle project to download and start a mongoDB on demand -``` - - de.flapdoodle.embed - de.flapdoodle.embed.mongo - ${flapdoodle.version} - -``` - -Maven test execution of this module is backed by flapdoodle. In case you don't have a mongoDB and run behind a proxy you may set the `JAVA_TOOL_OPTIONS` as global environment variable with your proxy settings. So flapdoodle is able to download the mongoDB dependency. diff --git a/extensions/hawkbit-extension-artifact-repository-mongo/pom.xml b/extensions/hawkbit-extension-artifact-repository-mongo/pom.xml deleted file mode 100644 index e796a0d24..000000000 --- a/extensions/hawkbit-extension-artifact-repository-mongo/pom.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - 4.0.0 - - org.eclipse.hawkbit - 0.2.0-SNAPSHOT - hawkbit-extensions-parent - - hawkbit-extension-artifact-repository-mongo - hawkBit :: Extensions :: Artifact Repository Mongo - - - - - org.eclipse.hawkbit - hawkbit-core - ${project.version} - - - org.springframework.data - spring-data-mongodb - - - org.springframework - spring-context - - - org.springframework.boot - spring-boot-autoconfigure - - - com.google.guava - guava - - - - - org.springframework.boot - spring-boot-starter-test - test - - - ru.yandex.qatools.allure - allure-junit-adaptor - test - - - org.springframework.boot - spring-boot-starter-logging - test - - - - de.flapdoodle.embed - de.flapdoodle.embed.mongo - test - - - - \ No newline at end of file diff --git a/extensions/hawkbit-extension-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/GridFsArtifact.java b/extensions/hawkbit-extension-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/GridFsArtifact.java deleted file mode 100644 index ba17be936..000000000 --- a/extensions/hawkbit-extension-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/GridFsArtifact.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.artifact.repository; - -import java.io.InputStream; - -import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact; -import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash; - -import com.mongodb.gridfs.GridFSDBFile; -import com.mongodb.gridfs.GridFSFile; - -/** - * A wrapper object for the {@link AbstractDbArtifact} object which returns the - * {@link InputStream} directly from {@link GridFSDBFile#getInputStream()} which - * retrieves when calling {@link #getFileInputStream()} always a new - * {@link InputStream} and not the same. - * - * - * - */ -public class GridFsArtifact extends AbstractDbArtifact { - - private final GridFSFile dbFile; - - /** - * @param dbFile - */ - public GridFsArtifact(final GridFSFile dbFile) { - super(dbFile.getId().toString(), new DbArtifactHash(dbFile.getFilename(), dbFile.getMD5()), dbFile.getLength(), - dbFile.getContentType()); - this.dbFile = dbFile; - } - - @Override - public InputStream getFileInputStream() { - if (dbFile instanceof GridFSDBFile) { - return ((GridFSDBFile) dbFile).getInputStream(); - } - return null; - } -} diff --git a/extensions/hawkbit-extension-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/MongoDBArtifactStore.java b/extensions/hawkbit-extension-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/MongoDBArtifactStore.java deleted file mode 100644 index 61def91a6..000000000 --- a/extensions/hawkbit-extension-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/MongoDBArtifactStore.java +++ /dev/null @@ -1,268 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.artifact.repository; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.DigestOutputStream; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.List; -import java.util.stream.Collectors; - -import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact; -import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash; -import org.eclipse.hawkbit.tenancy.TenantAware; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.data.mongodb.core.query.Criteria; -import org.springframework.data.mongodb.core.query.Query; -import org.springframework.data.mongodb.gridfs.GridFsOperations; -import org.springframework.validation.annotation.Validated; - -import com.google.common.io.BaseEncoding; -import com.google.common.io.ByteStreams; -import com.mongodb.BasicDBObject; -import com.mongodb.MongoClientException; -import com.mongodb.MongoException; -import com.mongodb.gridfs.GridFSDBFile; -import com.mongodb.gridfs.GridFSFile; - -/** - * The file management which looks up all the file in the file tore. - * - */ -@Validated -public class MongoDBArtifactStore implements ArtifactRepository { - - private static final Logger LOGGER = LoggerFactory.getLogger(MongoDBArtifactStore.class); - - /** - * The mongoDB field which holds the filename of the file to download. - * hawkBit update-server uses the SHA hash as a filename and lookup in the - * mongoDB. - */ - private static final String FILENAME = "filename"; - - /** - * The mongoDB field which holds the tenant of the file to download. - */ - private static final String TENANT = "tenant"; - - /** - * Query by {@link TenantAware} field. - */ - private static final String TENANT_QUERY = "metadata." + TENANT; - - /** - * The mongoDB field which holds the SHA1 hash, stored in the meta data - * object. - */ - private static final String SHA1 = "sha1"; - - private static final String ID = "_id"; - - private final GridFsOperations gridFs; - - MongoDBArtifactStore(final GridFsOperations gridFs) { - this.gridFs = gridFs; - } - - /** - * Retrieves a {@link GridFSDBFile} from the store by it's SHA1 hash. - * - * @param sha1Hash - * the sha1-hash of the file to lookup. - * - * @return The DbArtifact object or {@code null} if no file exists. - */ - @Override - public AbstractDbArtifact getArtifactBySha1(final String tenant, final String sha1Hash) { - - GridFSDBFile found = gridFs.findOne(new Query() - .addCriteria(Criteria.where(FILENAME).is(sha1Hash).and(TENANT_QUERY).is(sanitizeTenant(tenant)))); - - // fallback pre-multi-tenancy - if (found == null) { - found = gridFs.findOne( - new Query().addCriteria(Criteria.where(FILENAME).is(sha1Hash).and(TENANT_QUERY).exists(false))); - } - - return map(found); - } - - @Override - public AbstractDbArtifact store(final String tenant, final InputStream content, final String filename, - final String contentType) { - return store(tenant, content, filename, contentType, null); - } - - @Override - public AbstractDbArtifact store(final String tenant, final InputStream content, final String filename, - final String contentType, final DbArtifactHash hash) { - File tempFile = null; - try { - LOGGER.debug("storing file {} of content {}", filename, contentType); - tempFile = File.createTempFile("uploadFile", null); - try (final BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tempFile))) { - try (BufferedInputStream bis = new BufferedInputStream(content)) { - return store(tenant, bis, contentType, bos, tempFile, hash); - } - } - } catch (final IOException | MongoException e1) { - throw new ArtifactStoreException(e1.getMessage(), e1); - } finally { - if (tempFile != null && !tempFile.delete()) { - LOGGER.error("Could not delete temporary file: {}", tempFile); - } - } - } - - private static String sanitizeTenant(final String tenant) { - return tenant.trim().toUpperCase(); - } - - @Override - public void deleteBySha1(final String tenant, final String sha1Hash) { - try { - deleteArtifact(gridFs.findOne(new Query() - .addCriteria(Criteria.where(FILENAME).is(sha1Hash).and(TENANT_QUERY).is(sanitizeTenant(tenant))))); - } catch (final MongoException e) { - throw new ArtifactStoreException(e.getMessage(), e); - } - } - - private void deleteArtifact(final GridFSDBFile dbFile) { - if (dbFile != null) { - try { - gridFs.delete(new Query().addCriteria(Criteria.where(ID).is(dbFile.getId()))); - } catch (final MongoClientException e) { - throw new ArtifactStoreException(e.getMessage(), e); - } - } - - } - - private AbstractDbArtifact store(final String t, final InputStream content, final String contentType, - final OutputStream os, final File tempFile, final DbArtifactHash hash) { - final GridFsArtifact storedArtifact; - final String tenant = sanitizeTenant(t); - try { - final String sha1Hash = computeSHA1Hash(content, os, hash != null ? hash.getSha1() : null); - // upload if it does not exist already, check if file exists, not - // tenant specific. - final GridFSDBFile result = gridFs.findOne( - new Query().addCriteria(Criteria.where(FILENAME).is(sha1Hash).and(TENANT_QUERY).is(tenant))); - if (result == null) { - try (FileInputStream inputStream = new FileInputStream(tempFile)) { - final BasicDBObject metadata = new BasicDBObject(); - metadata.put(SHA1, sha1Hash); - metadata.put(TENANT, tenant); - storedArtifact = map(gridFs.store(inputStream, sha1Hash, contentType, metadata)); - } - } else { - LOGGER.info("file with sha1 hash {} already exists in database, increase reference counter", sha1Hash); - result.save(); - storedArtifact = map(result); - } - } catch (final NoSuchAlgorithmException | IOException e) { - throw new ArtifactStoreException(e); - } - - if (notNull(hash, storedArtifact) && !storedArtifact.getHashes().getMd5().equalsIgnoreCase(hash.getMd5())) { - throw new HashNotMatchException("The given md5 hash " + hash.getMd5() - + " not matching the calculated md5 hash " + storedArtifact.getHashes().getMd5(), - HashNotMatchException.MD5); - } - - return storedArtifact; - - } - - private static boolean notNull(final DbArtifactHash hash, final GridFsArtifact storedArtifact) { - return hash != null && hash.getMd5() != null && storedArtifact != null && storedArtifact.getHashes() != null; - } - - private static String computeSHA1Hash(final InputStream stream, final OutputStream os, final String providedSHA1Sum) - throws NoSuchAlgorithmException, IOException { - String sha1Hash; - // compute digest - // Exception squid:S2070 - not used for hashing sensitive - // data - @SuppressWarnings("squid:S2070") - final MessageDigest md = MessageDigest.getInstance("SHA-1"); - try (final DigestOutputStream dos = new DigestOutputStream(os, md)) { - ByteStreams.copy(stream, dos); - } - sha1Hash = BaseEncoding.base16().lowerCase().encode(md.digest()); - if (providedSHA1Sum != null && !providedSHA1Sum.equalsIgnoreCase(sha1Hash)) { - throw new HashNotMatchException( - "The given sha1 hash " + providedSHA1Sum + " not matching the calculated sha1 hash " + sha1Hash, - HashNotMatchException.SHA1); - } - return sha1Hash; - } - - /** - * Maps a list of {@link GridFSDBFile} to a list of - * {@link AbstractDbArtifact}s. - * - * @param tenant - * the tenant - * @param dbFiles - * the list of mongoDB gridFs files. - * @return list of artifacts mapped from the given dbFiles - */ - private static List map(final List dbFiles) { - return dbFiles.stream().map(MongoDBArtifactStore::map).collect(Collectors.toList()); - } - - /** - * Retrieves a list of {@link GridFSDBFile} from the store by all ids. - * - * @param ids - * the ids of the files to lookup. - * @return list of artifacts - */ - public List getArtifactsByIds(final List ids) { - return map(gridFs.find(new Query().addCriteria(Criteria.where(ID).in(ids)))); - } - - /** - * Maps a single {@link GridFSFile} to {@link AbstractDbArtifact}. - * - * @param tenant - * the tenant - * @param dbFile - * the mongoDB gridFs file. - * @return a mapped artifact from the given dbFile - */ - private static GridFsArtifact map(final GridFSFile fsFile) { - if (fsFile == null) { - return null; - } - - return new GridFsArtifact(fsFile); - } - - @Override - public void deleteByTenant(final String tenant) { - try { - gridFs.delete(new Query().addCriteria(Criteria.where(TENANT_QUERY).is(sanitizeTenant(tenant)))); - } catch (final MongoClientException e) { - throw new ArtifactStoreException(e.getMessage(), e); - } - } -} diff --git a/extensions/hawkbit-extension-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/MongoDBArtifactStoreAutoConfiguration.java b/extensions/hawkbit-extension-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/MongoDBArtifactStoreAutoConfiguration.java deleted file mode 100644 index bc3d9afda..000000000 --- a/extensions/hawkbit-extension-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/MongoDBArtifactStoreAutoConfiguration.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.artifact.repository; - -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; -import org.springframework.data.mongodb.gridfs.GridFsOperations; - -/** - * Auto configuration for the {@link MongoDBArtifactStore}. - */ -@Configuration -@ConditionalOnProperty(prefix = "org.eclipse.hawkbit.artifact.repository.mongo", name = "enabled", matchIfMissing = true) -@PropertySource("classpath:/hawkbit-mongodb-defaults.properties") -public class MongoDBArtifactStoreAutoConfiguration { - - /** - * @return Default {@link ArtifactRepository} implementation. - */ - @Bean - ArtifactRepository artifactRepository(final GridFsOperations gridFs) { - return new MongoDBArtifactStore(gridFs); - } -} diff --git a/extensions/hawkbit-extension-artifact-repository-mongo/src/main/resources/META-INF/spring.factories b/extensions/hawkbit-extension-artifact-repository-mongo/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 09c60408f..000000000 --- a/extensions/hawkbit-extension-artifact-repository-mongo/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -# Auto Configure -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.eclipse.hawkbit.artifact.repository.MongoDBArtifactStoreAutoConfiguration \ No newline at end of file diff --git a/extensions/hawkbit-extension-artifact-repository-mongo/src/main/resources/hawkbit-mongodb-defaults.properties b/extensions/hawkbit-extension-artifact-repository-mongo/src/main/resources/hawkbit-mongodb-defaults.properties deleted file mode 100644 index b8c756fae..000000000 --- a/extensions/hawkbit-extension-artifact-repository-mongo/src/main/resources/hawkbit-mongodb-defaults.properties +++ /dev/null @@ -1,11 +0,0 @@ -# -# Copyright (c) 2015 Bosch Software Innovations GmbH and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://www.eclipse.org/legal/epl-v10.html -# - -# MongoDB for artifact-repository -spring.data.mongodb.uri=mongodb://localhost/artifactrepo \ No newline at end of file diff --git a/extensions/hawkbit-extension-artifact-repository-mongo/src/test/java/org/eclipse/hawkbit/artifact/TestConfiguration.java b/extensions/hawkbit-extension-artifact-repository-mongo/src/test/java/org/eclipse/hawkbit/artifact/TestConfiguration.java deleted file mode 100644 index d59050e29..000000000 --- a/extensions/hawkbit-extension-artifact-repository-mongo/src/test/java/org/eclipse/hawkbit/artifact/TestConfiguration.java +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.artifact; - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.context.annotation.ComponentScan; - -@ComponentScan -@EnableAutoConfiguration -public class TestConfiguration { -} diff --git a/extensions/hawkbit-extension-artifact-repository-mongo/src/test/java/org/eclipse/hawkbit/artifact/repository/MongoDBArtifactStoreTest.java b/extensions/hawkbit-extension-artifact-repository-mongo/src/test/java/org/eclipse/hawkbit/artifact/repository/MongoDBArtifactStoreTest.java deleted file mode 100644 index b2bfdfde1..000000000 --- a/extensions/hawkbit-extension-artifact-repository-mongo/src/test/java/org/eclipse/hawkbit/artifact/repository/MongoDBArtifactStoreTest.java +++ /dev/null @@ -1,105 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.artifact.repository; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.io.ByteArrayInputStream; -import java.security.DigestInputStream; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Random; - -import org.eclipse.hawkbit.artifact.TestConfiguration; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import com.google.common.io.BaseEncoding; - -import ru.yandex.qatools.allure.annotations.Description; -import ru.yandex.qatools.allure.annotations.Features; -import ru.yandex.qatools.allure.annotations.Step; -import ru.yandex.qatools.allure.annotations.Stories; - -@Features("Component Tests - Repository") -@Stories("Artifact Store MongoDB") -@RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest(classes = { MongoDBArtifactStoreAutoConfiguration.class, TestConfiguration.class }, properties = { - "spring.data.mongodb.port=0", "spring.mongodb.embedded.version=3.4.4" }) -public class MongoDBArtifactStoreTest { - private static final String TENANT = "test_tenant"; - private static final String TENANT2 = "test_tenant2"; - - @Autowired - private MongoDBArtifactStore artifactStoreUnderTest; - - @Test - @Description("Ensures that search by SHA1 hash (which is used by hawkBit as artifact ID) finds the expected results.") - public void findArtifactBySHA1Hash() throws NoSuchAlgorithmException { - - final String sha1 = storeRandomArifactAndVerify(TENANT); - final String sha2 = storeRandomArifactAndVerify(TENANT2); - - assertThat(artifactStoreUnderTest.getArtifactBySha1(TENANT2, sha1)).isNull(); - assertThat(artifactStoreUnderTest.getArtifactBySha1(TENANT, sha2)).isNull(); - } - - @Step - private String storeRandomArifactAndVerify(final String tenant) throws NoSuchAlgorithmException { - final int filelengthBytes = 128; - final String filename = "testfile.json"; - final String contentType = "application/json"; - - final DigestInputStream digestInputStream = digestInputStream(generateInputStream(filelengthBytes), "SHA-1"); - artifactStoreUnderTest.store(tenant, digestInputStream, filename, contentType); - - final String sha1 = BaseEncoding.base16().lowerCase().encode(digestInputStream.getMessageDigest().digest()); - assertThat(artifactStoreUnderTest.getArtifactBySha1(tenant, sha1)).isNotNull(); - return sha1; - } - - @Test - @Description("Deletes file from repository identified by SHA1 hash as filename.") - public void deleteArtifactBySHA1Hash() throws NoSuchAlgorithmException { - - final String sha1 = storeRandomArifactAndVerify(TENANT); - - artifactStoreUnderTest.deleteBySha1(TENANT, sha1); - assertThat(artifactStoreUnderTest.getArtifactBySha1(TENANT, sha1)).isNull(); - } - - @Test - @Description("Verfies that all data of a tenant is erased if repository is asked to do so. " - + "Data of other tenants is not affected.") - public void deleteTenant() throws NoSuchAlgorithmException { - - final String shaDeleted = storeRandomArifactAndVerify(TENANT); - final String shaUndeleted = storeRandomArifactAndVerify("another_tenant"); - - artifactStoreUnderTest.deleteByTenant("tenant_that_does_not_exist"); - artifactStoreUnderTest.deleteByTenant(TENANT); - assertThat(artifactStoreUnderTest.getArtifactBySha1(TENANT, shaDeleted)).isNull(); - assertThat(artifactStoreUnderTest.getArtifactBySha1("another_tenant", shaUndeleted)).isNotNull(); - } - - private static ByteArrayInputStream generateInputStream(final int length) { - final byte[] bytes = new byte[length]; - new Random().nextBytes(bytes); - return new ByteArrayInputStream(bytes); - } - - private static DigestInputStream digestInputStream(final ByteArrayInputStream stream, final String digest) - throws NoSuchAlgorithmException { - return new DigestInputStream(stream, MessageDigest.getInstance(digest)); - } - -} diff --git a/extensions/hawkbit-extension-artifact-repository-s3/README.md b/extensions/hawkbit-extension-artifact-repository-s3/README.md deleted file mode 100644 index ee4e20cad..000000000 --- a/extensions/hawkbit-extension-artifact-repository-s3/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# Eclipse hawkBit - Artifact Repository AWS S3 -HawkBit Artifact Repository is a library for storing binary artifacts and metadata into the AWS S3 service. - - -## Using Artifact Repository S3 Extension -The module contains a spring-boot autoconfiguration for easily integration into spring-boot projects. -For using this extension in the hawkbit-example-application you just need to add the maven dependency. -``` - - org.eclipse.hawkbit - hawkbit-extension-artifact-repository-s3 - ${project.version} - -``` - -## Configuration of the S3 Extension - -#### Bucket -All files are stored in a bucket configured via property `org.eclipse.hawkbit.repository.s3.bucketName` (see S3RepositoryProperties). -The name of the object stored in the S3 bucket is the SHA1-hash of the binary file. - -#### S3 Credentials -The extension is using the `DefaultAWSCredentialsProviderChain` class which looks for credentials in this order: - -1. Environment variables (AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY) -2. Java system properties (aws.accessKeyId and aws.secretKey) -3. Default credential profile file (~/.aws/credentials) -4. Amazon ECS container credentials -5. Instance profile credentials - -For more information check the [Amazon credentials guide](http://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html). - -You can exchange the credentials provider by overwriting the `AWSCredentialsProvider` bean (see S3RepositoryAutoConfiguration). diff --git a/extensions/hawkbit-extension-artifact-repository-s3/pom.xml b/extensions/hawkbit-extension-artifact-repository-s3/pom.xml deleted file mode 100644 index ecd10e049..000000000 --- a/extensions/hawkbit-extension-artifact-repository-s3/pom.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - 4.0.0 - - org.eclipse.hawkbit - hawkbit-extensions-parent - 0.2.0-SNAPSHOT - - hawkbit-extension-artifact-repository-s3 - hawkBit :: Extensions :: S3 Repository - - - - - com.amazonaws - aws-java-sdk-s3 - - - com.amazonaws - aws-java-sdk-core - - - org.eclipse.hawkbit - hawkbit-core - ${project.version} - - - com.google.guava - guava - - - org.springframework - spring-core - - - org.springframework.boot - spring-boot-autoconfigure - - - commons-io - commons-io - - - org.springframework.boot - spring-boot-starter-test - test - - - ru.yandex.qatools.allure - allure-junit-adaptor - test - - - \ No newline at end of file diff --git a/extensions/hawkbit-extension-artifact-repository-s3/src/main/java/org/eclipse/hawkbit/artifact/repository/S3Artifact.java b/extensions/hawkbit-extension-artifact-repository-s3/src/main/java/org/eclipse/hawkbit/artifact/repository/S3Artifact.java deleted file mode 100644 index 9fe130ccf..000000000 --- a/extensions/hawkbit-extension-artifact-repository-s3/src/main/java/org/eclipse/hawkbit/artifact/repository/S3Artifact.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.artifact.repository; - -import java.io.InputStream; - -import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact; -import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash; -import org.springframework.util.Assert; - -import com.amazonaws.services.s3.AmazonS3; - -/** - * An {@link AbstractDbArtifact} implementation which retrieves the - * {@link InputStream} from the {@link AmazonS3} client. - */ -public class S3Artifact extends AbstractDbArtifact { - - private final AmazonS3 amazonS3; - private final S3RepositoryProperties s3Properties; - private final String key; - - S3Artifact(final AmazonS3 amazonS3, final S3RepositoryProperties s3Properties, final String key, - final String artifactId, final DbArtifactHash hashes, final Long size, final String contentType) { - super(artifactId, hashes, size, contentType); - Assert.notNull(amazonS3, "S3 cannot be null"); - Assert.notNull(s3Properties, "Properties cannot be null"); - Assert.notNull(key, "Key cannot be null"); - this.amazonS3 = amazonS3; - this.s3Properties = s3Properties; - this.key = key; - } - - @Override - public InputStream getFileInputStream() { - return amazonS3.getObject(s3Properties.getBucketName(), key).getObjectContent(); - } - - @Override - public String toString() { - return "S3Artifact [key=" + key + ", getArtifactId()=" + getArtifactId() + ", getHashes()=" + getHashes() - + ", getSize()=" + getSize() + ", getContentType()=" + getContentType() + "]"; - } -} diff --git a/extensions/hawkbit-extension-artifact-repository-s3/src/main/java/org/eclipse/hawkbit/artifact/repository/S3Repository.java b/extensions/hawkbit-extension-artifact-repository-s3/src/main/java/org/eclipse/hawkbit/artifact/repository/S3Repository.java deleted file mode 100644 index 45d579538..000000000 --- a/extensions/hawkbit-extension-artifact-repository-s3/src/main/java/org/eclipse/hawkbit/artifact/repository/S3Repository.java +++ /dev/null @@ -1,255 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.artifact.repository; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.security.DigestOutputStream; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact; -import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.validation.annotation.Validated; - -import com.amazonaws.AmazonClientException; -import com.amazonaws.RequestClientOptions; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.Headers; -import com.amazonaws.services.s3.model.DeleteObjectRequest; -import com.amazonaws.services.s3.model.ObjectListing; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.S3Object; -import com.amazonaws.services.s3.model.S3ObjectSummary; -import com.google.common.io.BaseEncoding; -import com.google.common.io.ByteStreams; - -/** - * An {@link ArtifactRepository} implementation for the AWS S3 service. All - * binaries are stored in single bucket using the configured name - * {@link S3RepositoryProperties#getBucketName()}. - * - * From the AWS S3 documentation: - *

- * There is no limit to the number of objects that can be stored in a bucket and - * no difference in performance whether you use many buckets or just a few. You - * can store all of your objects in a single bucket, or you can organize them - * across several buckets. - *

- */ -@Validated -public class S3Repository implements ArtifactRepository { - - private static final Logger LOG = LoggerFactory.getLogger(S3Repository.class); - - private static final String TEMP_FILE_PREFIX = "tmp"; - private static final String TEMP_FILE_SUFFIX = "artifactrepo"; - - private final AmazonS3 amazonS3; - private final S3RepositoryProperties s3Properties; - - /** - * Constructor. - * - * @param amazonS3 - * the amazonS3 client to use - * @param s3Properties - * the properties which e.g. holds the name of the bucket to - * store in - */ - public S3Repository(final AmazonS3 amazonS3, final S3RepositoryProperties s3Properties) { - this.amazonS3 = amazonS3; - this.s3Properties = s3Properties; - } - - @Override - public AbstractDbArtifact store(final String tenant, final InputStream content, final String filename, - final String contentType) { - return store(tenant, content, filename, contentType, null); - } - - @Override - // suppress warning, of not strong enough hashing algorithm, SHA-1 and MD5 - // is not used security related - @SuppressWarnings("squid:S2070") - public AbstractDbArtifact store(final String tenant, final InputStream content, final String filename, - final String contentType, final DbArtifactHash hash) { - final MessageDigest mdSHA1; - final MessageDigest mdMD5; - try { - mdSHA1 = MessageDigest.getInstance("SHA1"); - mdMD5 = MessageDigest.getInstance("MD5"); - } catch (final NoSuchAlgorithmException e) { - throw new ArtifactStoreException(e.getMessage(), e); - } - - LOG.debug("Creating temporary file to store the inputstream to it"); - - final File file = createTempFile(); - LOG.debug("Calculating sha1 and md5 hashes"); - try (final DigestOutputStream outputstream = openFileOutputStream(file, mdSHA1, mdMD5)) { - ByteStreams.copy(content, outputstream); - outputstream.flush(); - final String sha1Hash16 = BaseEncoding.base16().lowerCase().encode(mdSHA1.digest()); - final String md5Hash16 = BaseEncoding.base16().lowerCase().encode(mdMD5.digest()); - - return store(tenant, sha1Hash16, md5Hash16, contentType, file, hash); - } catch (final IOException e) { - throw new ArtifactStoreException(e.getMessage(), e); - } finally { - if (!file.delete()) { - LOG.error("Could not delete temp file {}", file); - } - } - } - - private AbstractDbArtifact store(final String tenant, final String sha1Hash16, final String mdMD5Hash16, - final String contentType, final File file, final DbArtifactHash hash) { - final S3Artifact s3Artifact = createS3Artifact(tenant, sha1Hash16, mdMD5Hash16, contentType, file); - checkHashes(s3Artifact, hash); - final String key = objectKey(tenant, sha1Hash16); - - LOG.info("Storing file {} with length {} to AWS S3 bucket {} as SHA1 {}", file.getName(), file.length(), - s3Properties.getBucketName(), key); - - if (exists(key)) { - LOG.debug("Artifact {} already exists on S3 bucket {}, don't need to upload twice", sha1Hash16, - s3Properties.getBucketName()); - return s3Artifact; - } - - try (final InputStream inputStream = new BufferedInputStream(new FileInputStream(file), - RequestClientOptions.DEFAULT_STREAM_BUFFER_SIZE)) { - final ObjectMetadata objectMetadata = createObjectMetadata(mdMD5Hash16, contentType, file); - amazonS3.putObject(s3Properties.getBucketName(), key, inputStream, objectMetadata); - - return s3Artifact; - } catch (final IOException | AmazonClientException e) { - throw new ArtifactStoreException(e.getMessage(), e); - } - } - - private S3Artifact createS3Artifact(final String tenant, final String sha1Hash, final String mdMD5Hash16, - final String contentType, final File file) { - return new S3Artifact(amazonS3, s3Properties, objectKey(tenant, sha1Hash), sha1Hash, - new DbArtifactHash(sha1Hash, mdMD5Hash16), file.length(), contentType); - } - - private ObjectMetadata createObjectMetadata(final String mdMD5Hash16, final String contentType, final File file) { - final ObjectMetadata objectMetadata = new ObjectMetadata(); - final String mdMD5Hash64 = BaseEncoding.base64().encode(BaseEncoding.base16().lowerCase().decode(mdMD5Hash16)); - objectMetadata.setContentMD5(mdMD5Hash64); - objectMetadata.setContentType(contentType); - objectMetadata.setContentLength(file.length()); - objectMetadata.setHeader("x-amz-meta-md5chksum", mdMD5Hash64); - if (s3Properties.isServerSideEncryption()) { - objectMetadata.setHeader(Headers.SERVER_SIDE_ENCRYPTION, s3Properties.getServerSideEncryptionAlgorithm()); - } - return objectMetadata; - } - - @Override - public void deleteBySha1(final String tenant, final String sha1Hash) { - final String key = objectKey(tenant, sha1Hash); - - LOG.info("Deleting S3 object from bucket {} and key {}", s3Properties.getBucketName(), key); - amazonS3.deleteObject(new DeleteObjectRequest(s3Properties.getBucketName(), key)); - } - - private static String objectKey(final String tenant, final String sha1Hash) { - return sanitizeTenant(tenant) + "/" + sha1Hash; - } - - @Override - public AbstractDbArtifact getArtifactBySha1(final String tenant, final String sha1Hash) { - final String key = objectKey(tenant, sha1Hash); - - LOG.info("Retrieving S3 object from bucket {} and key {}", s3Properties.getBucketName(), key); - try (final S3Object s3Object = amazonS3.getObject(s3Properties.getBucketName(), key)) { - if (s3Object == null) { - return null; - } - - final ObjectMetadata s3ObjectMetadata = s3Object.getObjectMetadata(); - - // the MD5Content is stored in the ETag - return new S3Artifact(amazonS3, s3Properties, key, sha1Hash, - new DbArtifactHash(sha1Hash, - BaseEncoding.base16().lowerCase() - .encode(BaseEncoding.base64().decode(s3ObjectMetadata.getETag()))), - s3ObjectMetadata.getContentLength(), s3ObjectMetadata.getContentType()); - } catch (final IOException e) { - LOG.error("Could not verify S3Object", e); - return null; - } - } - - private static void checkHashes(final AbstractDbArtifact artifact, final DbArtifactHash hash) { - if (hash == null) { - return; - } - if (hash.getSha1() != null && !artifact.getHashes().getSha1().equals(hash.getSha1())) { - throw new HashNotMatchException("The given sha1 hash " + hash.getSha1() - + " does not match with the calcualted sha1 hash " + artifact.getHashes().getSha1(), - HashNotMatchException.SHA1); - } - if (hash.getMd5() != null && !artifact.getHashes().getMd5().equals(hash.getMd5())) { - throw new HashNotMatchException("The given md5 hash " + hash.getMd5() - + " does not match with the calcualted md5 hash " + artifact.getHashes().getMd5(), - HashNotMatchException.MD5); - } - } - - private static File createTempFile() { - try { - return File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX); - } catch (final IOException e) { - throw new ArtifactStoreException("Cannot create tempfile", e); - } - } - - private static DigestOutputStream openFileOutputStream(final File file, final MessageDigest mdSHA1, - final MessageDigest mdMD5) throws FileNotFoundException { - return new DigestOutputStream( - new DigestOutputStream(new BufferedOutputStream(new FileOutputStream(file)), mdMD5), mdSHA1); - } - - private boolean exists(final String sha1) { - return amazonS3.doesObjectExist(s3Properties.getBucketName(), sha1); - } - - @Override - public void deleteByTenant(final String tenant) { - final String folder = sanitizeTenant(tenant); - - LOG.info("Deleting S3 object folder (tenant) from bucket {} and key {}", s3Properties.getBucketName(), folder); - - // Delete artifacts - ObjectListing objects = amazonS3.listObjects(s3Properties.getBucketName(), folder + "/"); - do { - for (final S3ObjectSummary objectSummary : objects.getObjectSummaries()) { - amazonS3.deleteObject(s3Properties.getBucketName(), objectSummary.getKey()); - } - objects = amazonS3.listNextBatchOfObjects(objects); - } while (objects.isTruncated()); - - } - - private static String sanitizeTenant(final String tenant) { - return tenant.trim().toUpperCase(); - } -} diff --git a/extensions/hawkbit-extension-artifact-repository-s3/src/main/java/org/eclipse/hawkbit/artifact/repository/S3RepositoryAutoConfiguration.java b/extensions/hawkbit-extension-artifact-repository-s3/src/main/java/org/eclipse/hawkbit/artifact/repository/S3RepositoryAutoConfiguration.java deleted file mode 100644 index a4296c2ba..000000000 --- a/extensions/hawkbit-extension-artifact-repository-s3/src/main/java/org/eclipse/hawkbit/artifact/repository/S3RepositoryAutoConfiguration.java +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.artifact.repository; - -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import com.amazonaws.ClientConfiguration; -import com.amazonaws.auth.AWSCredentialsProvider; -import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3Client; - -/** - * The Spring auto-configuration to register the necessary beans for the S3 - * artifact repository implementation. - */ -@Configuration -@ConditionalOnProperty(prefix = "org.eclipse.hawkbit.artifact.repository.s3", name = "enabled", matchIfMissing = true) -@EnableConfigurationProperties(S3RepositoryProperties.class) -public class S3RepositoryAutoConfiguration { - - /** - * The {@link DefaultAWSCredentialsProviderChain} looks for credentials in - * this order: - * - *
-     * 1. Environment Variables (AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY)
-     * 2. Java System Properties (aws.accessKeyId and aws.secretKey)
-     * 3. The default credential profiles file (~/.aws/credentials)
-     * 4. Amazon ECS container credentials
-     * 5. Instance profile credentials
-     * 
- * - * @return the {@link DefaultAWSCredentialsProviderChain} if no other - * {@link AWSCredentialsProvider} bean is registered. - */ - @Bean - @ConditionalOnMissingBean - public AWSCredentialsProvider awsCredentialsProvider() { - return new DefaultAWSCredentialsProviderChain(); - } - - /** - * The default AmazonS3 client configuration, which declares the - * configuration for managing connection behavior to s3. - * - * @return the default {@link ClientConfiguration} bean with the default - * client configuration - */ - @Bean - @ConditionalOnMissingBean - public ClientConfiguration awsClientConfiguration() { - return new ClientConfiguration(); - } - - /** - * @return the {@link AmazonS3Client} if no other {@link AmazonS3} bean is - * registered. - */ - @Bean - @ConditionalOnMissingBean - public AmazonS3 amazonS3() { - return new AmazonS3Client(awsCredentialsProvider(), awsClientConfiguration()); - } - - /** - * @return AWS S3 repository {@link ArtifactRepository} implementation. - */ - @Bean - public ArtifactRepository artifactRepository(final S3RepositoryProperties s3Properties) { - return new S3Repository(amazonS3(), s3Properties); - } -} diff --git a/extensions/hawkbit-extension-artifact-repository-s3/src/main/java/org/eclipse/hawkbit/artifact/repository/S3RepositoryProperties.java b/extensions/hawkbit-extension-artifact-repository-s3/src/main/java/org/eclipse/hawkbit/artifact/repository/S3RepositoryProperties.java deleted file mode 100644 index df6bbd880..000000000 --- a/extensions/hawkbit-extension-artifact-repository-s3/src/main/java/org/eclipse/hawkbit/artifact/repository/S3RepositoryProperties.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.artifact.repository; - -import org.springframework.boot.context.properties.ConfigurationProperties; - -import com.amazonaws.services.s3.model.SSEAlgorithm; - -/** - * The AWS S3 configuration properties for the S3 artifact repository - * implementation. - */ -@ConfigurationProperties("org.eclipse.hawkbit.repository.s3") -public class S3RepositoryProperties { - - private String bucketName = "artifactrepository"; - private boolean serverSideEncryption = false; - private String serverSideEncryptionAlgorithm = SSEAlgorithm.AES256.getAlgorithm(); - - public String getBucketName() { - return bucketName; - } - - public void setBucketName(final String bucketName) { - this.bucketName = bucketName; - } - - public boolean isServerSideEncryption() { - return serverSideEncryption; - } - - public void setServerSideEncryption(final boolean serverSideEncryption) { - this.serverSideEncryption = serverSideEncryption; - } - - public String getServerSideEncryptionAlgorithm() { - return serverSideEncryptionAlgorithm; - } - - public void setServerSideEncryptionAlgorithm(final String serverSideEncryptionAlgorithm) { - this.serverSideEncryptionAlgorithm = serverSideEncryptionAlgorithm; - } -} diff --git a/extensions/hawkbit-extension-artifact-repository-s3/src/main/resources/META-INF/spring.factories b/extensions/hawkbit-extension-artifact-repository-s3/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 3736f86fd..000000000 --- a/extensions/hawkbit-extension-artifact-repository-s3/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -# Auto Configure -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.eclipse.hawkbit.artifact.repository.S3RepositoryAutoConfiguration diff --git a/extensions/hawkbit-extension-artifact-repository-s3/src/test/java/org/eclipse/hawkbit/artifact/repository/S3RepositoryTest.java b/extensions/hawkbit-extension-artifact-repository-s3/src/test/java/org/eclipse/hawkbit/artifact/repository/S3RepositoryTest.java deleted file mode 100644 index e3855bb96..000000000 --- a/extensions/hawkbit-extension-artifact-repository-s3/src/test/java/org/eclipse/hawkbit/artifact/repository/S3RepositoryTest.java +++ /dev/null @@ -1,226 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.artifact.repository; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.when; - -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.DigestOutputStream; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Random; - -import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact; -import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; - -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.S3Object; -import com.google.common.io.BaseEncoding; -import com.google.common.io.ByteStreams; - -import ru.yandex.qatools.allure.annotations.Description; -import ru.yandex.qatools.allure.annotations.Features; -import ru.yandex.qatools.allure.annotations.Stories; - -/** - * Test class for the {@link S3Repository}. - */ -@RunWith(MockitoJUnitRunner.class) -@Features("Unit Tests - S3 Repository") -@Stories("S3 Artifact Repository") -public class S3RepositoryTest { - private static final String TENANT = "test_tenant"; - - @Mock - private AmazonS3 amazonS3Mock; - - @Mock - private S3Object s3ObjectMock; - - @Mock - private ObjectMetadata s3ObjectMetadataMock; - - @Captor - private ArgumentCaptor objectMetaDataCaptor; - - @Captor - private ArgumentCaptor inputStreamCaptor; - - private final S3RepositoryProperties s3Properties = new S3RepositoryProperties(); - private S3Repository s3RepositoryUnderTest; - - @Before - public void before() { - s3RepositoryUnderTest = new S3Repository(amazonS3Mock, s3Properties); - } - - @Test - @Description("Verifies that the amazonS3 client is called to put the object to S3 with the correct inputstream and meta-data") - public void storeInputStreamCallAmazonS3Client() throws IOException, NoSuchAlgorithmException { - final byte[] rndBytes = randomBytes(); - final String knownSHA1 = getSha1OfBytes(rndBytes); - final String knownContentType = "application/octet-stream"; - - // test - storeRandomBytes(rndBytes, knownContentType); - - // verify - Mockito.verify(amazonS3Mock).putObject(eq(s3Properties.getBucketName()), - eq(TENANT.toUpperCase() + "/" + knownSHA1), inputStreamCaptor.capture(), - objectMetaDataCaptor.capture()); - - final ObjectMetadata recordedObjectMetadata = objectMetaDataCaptor.getValue(); - assertThat(recordedObjectMetadata.getContentType()).isEqualTo(knownContentType); - assertThat(recordedObjectMetadata.getContentMD5()).isNotNull(); - assertThat(recordedObjectMetadata.getContentLength()).isEqualTo(rndBytes.length); - } - - @Test - @Description("Verifies that the amazonS3 client is called to retrieve the correct artifact from S3 and the mapping to the DBArtifact is correct") - public void getArtifactBySHA1Hash() { - final String knownSHA1Hash = "da39a3ee5e6b4b0d3255bfef95601890afd80709"; - final long knownContentLength = 100; - final String knownContentType = "application/octet-stream"; - final String knownMd5 = "098f6bcd4621d373cade4e832627b4f6"; - final String knownMdBase16 = BaseEncoding.base16().lowerCase().encode(knownMd5.getBytes()); - final String knownMd5Base64 = BaseEncoding.base64().encode(knownMd5.getBytes()); - - when(amazonS3Mock.getObject(anyString(), anyString())).thenReturn(s3ObjectMock); - when(s3ObjectMock.getObjectMetadata()).thenReturn(s3ObjectMetadataMock); - when(s3ObjectMetadataMock.getContentLength()).thenReturn(knownContentLength); - when(s3ObjectMetadataMock.getETag()).thenReturn(knownMd5Base64); - when(s3ObjectMetadataMock.getContentType()).thenReturn(knownContentType); - - // test - final AbstractDbArtifact artifactBySha1 = s3RepositoryUnderTest.getArtifactBySha1(TENANT, knownSHA1Hash); - - // verify - assertThat(artifactBySha1.getArtifactId()).isEqualTo(knownSHA1Hash); - assertThat(artifactBySha1.getContentType()).isEqualTo(knownContentType); - assertThat(artifactBySha1.getSize()).isEqualTo(knownContentLength); - assertThat(artifactBySha1.getHashes().getSha1()).isEqualTo(knownSHA1Hash); - assertThat(artifactBySha1.getHashes().getMd5()).isEqualTo(knownMdBase16); - } - - @Test - @Description("Verifies that the amazonS3 client is not called to put the object to S3 due the artifact already exists on S3") - public void artifactIsNotUploadedIfAlreadyExists() throws NoSuchAlgorithmException, IOException { - final byte[] rndBytes = randomBytes(); - final String knownSHA1 = getSha1OfBytes(rndBytes); - final String knownContentType = "application/octet-stream"; - - when(amazonS3Mock.doesObjectExist(s3Properties.getBucketName(), knownSHA1)).thenReturn(true); - - // test - storeRandomBytes(rndBytes, knownContentType); - - // verify - Mockito.verify(amazonS3Mock, never()).putObject(eq(s3Properties.getBucketName()), eq(knownSHA1), - inputStreamCaptor.capture(), objectMetaDataCaptor.capture()); - - } - - @Test - @Description("Verifies that null is returned if the given hash does not exists on S3") - public void getArtifactBySha1ReturnsNullIfFileDoesNotExists() { - final String knownSHA1Hash = "0815"; - when(amazonS3Mock.getObject(s3Properties.getBucketName(), knownSHA1Hash)).thenReturn(null); - - // test - final AbstractDbArtifact artifactBySha1NotExists = s3RepositoryUnderTest.getArtifactBySha1(TENANT, knownSHA1Hash); - - // verify - assertThat(artifactBySha1NotExists).isNull(); - } - - @Test - @Description("Verifies that given SHA1 hash are checked and if not match will throw exception") - public void sha1HashValuesAreNotTheSameThrowsException() throws IOException { - - final byte[] rndBytes = randomBytes(); - final String knownContentType = "application/octet-stream"; - final String wrongSHA1Hash = "wrong"; - final String wrongMD5 = "wrong"; - - // test - try { - storeRandomBytes(rndBytes, knownContentType, new DbArtifactHash(wrongSHA1Hash, wrongMD5)); - fail("Expected an HashNotMatchException, but didn't throw"); - } catch (final HashNotMatchException e) { - assertThat(e.getHashFunction()).isEqualTo(HashNotMatchException.SHA1); - } - } - - @Test - @Description("Verifies that given MD5 hash are checked and if not match will throw exception") - public void md5HashValuesAreNotTheSameThrowsException() throws IOException, NoSuchAlgorithmException { - - final byte[] rndBytes = randomBytes(); - final String knownContentType = "application/octet-stream"; - final String knownSHA1 = getSha1OfBytes(rndBytes); - final String wrongMD5 = "wrong"; - - // test - try { - storeRandomBytes(rndBytes, knownContentType, new DbArtifactHash(knownSHA1, wrongMD5)); - fail("Expected an HashNotMatchException, but didn't throw"); - } catch (final HashNotMatchException e) { - assertThat(e.getHashFunction()).isEqualTo(HashNotMatchException.MD5); - } - } - - private void storeRandomBytes(final byte[] rndBytes, final String contentType) - throws IOException, NoSuchAlgorithmException { - storeRandomBytes(rndBytes, contentType, null); - } - - private void storeRandomBytes(final byte[] rndBytes, final String contentType, final DbArtifactHash hashes) - throws IOException { - final String knownFileName = "randomBytes"; - try (InputStream content = new BufferedInputStream(new ByteArrayInputStream(rndBytes))) { - s3RepositoryUnderTest.store(TENANT, content, knownFileName, contentType, hashes); - } - } - - private static String getSha1OfBytes(final byte[] bytes) throws IOException, NoSuchAlgorithmException { - final MessageDigest messageDigest = MessageDigest.getInstance("SHA1"); - - try (InputStream input = new ByteArrayInputStream(bytes); - OutputStream output = new DigestOutputStream(new ByteArrayOutputStream(), messageDigest)) { - ByteStreams.copy(input, output); - return BaseEncoding.base16().lowerCase().encode(messageDigest.digest()); - } - } - - private static byte[] randomBytes() { - final byte[] randomBytes = new byte[20]; - final Random ran = new Random(); - ran.nextBytes(randomBytes); - return randomBytes; - } -} diff --git a/extensions/hawkbit-extension-uaa/README.md b/extensions/hawkbit-extension-uaa/README.md deleted file mode 100644 index 70722fb60..000000000 --- a/extensions/hawkbit-extension-uaa/README.md +++ /dev/null @@ -1,119 +0,0 @@ -# hawkBit UAA Extension -The hawkBit UAA extension enables hawkBit to use the [User Account and Authentication (UAA)](https://github.com/cloudfoundry/uaa) based on the Spring Security OAuth project. -In general the mechanism can be adapted to use any OAUTH2 server. The `UserPrincipalInfoTokenServices` might be adapted for other OAUTH2 providers to extract the principal information. - -The `UaaOAuthAutoConfiguration` setups the necessary servlet-filter to intercept the security-chain to implement the OAUTH2 workflow. It allows to redirect to the UAA-Login-Form via the URL `/uaalogin` as well as to use the bearer access token within the hawkBit REST-API using the HTTP Authorization header `Authorization: bearer ezro63ut....`. - -To retrieve the bearer access token, check out the OAUTH2 authorization resource of the [UAA-API](https://github.com/cloudfoundry/uaa/blob/master/docs/UAA-APIs.rst) - -## Using UAA Extension -To use this extension in the example application you just need to add the maven-dependencies to the example-application `pom.xml` and configure the necessary properties in the `application.properties` -``` - - org.eclipse.hawkbit - hawkbit-extension-uaa - ${project.version} - -``` - -## Configuration -The `UaaClientProperties` must contain the necessary configuration to setup the OAUTH2 client-id and client-credentials, as well as the necessary OAUTH2 URLS as well as the JWT signing key. - -``` -uaa.client.clientId=hawkBit -uaa.client.clientSecret=hawkBitSecret -uaa.client.accessTokenUri=http://localhost:8080/uaa/oauth/token -uaa.client.userAuthorizationUri=http://localhost:8080/uaa/oauth/authorize -uaa.client.clientAuthenticationScheme=form -uaa.resource.userInfoUri=http://localhost:8080/uaa/userinfo -uaa.resource.jwt.keyValue=uaasign -``` - -## Multitenancy -The implementation uses the `zid` (zoneId) as tenant information. The default zone-id in the UAA is `uaa`, so every user which logs into hawkBit logs in for the tenant `uaa`. You can use the UAA zones mechanism to implement multi-tenancy mechanism to hawkbit or you can change the strategy. To change the tenant extraction strategy you can adapt the `UserPrincipalInfoTokenServices` which creates the hawkBit `UserPrincipal` which contains the tenant information of the principal. - -## Token Signing -Using the bearer token within the hawkBit REST-APIs the bearer token is verified by hawkBit using either a symmetric or asymmetric keys. The necessary `key-value` must be configured in the configuration. - -# UAA Configuration -The [User Account and Authentication (UAA)](https://github.com/cloudfoundry/uaa) can be started as an stand-alone application. -More information to configuration see [UAA-Docs](https://github.com/cloudfoundry/uaa/blob/master/docs). - -## uaa.yml -The `uaa.yml` contains the necessary bootstrap configuration of the UAA. To work with hawkBit you'll need to setup the OAUTH2 client which hawkBit is using. Furthermore you need to setup the necessary hawkBit permissions to allow hawkBit to do authorization decision based on the known permissions. - -Example `uaa.yml` configuration: -``` -scim: - users: - - hawkbitadmin|hawkbitadmin|hawkbitadmin@test.org|hawkbitadmin|hawkbitadmin|uaa.admin,READ_TARGET,CREATE_TARGET,UPDATE_TARGET,DELETE_TARGET,READ_REPOSITORY,UPDATE_REPOSITORY,CREATE_REPOSITORY,DELETE_REPOSITORY,SYSTEM_MONITOR,SYSTEM_DIAG,SYSTEM_ADMIN,DOWNLOAD_REPOSITORY_ARTIFACT,TENANT_CONFIGURATION,ROLLOUT_MANAGEMENT - groups: - zones.read: Read identity zones - zones.write: Create and update identity zones - idps.read: Retrieve identity providers - idps.write: Create and update identity providers - clients.admin: Create, modify and delete OAuth clients - clients.write: Create and modify OAuth clients - clients.read: Read information about OAuth clients - clients.secret: Change the password of an OAuth client - scim.write: Create, modify and delete SCIM entities, i.e. users and groups - scim.read: Read all SCIM entities, i.e. users and groups - scim.create: Create users - scim.userids: Read user IDs and retrieve users by ID - scim.zones: Control a user's ability to manage a zone - scim.invite: Send invitations to users - password.write: Change your password - oauth.approval: Manage approved scopes - oauth.login: Authenticate users outside of the UAA - openid: Access profile information, i.e. email, first and last name, and phone number - groups.update: Update group information and memberships - uaa.user: Act as a user in the UAA - uaa.resource: Serve resources protected by the UAA - uaa.admin: Act as an administrator throughout the UAA - uaa.none: Forbid acting as a user - uaa.offline_token: Allow offline access - -jwt: - token: - signing-key: uaasign - verification-key: uaasign -login: - branding: - companyName: hawkbit -# squareLogo: | -# this is an invalid -# base64 logo with -# line feeds -# productLogo: | -# this is an invalid -# base64 logo with -# line feeds - -oauth: - user: - authorities: - - openid - clients: - hawkbit: - id: hawkbit - secret: hawkbitsecret - authorized-grant-types: password,implicit,authorization_code,client_credentials,refresh_token - scope: READ_TARGET,CREATE_TARGET,UPDATE_TARGET,DELETE_TARGET,READ_REPOSITORY,UPDATE_REPOSITORY,CREATE_REPOSITORY,DELETE_REPOSITORY,SYSTEM_MONITOR,SYSTEM_DIAG,SYSTEM_ADMIN,DOWNLOAD_REPOSITORY_ARTIFACT,TENANT_CONFIGURATION,ROLLOUT_MANAGEMENT,openid,uaa.user,uaa.admin,password.write,scim.userids,cloud_controller.admin,scim.read,scim.write - authorities: uaa.admin,openid,scim.read,zones.uaa.admin,scim.userids,scim.zones - autoapprove: true -``` - -## Dockerize UAA -The UAA is not shipped as a docker container unfortunately so you build the UAA as docker image by your own -Dockerfile -``` -FROM tomcat:8.5.6-jre8 -COPY uaa.war /usr/local/tomcat/webapps/uaa.war -RUN echo "CLOUD_FOUNDRY_CONFIG_PATH=/etc/uaa" >> /usr/local/tomcat/conf/catalina.properties -``` -The UAA configuration is based on the `uaa.yml` file which can be placed into the `/etc/uaa/uaa.yml` on the docker host system. - -After building the `uaa` docker image you can then start the `uaa-server` using docker -``` -docker run -p 8080:8080 -d -e "SPRING_PROFILES_ACTIVE=hsqldb" -v "/etc/uaa:/etc/uaa" uaa -``` diff --git a/extensions/hawkbit-extension-uaa/pom.xml b/extensions/hawkbit-extension-uaa/pom.xml deleted file mode 100644 index 54569b4a5..000000000 --- a/extensions/hawkbit-extension-uaa/pom.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - 4.0.0 - - - org.eclipse.hawkbit - hawkbit-extensions-parent - 0.2.0-SNAPSHOT - - - hawkbit-extension-uaa - - - - org.eclipse.hawkbit - hawkbit-security-core - ${project.version} - - - org.springframework.security - spring-security-jwt - - - org.springframework.boot - spring-boot - - - org.springframework.boot - spring-boot-autoconfigure - - - org.springframework.boot - spring-boot-starter-security - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-jetty - - - org.springframework.security.oauth - spring-security-oauth2 - - - com.google.guava - guava - - - org.springframework.boot - spring-boot-starter-test - test - - - hawkBit :: Extensions :: UAA Integration - diff --git a/extensions/hawkbit-extension-uaa/src/main/java/org/eclipse/hawkbit/security/uaa/UaaClientProperties.java b/extensions/hawkbit-extension-uaa/src/main/java/org/eclipse/hawkbit/security/uaa/UaaClientProperties.java deleted file mode 100644 index ee3e281eb..000000000 --- a/extensions/hawkbit-extension-uaa/src/main/java/org/eclipse/hawkbit/security/uaa/UaaClientProperties.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.security.uaa; - -import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.NestedConfigurationProperty; -import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; - -/** - * Configuration properties for setting the UAA OAUTH2 client-properties and - * resource-properties. - * - *
-    uaa.client.clientId=app
-    uaa.client.clientSecret=appsecret
-    uaa.client.accessTokenUri=http://localhost:8080/uaa/oauth/token
-    uaa.client.userAuthorizationUri=http://localhost:8080/uaa/oauth/authorize
-    uaa.client.clientAuthenticationScheme=form
-    uaa.resource.userInfoUri=http://localhost:8080/uaa/userinfo
-    uaa.resource.jwt.keyValue=abc
- * 
- */ -@ConfigurationProperties("uaa") -public class UaaClientProperties { - - @NestedConfigurationProperty - private final AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails(); - - @NestedConfigurationProperty - private final ResourceServerProperties resource = new ResourceServerProperties(); - - public AuthorizationCodeResourceDetails getClient() { - return client; - } - - public ResourceServerProperties getResource() { - return resource; - } -} diff --git a/extensions/hawkbit-extension-uaa/src/main/java/org/eclipse/hawkbit/security/uaa/UaaOAuthAutoConfiguration.java b/extensions/hawkbit-extension-uaa/src/main/java/org/eclipse/hawkbit/security/uaa/UaaOAuthAutoConfiguration.java deleted file mode 100644 index 8ca4f8d7f..000000000 --- a/extensions/hawkbit-extension-uaa/src/main/java/org/eclipse/hawkbit/security/uaa/UaaOAuthAutoConfiguration.java +++ /dev/null @@ -1,199 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.security.uaa; - -import java.io.IOException; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; - -import org.eclipse.hawkbit.im.authentication.UserAuthenticationFilter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.context.embedded.FilterRegistrationBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.oauth2.client.OAuth2ClientContext; -import org.springframework.security.oauth2.client.OAuth2RestTemplate; -import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter; -import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter; -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client; -import org.springframework.security.oauth2.provider.authentication.BearerTokenExtractor; -import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager; -import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter; -import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter; -import org.springframework.security.oauth2.provider.token.DefaultTokenServices; -import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; -import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; -import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; -import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; - -import com.google.common.base.Throwables; - -/** - * The Spring-Auto-Configuration implementation for integrating the UAA - * (https://github.com/cloudfoundry/uaa) as an identity management. - * - * To use the OAUTH2 redirect login flow the - * {@link OAuth2ClientAuthenticationProcessingFilter} is listing on the path - * {@code /uaalogin}. This will then re-direct to the configured UAA login form. - * - * The {@link UserAuthenticationFilter} implementation delegates to the - * {@link OAuth2AuthenticationProcessingFilter} which validates given bearer - * tokens in the {@code Authorization} header ' - * {@code Authorization: bearer eyJhbGciOiJIUzI1NiIsImtpZCI6Imx}' to - * authenticate bearer tokens for the REST API. Only the signed token is - * verified, there is no extra round-trip back to the OAUTH2-Server (UAA). - * - *

- * Example configuration: - * - *
-    uaa.client.clientId=app
-    uaa.client.clientSecret=appsecret
-    uaa.client.accessTokenUri=http://localhost:8080/uaa/oauth/token
-    uaa.client.userAuthorizationUri=http://localhost:8080/uaa/oauth/authorize
-    uaa.client.clientAuthenticationScheme=form
-    uaa.resource.userInfoUri=http://localhost:8080/uaa/userinfo
-    uaa.resource.jwt.keyValue=abc
- * 
- * - */ -@EnableOAuth2Client -@EnableConfigurationProperties(UaaClientProperties.class) -@Order(Ordered.HIGHEST_PRECEDENCE) -public class UaaOAuthAutoConfiguration extends WebSecurityConfigurerAdapter { - - @Autowired - private OAuth2ClientContext oauth2ClientContext; - - @Autowired - private UaaClientProperties uaaClientResources; - - @Override - protected void configure(final HttpSecurity http) throws Exception { - http.regexMatcher("\\/uaalogin.*").addFilterBefore(ssoFilter("/uaalogin"), BasicAuthenticationFilter.class); - } - - /** - * @return The {@link UserPrincipalInfoTokenServices} which extract - * authentication, principal and authorities information from an JWT - * access token. - */ - @Bean - public UserPrincipalInfoTokenServices userPrincipalInfoTokenServices() { - return new UserPrincipalInfoTokenServices(uaaClientResources.getResource().getUserInfoUri(), - uaaClientResources.getClient().getClientId(), oauth2ClientContext); - } - - /** - * @return The {@link JwtTokenStore} verifies access tokens and extract - * authentication and authorities from it. - */ - @Bean - public JwtTokenStore jwtTokenStore() { - final DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter(); - accessTokenConverter.setUserTokenConverter(userPrincipalInfoTokenServices()); - final JwtAccessTokenConverter jwtTokenEnhancer = new JwtAccessTokenConverter(); - jwtTokenEnhancer.setAccessTokenConverter(accessTokenConverter); - jwtTokenEnhancer.setSigningKey(uaaClientResources.getResource().getJwt().getKeyValue()); - jwtTokenEnhancer.setVerifierKey(uaaClientResources.getResource().getJwt().getKeyValue()); - try { - jwtTokenEnhancer.afterPropertiesSet(); - } catch (final Exception e) { - throw Throwables.propagate(e); - } - return new JwtTokenStore(jwtTokenEnhancer); - } - - /** - * @param filter - * the {@link OAuth2ClientContextFilter} to register. - * @return the Spring {@link FilterRegistrationBean} to register a filter in - * the spring filter-chain - */ - @Bean - public FilterRegistrationBean oauth2ClientFilterRegistration(final OAuth2ClientContextFilter filter) { - final FilterRegistrationBean registration = new FilterRegistrationBean(); - registration.setFilter(filter); - registration.setOrder(-100); - return registration; - } - - /** - * @return The adapter for the hawkBit {@link UserAuthenticationFilter} - * which delegates to the oAuth-filter mechanism to authenticate JWT - * bearer tokens in the hawkBit security filter chain. - */ - @Bean - public UserAuthenticationFilter userAuthenticationFilter() { - return new UserAuthenticationFilterAdapter(resourceOAuthFilter()); - } - - private Filter resourceOAuthFilter() { - final DefaultTokenServices remoteTokenService = new DefaultTokenServices(); - remoteTokenService.setTokenStore(jwtTokenStore()); - final OAuth2AuthenticationManager oauth2Manager = new OAuth2AuthenticationManager(); - oauth2Manager.setTokenServices(remoteTokenService); - final OAuth2AuthenticationProcessingFilter oAuth2AuthenticationProcessingFilter = new OAuth2AuthenticationProcessingFilter(); - oAuth2AuthenticationProcessingFilter.setTokenExtractor(new BearerTokenExtractor()); - oAuth2AuthenticationProcessingFilter.setAuthenticationManager(oauth2Manager); - return oAuth2AuthenticationProcessingFilter; - } - - private Filter ssoFilter(final String path) { - final OAuth2ClientAuthenticationProcessingFilter oAuth2ClientAuthenticationFilter = new OAuth2ClientAuthenticationProcessingFilter( - path); - final SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler(); - oAuth2ClientAuthenticationFilter.setAuthenticationSuccessHandler(successHandler); - successHandler.setAlwaysUseDefaultTargetUrl(true); - successHandler.setDefaultTargetUrl("/UI"); - final OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate(uaaClientResources.getClient(), - oauth2ClientContext); - oAuth2ClientAuthenticationFilter.setRestTemplate(oAuth2RestTemplate); - final UserPrincipalInfoTokenServices tokenServices = new UserPrincipalInfoTokenServices( - uaaClientResources.getResource().getUserInfoUri(), uaaClientResources.getClient().getClientId(), - oauth2ClientContext); - tokenServices.setRestTemplate(oAuth2RestTemplate); - tokenServices.setAuthoritiesExtractor(tokenServices); - oAuth2ClientAuthenticationFilter.setTokenServices(tokenServices); - return oAuth2ClientAuthenticationFilter; - } - - private static final class UserAuthenticationFilterAdapter implements UserAuthenticationFilter { - private final Filter delegate; - - private UserAuthenticationFilterAdapter(final Filter delegate) { - this.delegate = delegate; - } - - @Override - public void init(final FilterConfig filterConfig) throws ServletException { - delegate.init(filterConfig); - } - - @Override - public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) - throws IOException, ServletException { - delegate.doFilter(request, response, chain); - } - - @Override - public void destroy() { - delegate.destroy(); - } - } -} diff --git a/extensions/hawkbit-extension-uaa/src/main/java/org/eclipse/hawkbit/security/uaa/UserPrincipalInfoTokenServices.java b/extensions/hawkbit-extension-uaa/src/main/java/org/eclipse/hawkbit/security/uaa/UserPrincipalInfoTokenServices.java deleted file mode 100644 index 078bc0019..000000000 --- a/extensions/hawkbit-extension-uaa/src/main/java/org/eclipse/hawkbit/security/uaa/UserPrincipalInfoTokenServices.java +++ /dev/null @@ -1,105 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.security.uaa; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.eclipse.hawkbit.im.authentication.UserPrincipal; -import org.springframework.boot.autoconfigure.security.oauth2.resource.AuthoritiesExtractor; -import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.jwt.Jwt; -import org.springframework.security.jwt.JwtHelper; -import org.springframework.security.oauth2.client.OAuth2ClientContext; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.common.util.JsonParser; -import org.springframework.security.oauth2.common.util.JsonParserFactory; -import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter; - -/** - * Implementation which maps principals from the OAUTH2 access tokens to the - * hawkBit {@link UserPrincipal}, so hawkBit is able to work with the user and - * tenant information. Additional extracting the {@code scope}-list from the JWT - * into {@link GrantedAuthority}. - * - * This implementation concentrates all necessary authentication, principal and - * authorities mapping within the OAUTH2 workflow, e.g. using redirect login - * form or using the REST-API with a access bearer token. - */ -public class UserPrincipalInfoTokenServices extends UserInfoTokenServices - implements UserAuthenticationConverter, AuthoritiesExtractor { - - private final OAuth2ClientContext oauth2ClientContext; - private final JsonParser jsonParser = JsonParserFactory.create(); - - /** - * Constructor. - * - * @param userInfoEndpointUrl - * the OAUTH2 info endpoint to retrieve user information - * @param clientId - * the OAUTH2 client-id to execute the user info endpoint - * @param oauth2ClientContext - * the spring {@link OAuth2ClientContext} - */ - public UserPrincipalInfoTokenServices(final String userInfoEndpointUrl, final String clientId, - final OAuth2ClientContext oauth2ClientContext) { - super(userInfoEndpointUrl, clientId); - this.oauth2ClientContext = oauth2ClientContext; - } - - @Override - protected Object getPrincipal(final Map map) { - final String username = String.valueOf(map.get("user_name")); - final String firstname = String.valueOf(map.get("given_name")); - final String lastname = String.valueOf(map.get("family_name")); - final String email = String.valueOf(map.get("email")); - final String zoneId = String.valueOf(getAccessTokenMap().get("zid")); - return new UserPrincipal(username, firstname, lastname, username, email, zoneId); - } - - @Override - public Map convertUserAuthentication(final Authentication userAuthentication) { - throw new UnsupportedOperationException("converting an authentication object to a map is not implemented"); - } - - @Override - @SuppressWarnings("unchecked") - public Authentication extractAuthentication(final Map map) { - final Object principal = getPrincipal((Map) map); - return new UsernamePasswordAuthenticationToken(principal, "N/A", extractAuthorities((Map) map)); - } - - @Override - public List extractAuthorities(final Map map) { - final Map accessTokenMap; - if (map.containsKey("scope")) { - accessTokenMap = map; - } else { - accessTokenMap = getAccessTokenMap(); - } - @SuppressWarnings("unchecked") - final List scopes = (List) accessTokenMap.get("scope"); - return scopes.stream().map(scope -> new SimpleGrantedAuthority(scope)).collect(Collectors.toList()); - - } - - private Map getAccessTokenMap() { - final Map accessTokenMap; - final OAuth2AccessToken accessToken = oauth2ClientContext.getAccessToken(); - final Jwt decode = JwtHelper.decode(accessToken.getValue()); - accessTokenMap = jsonParser.parseMap(decode.getClaims()); - return accessTokenMap; - } -} diff --git a/extensions/hawkbit-extension-uaa/src/main/resources/META-INF/spring.factories b/extensions/hawkbit-extension-uaa/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 90e1d3b47..000000000 --- a/extensions/hawkbit-extension-uaa/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -# Auto Configure -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.eclipse.hawkbit.security.uaa.UaaOAuthAutoConfiguration diff --git a/extensions/pom.xml b/extensions/pom.xml deleted file mode 100644 index 6d47eaa45..000000000 --- a/extensions/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - 4.0.0 - - org.eclipse.hawkbit - hawkbit-parent - 0.2.0-SNAPSHOT - - hawkbit-extensions-parent - pom - hawkBit :: Extensions - Parent pom for hawkBit extensions - - - - eclipserel - hawkBit Repository - Release - https://repo.eclipse.org/content/repositories/hawkbit-releases - - - eclipsesnap - hawkBit Repository - Snapshots - https://repo.eclipse.org/content/repositories/hawkbit-snapshots - - - - - ${project.basedir}/../../target/ - - - - hawkbit-extension-uaa - hawkbit-extension-artifact-repository-mongo - hawkbit-extension-artifact-repository-s3 - - - diff --git a/pom.xml b/pom.xml index 13b411355..738e4e1b7 100644 --- a/pom.xml +++ b/pom.xml @@ -48,8 +48,6 @@ hawkbit-test-report hawkbit-runtime hawkbit-starters - examples - extensions @@ -209,32 +207,6 @@ com.mycila license-maven-plugin - 2.11 - -
licenses/LICENSE_HEADER_TEMPLATE_BOSCH.txt
- - licenses/LICENSE_HEADER_TEMPLATE_SIEMENS.txt - - - **/README - 3rd-dependencies/** - **/.git* - .git* - **/*.sql - **/*.sql - eclipse_codeformatter.xml - **/addons.scss - **/VAADIN/widgetsets/** - .sonar - **/Dockerfile - **/.sonar/** - docs/src/main/resources/** - **/LICENSE* - - - JAVADOC_STYLE - -
org.apache.maven.plugins @@ -319,6 +291,36 @@ + + com.mycila + license-maven-plugin + 2.11 + +
licenses/LICENSE_HEADER_TEMPLATE_BOSCH.txt
+ + licenses/LICENSE_HEADER_TEMPLATE_SIEMENS.txt + + + **/README + 3rd-dependencies/** + **/.git* + .git* + **/*.sql + **/*.sql + eclipse_codeformatter.xml + **/addons.scss + **/VAADIN/widgetsets/** + .sonar + **/Dockerfile + **/.sonar/** + docs/src/main/resources/** + **/LICENSE* + + + JAVADOC_STYLE + +
+
org.eclipse.m2e lifecycle-mapping