Initial check in accordance with Parallel IP
This commit is contained in:
105
3rd-dependencies/compile.txt
Executable file
105
3rd-dependencies/compile.txt
Executable file
@@ -0,0 +1,105 @@
|
||||
aopalliance:aopalliance:jar:1.0:compile
|
||||
com.fasterxml.jackson.core:jackson-annotations:jar:2.5.0:compile
|
||||
com.fasterxml.jackson.core:jackson-core:jar:2.5.0:compile
|
||||
com.fasterxml.jackson.core:jackson-databind:jar:2.5.0:compile
|
||||
com.fasterxml:classmate:jar:1.3.0:compile
|
||||
com.google.guava:guava:jar:18.0:compile
|
||||
com.h2database:h2:jar:1.4.186:compile
|
||||
com.rabbitmq:amqp-client:jar:3.5.5:compile
|
||||
com.vaadin.external.atmosphere:atmosphere-runtime:jar:2.2.7.vaadin1:compile
|
||||
com.vaadin.external.flute:flute:jar:1.3.0.gg2:compile
|
||||
com.vaadin.external.google:guava:jar:16.0.1.vaadin1:compile
|
||||
com.vaadin.external.slf4j:vaadin-slf4j-jdk14:jar:1.6.1:compile
|
||||
com.vaadin.external.streamhtmlparser:streamhtmlparser-jsilver:jar:0.0.10.vaadin1:compile
|
||||
com.vaadin:vaadin-push:jar:7.5.7:compile
|
||||
com.vaadin:vaadin-sass-compiler:jar:0.9.12:compile
|
||||
com.vaadin:vaadin-server:jar:7.5.7:compile
|
||||
com.vaadin:vaadin-shared:jar:7.5.7:compile
|
||||
com.vaadin:vaadin-spring-boot:jar:1.0.0:compile
|
||||
com.vaadin:vaadin-spring:jar:1.0.0:compile
|
||||
com.vaadin:vaadin-themes:jar:7.5.7:compile
|
||||
commons-io:commons-io:jar:2.4:compile
|
||||
cz.jirutka.rsql:rsql-parser:jar:2.0.0:compile
|
||||
io.springfox:springfox-core:jar:2.0.3:compile
|
||||
io.springfox:springfox-schema:jar:2.0.3:compile
|
||||
io.springfox:springfox-spi:jar:2.0.3:compile
|
||||
io.springfox:springfox-spring-web:jar:2.0.3:compile
|
||||
io.springfox:springfox-swagger-common:jar:2.0.3:compile
|
||||
io.springfox:springfox-swagger2:jar:2.0.3:compile
|
||||
io.swagger:swagger-annotations:jar:1.5.0:compile
|
||||
io.swagger:swagger-models:jar:1.5.0:compile
|
||||
javax.servlet:javax.servlet-api:jar:3.1.0:compile
|
||||
javax.transaction:javax.transaction-api:jar:1.2:compile
|
||||
javax.validation:validation-api:jar:1.1.0.Final:compile
|
||||
joda-time:joda-time:jar:2.5:compile
|
||||
net._01001111:jlorem:jar:1.1:compile
|
||||
org.apache.commons:commons-lang3:jar:3.4:compile
|
||||
org.apache.commons:commons-pool2:jar:2.2:compile
|
||||
org.apache.logging.log4j:log4j-api:jar:2.1:compile
|
||||
org.apache.logging.log4j:log4j-core:jar:2.1:compile
|
||||
org.apache.logging.log4j:log4j-slf4j-impl:jar:2.1:compile
|
||||
org.apache.tomcat:tomcat-jdbc:jar:8.0.28:compile
|
||||
org.apache.tomcat:tomcat-juli:jar:8.0.28:compile
|
||||
org.aspectj:aspectjrt:jar:1.8.5:compile
|
||||
org.aspectj:aspectjweaver:jar:1.8.5:compile
|
||||
org.eclipse.persistence:javax.persistence:jar:2.1.0:compile
|
||||
org.eclipse.persistence:org.eclipse.persistence.antlr:jar:2.6.0:compile
|
||||
org.eclipse.persistence:org.eclipse.persistence.asm:jar:2.6.0:compile
|
||||
org.eclipse.persistence:org.eclipse.persistence.core:jar:2.6.0:compile
|
||||
org.eclipse.persistence:org.eclipse.persistence.jpa.jpql:jar:2.6.0:compile
|
||||
org.eclipse.persistence:org.eclipse.persistence.jpa:jar:2.6.0:compile
|
||||
org.flywaydb:flyway-core:jar:3.1:compile
|
||||
org.glassfish:javax.json:jar:1.0.4:compile
|
||||
org.hibernate:hibernate-validator:jar:5.2.2.Final:compile
|
||||
org.jboss.logging:jboss-logging:jar:3.2.1.Final:compile
|
||||
org.jsoup:jsoup:jar:1.8.1:compile
|
||||
org.mapstruct:mapstruct:jar:1.0.0.Beta4:compile
|
||||
org.mongodb:mongo-java-driver:jar:3.0.2:compile
|
||||
org.objenesis:objenesis:jar:2.1:compile
|
||||
org.slf4j:jcl-over-slf4j:jar:1.7.12:compile
|
||||
org.slf4j:jul-to-slf4j:jar:1.7.12:compile
|
||||
org.slf4j:slf4j-api:jar:1.7.7:compile
|
||||
org.springframework.amqp:spring-amqp:jar:1.4.6.RELEASE:compile
|
||||
org.springframework.amqp:spring-rabbit:jar:1.4.6.RELEASE:compile
|
||||
org.springframework.boot:spring-boot-autoconfigure:jar:1.2.7.RELEASE:compile
|
||||
org.springframework.boot:spring-boot-starter-aop:jar:1.2.7.RELEASE:compile
|
||||
org.springframework.boot:spring-boot-starter-data-jpa:jar:1.2.7.RELEASE:compile
|
||||
org.springframework.boot:spring-boot-starter-jdbc:jar:1.2.7.RELEASE:compile
|
||||
org.springframework.boot:spring-boot-starter-log4j2:jar:1.2.7.RELEASE:compile
|
||||
org.springframework.boot:spring-boot-starter-web:jar:1.2.7.RELEASE:compile
|
||||
org.springframework.boot:spring-boot-starter:jar:1.2.7.RELEASE:compile
|
||||
org.springframework.boot:spring-boot:jar:1.2.7.RELEASE:compile
|
||||
org.springframework.data:spring-data-commons:jar:1.10.1.RELEASE:compile
|
||||
org.springframework.data:spring-data-jpa:jar:1.8.1.RELEASE:compile
|
||||
org.springframework.data:spring-data-mongodb:jar:1.7.1.RELEASE:compile
|
||||
org.springframework.data:spring-data-redis:jar:1.5.1.RELEASE:compile
|
||||
org.springframework.hateoas:spring-hateoas:jar:0.16.0.RELEASE:compile
|
||||
org.springframework.plugin:spring-plugin-core:jar:1.1.0.RELEASE:compile
|
||||
org.springframework.plugin:spring-plugin-metadata:jar:1.2.0.RELEASE:compile
|
||||
org.springframework.retry:spring-retry:jar:1.1.2.RELEASE:compile
|
||||
org.springframework.security:spring-security-aspects:jar:3.2.8.RELEASE:compile
|
||||
org.springframework.security:spring-security-config:jar:3.2.8.RELEASE:compile
|
||||
org.springframework.security:spring-security-core:jar:3.2.8.RELEASE:compile
|
||||
org.springframework.security:spring-security-web:jar:3.2.8.RELEASE:compile
|
||||
org.springframework:spring-aop:jar:4.1.8.RELEASE:compile
|
||||
org.springframework:spring-aspects:jar:4.1.8.RELEASE:compile
|
||||
org.springframework:spring-beans:jar:4.1.8.RELEASE:compile
|
||||
org.springframework:spring-context-support:jar:4.1.8.RELEASE:compile
|
||||
org.springframework:spring-context:jar:4.1.8.RELEASE:compile
|
||||
org.springframework:spring-core:jar:4.1.8.RELEASE:compile
|
||||
org.springframework:spring-expression:jar:4.1.8.RELEASE:compile
|
||||
org.springframework:spring-jdbc:jar:4.1.8.RELEASE:compile
|
||||
org.springframework:spring-messaging:jar:4.1.8.RELEASE:compile
|
||||
org.springframework:spring-orm:jar:4.1.8.RELEASE:compile
|
||||
org.springframework:spring-tx:jar:4.1.8.RELEASE:compile
|
||||
org.springframework:spring-web:jar:4.1.8.RELEASE:compile
|
||||
org.springframework:spring-webmvc:jar:4.1.8.RELEASE:compile
|
||||
org.vaadin.addons.lazyquerycontainer:vaadin-lazyquerycontainer:jar:7.4.0.1:compile
|
||||
org.vaadin.addons:flexibleoptiongroup:jar:2.2.0:compile
|
||||
org.vaadin.addons:tokenfield:jar:7.0.1:compile
|
||||
org.vaadin.spring.addons:vaadin-spring-addon-eventbus:jar:0.0.6.RELEASE:compile
|
||||
org.vaadin.spring.extensions:vaadin-spring-ext-core:jar:0.0.6.RELEASE:compile
|
||||
org.vaadin.spring.extensions:vaadin-spring-ext-security:jar:0.0.6.RELEASE:compile
|
||||
org.w3c.css:sac:jar:1.3:compile
|
||||
org.yaml:snakeyaml:jar:1.14:compile
|
||||
redis.clients:jedis:jar:2.5.2:compile
|
||||
8
3rd-dependencies/listDeps.sh
Executable file
8
3rd-dependencies/listDeps.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
# This script
|
||||
cd ..
|
||||
mvn dependency:list -DexcludeGroupIds=org.eclipse.hawkbit -Dsort=true -DoutputFile=dependencies.txt
|
||||
find . -name dependencies.txt|while read i; do cat $i;done|grep '.*:.*:compile'|sort|uniq > 3rd-dependencies/compile.txt
|
||||
find . -name dependencies.txt|while read i; do cat $i;done|grep '.*:.*:test'|sort|uniq > 3rd-dependencies/test.txt
|
||||
find . -name dependencies.txt|while read i; do cat $i;done|grep '.*:.*:provided'|sort|uniq > 3rd-dependencies/provided.txt
|
||||
find . -name dependencies.txt|while read i; do rm $i;done
|
||||
cd 3rd-dependencies/
|
||||
6
3rd-dependencies/provided.txt
Executable file
6
3rd-dependencies/provided.txt
Executable file
@@ -0,0 +1,6 @@
|
||||
javax.servlet:javax.servlet-api:jar:3.1.0:provided
|
||||
org.apache.tomcat.embed:tomcat-embed-core:jar:8.0.28:provided
|
||||
org.apache.tomcat.embed:tomcat-embed-el:jar:8.0.28:provided
|
||||
org.apache.tomcat.embed:tomcat-embed-logging-juli:jar:8.0.28:provided
|
||||
org.apache.tomcat.embed:tomcat-embed-websocket:jar:8.0.28:provided
|
||||
org.springframework.boot:spring-boot-starter-tomcat:jar:1.2.7.RELEASE:provided
|
||||
55
3rd-dependencies/test.txt
Executable file
55
3rd-dependencies/test.txt
Executable file
@@ -0,0 +1,55 @@
|
||||
com.fasterxml.jackson.core:jackson-core:jar:2.5.0:test
|
||||
com.fasterxml.jackson.core:jackson-databind:jar:2.5.0:test
|
||||
com.github.fge:btf:jar:1.2:test
|
||||
com.github.fge:jackson-coreutils:jar:1.6:test
|
||||
com.github.fge:json-patch:jar:1.7:test
|
||||
com.github.fge:msg-simple:jar:1.1:test
|
||||
com.google.code.findbugs:jsr305:jar:2.0.1:test
|
||||
com.h2database:h2:jar:1.4.186:test
|
||||
com.jayway.jsonpath:json-path:jar:0.9.1:test
|
||||
commons-beanutils:commons-beanutils-core:jar:1.8.3:test
|
||||
commons-io:commons-io:jar:2.4:test
|
||||
commons-logging:commons-logging:jar:1.1.1:test
|
||||
de.flapdoodle.embed:de.flapdoodle.embed.mongo:jar:1.50.0:test
|
||||
de.flapdoodle.embed:de.flapdoodle.embed.process:jar:1.50.0:test
|
||||
io.swagger:swagger-annotations:jar:1.5.0:test
|
||||
javax.el:javax.el-api:jar:2.2.4:test
|
||||
junit:junit:jar:4.12:test
|
||||
net.java.dev.jna:jna-platform:jar:4.0.0:test
|
||||
net.java.dev.jna:jna:jar:3.3.0:test
|
||||
net.java.dev.jna:jna:jar:4.0.0:test
|
||||
net.java.dev.jna:jna:jar:platform:3.3.0:test
|
||||
net.minidev:json-smart:jar:1.2:test
|
||||
org.apache.commons:commons-compress:jar:1.3:test
|
||||
org.apache.commons:commons-lang3:jar:3.1:test
|
||||
org.apache.tika:tika-core:jar:1.7:test
|
||||
org.aspectj:aspectjrt:jar:1.8.5:test
|
||||
org.atteo:evo-inflector:jar:1.2.1:test
|
||||
org.easytesting:fest-assert-core:jar:2.0M10:test
|
||||
org.easytesting:fest-assert:jar:1.4:test
|
||||
org.easytesting:fest-util:jar:1.2.5:test
|
||||
org.hamcrest:hamcrest-core:jar:1.3:test
|
||||
org.hamcrest:hamcrest-library:jar:1.3:test
|
||||
org.json:json:jar:20141113:test
|
||||
org.jvnet.jaxb2_commons:jaxb2-basics-runtime:jar:0.9.3:test
|
||||
org.mariadb.jdbc:mariadb-java-client:jar:1.2.3:test
|
||||
org.mockito:mockito-core:jar:1.10.19:test
|
||||
org.objenesis:objenesis:jar:2.1:test
|
||||
org.springframework.boot:spring-boot-starter-test:jar:1.2.7.RELEASE:test
|
||||
org.springframework.data:spring-data-rest-core:jar:2.3.1.RELEASE:test
|
||||
org.springframework.data:spring-data-rest-webmvc:jar:2.3.1.RELEASE:test
|
||||
org.springframework.hateoas:spring-hateoas:jar:0.16.0.RELEASE:test
|
||||
org.springframework.plugin:spring-plugin-core:jar:1.1.0.RELEASE:test
|
||||
org.springframework.security:spring-security-aspects:jar:3.2.8.RELEASE:test
|
||||
org.springframework.security:spring-security-config:jar:3.2.8.RELEASE:test
|
||||
org.springframework.security:spring-security-web:jar:3.2.8.RELEASE:test
|
||||
org.springframework:spring-context-support:jar:4.1.8.RELEASE:test
|
||||
org.springframework:spring-test:jar:4.1.8.RELEASE:test
|
||||
org.springframework:spring-web:jar:4.1.8.RELEASE:test
|
||||
org.springframework:spring-webmvc:jar:4.1.8.RELEASE:test
|
||||
ru.yandex.qatools.allure:allure-java-adaptor-api:jar:1.4.15:test
|
||||
ru.yandex.qatools.allure:allure-java-annotations:jar:1.4.15:test
|
||||
ru.yandex.qatools.allure:allure-java-aspects:jar:1.4.15:test
|
||||
ru.yandex.qatools.allure:allure-junit-adaptor:jar:1.4.15:test
|
||||
ru.yandex.qatools.allure:allure-model:jar:1.4.15:test
|
||||
ru.yandex.qatools.properties:properties-loader:jar:1.5:test
|
||||
70
CONTRUBUTING.md
Executable file
70
CONTRUBUTING.md
Executable file
@@ -0,0 +1,70 @@
|
||||
# Contributing to eclipse hawkBit
|
||||
|
||||
:+1: First off, thanks for taking the time to contribute! We really appreciate this. :+1:
|
||||
|
||||
Please read this if you intend to contribute to the project.
|
||||
|
||||
## Code Conventions
|
||||
|
||||
* Java files:
|
||||
* we follow the standard eclipse IDE (built in) code formatter with the following changes:
|
||||
* Tab policy: spaces only: 4
|
||||
* XML files:
|
||||
* we follow the standard eclipse IDE XML formatter with the following changes:
|
||||
* Indent using spaces only: 3
|
||||
* SCSS files:
|
||||
* we follow the standard [scss-lint](https://github.com/brigade/scss-lint/) rules with the following exception:
|
||||
* disabled rules: ImportantRule, PropertySortOrder
|
||||
* Sonarqube:
|
||||
* Our rule set is defined [here](http://sonar.eu-gb.mybluemix.net)
|
||||
|
||||
## Legal considerations for your contribution
|
||||
|
||||
The following steps are necessary to comply with the Eclipse Foundation's IP policy.
|
||||
|
||||
Please also read [this](http://wiki.eclipse.org/Development_Resources/Contributing_via_Git)
|
||||
|
||||
In order for any contributions to be accepted you MUST do the following things.
|
||||
|
||||
* Sign the [Eclipse Foundation Contributor License Agreement](http://www.eclipse.org/legal/CLA.php).
|
||||
To sign the Eclipse CLA you need to:
|
||||
|
||||
* Obtain an Eclipse Foundation userid. Anyone who currently uses Eclipse Bugzilla or Gerrit systems already has one of those.
|
||||
If you don’t, you need to [register](https://dev.eclipse.org/site_login/createaccount.php).
|
||||
|
||||
* Login into the [projects portal](https://projects.eclipse.org/), select “My Account”, and then the “Contributor License Agreement” tab.
|
||||
|
||||
* Add your github username in your Eclipse Foundation account settings. Log in it to Eclipse and go to account settings.
|
||||
|
||||
* "Sign-off" your commits (NOTE! This is only necessary if contributing to the vertx-core project)
|
||||
|
||||
Every commit you make in your patch or pull request MUST be "signed off".
|
||||
|
||||
You do this by adding the `-s` flag when you make the commit(s), e.g.
|
||||
|
||||
git commit -s -m "Shave the yak some more"
|
||||
|
||||
## Making your changes
|
||||
|
||||
* Fork the repository on GitHub
|
||||
* Create a new branch for your changes
|
||||
* Make your changes
|
||||
* Make sure you include tests
|
||||
* Make sure the tests pass after your changes
|
||||
* Commit your changes into that branch
|
||||
* Use descriptive and meaningful commit messages
|
||||
* If you have a lot of commits squash them into a single commit
|
||||
* Make sure you use the `-s` flag when committing as explained above.
|
||||
* Push your changes to your branch in your forked repository
|
||||
|
||||
## Submitting the changes
|
||||
|
||||
Submit a pull request via the normal GitHub UI (desktop or web).
|
||||
|
||||
## After submitting
|
||||
|
||||
* Do not use your branch for any other development, otherwise further changes that you make will be visible in the PR.
|
||||
|
||||
# Further information
|
||||
|
||||
* [Eclipse Project Page](http://projects.eclipse.org/projects/iot.hawkbit)
|
||||
131
DDIA.md
Executable file
131
DDIA.md
Executable file
@@ -0,0 +1,131 @@
|
||||
## Direct Device Integration API (HTTP)
|
||||
This API is based on HTTP standards and based on a polling mechanism.
|
||||
The hawkbit update server provides REST resources which are consumed by the device to retrieve software update tasks.
|
||||
|
||||
|
||||
##### Base Poll Resource
|
||||
```
|
||||
GET /{tenant}/controller/v1/{controllerId}
|
||||
```
|
||||
In the answer to the baseUrl polling the backend can send action links. A possible action is a deploy command.
|
||||
The client makes a GET request on the given link:
|
||||
|
||||
_Example Response_
|
||||
```
|
||||
{
|
||||
"config": {
|
||||
"polling": {
|
||||
"sleep": "00:05:00"
|
||||
}
|
||||
},
|
||||
"_links": {
|
||||
"deploymentBase": {
|
||||
"href": "http://localhost:8080/default/controller/v1/example/deploymentBase/1?c=644088541"
|
||||
},
|
||||
"configData": {
|
||||
"href": "http://localhost:8080/default/controller/v1/example/configData"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### Deployment Base Resource
|
||||
```
|
||||
GET /{tenant}/controller/v1/{controllerId}/deploymentBase/{id}
|
||||
```
|
||||
_Example Response_
|
||||
```
|
||||
{
|
||||
"deployment": {
|
||||
"download": "forced",
|
||||
"update": "forced",
|
||||
"chunks": [
|
||||
{
|
||||
"part": "os",
|
||||
"version": "1.0.0",
|
||||
"name": "Linux",
|
||||
"artifacts": [
|
||||
{
|
||||
"filename": "linux.zip",
|
||||
"hashes": {
|
||||
"sha1": "46fc56de883ec027759d8513458fe1010aa7e793",
|
||||
"md5": "5813e9655bd6871d0c25b8d510fd8605"
|
||||
},
|
||||
"size": 52167,
|
||||
"_links": {
|
||||
"download": {
|
||||
"href": "http://localhost:8080/default/controller/v1/example/softwaremodules/1/artifacts/linux.zip"
|
||||
},
|
||||
"md5sum": {
|
||||
"href": "http://localhost:8080/default/controller/v1/example/softwaremodules/1/artifacts/linux.zip.MD5SUM"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"id": "1"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
##### Deployment Feedback Resource
|
||||
To every deployment the client can post feedback back to the update-server about the deployment status.
|
||||
```
|
||||
POST /{tenant}/controller/v1/{controllerId}/deploymentBase/{id}/feedback
|
||||
Content-Type: application/json
|
||||
```
|
||||
_Example Body Deployment Success_
|
||||
```
|
||||
{
|
||||
"id": 1,
|
||||
"time": "20140511T121314",
|
||||
"status": {
|
||||
"execution": "closed",
|
||||
"result": {
|
||||
"finished": "success",
|
||||
"progress": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
_Example Body Deployment Proceeding_
|
||||
```
|
||||
{
|
||||
"id": "1",
|
||||
"time": "20140511T121314",
|
||||
"status": {
|
||||
"execution": "proceeding",
|
||||
"result": {
|
||||
"finished": "none",
|
||||
"progress": {
|
||||
"cnt": 2,
|
||||
"of": 5
|
||||
}
|
||||
},
|
||||
"details": [
|
||||
"checking hash sums"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
_Example Body Deployment Error_
|
||||
```
|
||||
{
|
||||
"id": 1,
|
||||
"time": "20140511T121314",
|
||||
"status": {
|
||||
"execution": "rejected",
|
||||
"result": {
|
||||
"finished": "failure",
|
||||
"progress": {}
|
||||
},
|
||||
"details": [
|
||||
"something bad happend"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
6
LICENCE_HEADER_TEMPLATE.txt
Executable file
6
LICENCE_HEADER_TEMPLATE.txt
Executable file
@@ -0,0 +1,6 @@
|
||||
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
|
||||
37
README.md
Executable file
37
README.md
Executable file
@@ -0,0 +1,37 @@
|
||||
# hawkbit-update-server
|
||||
Build Status: [](https://circleci.com/gh/bsinno/hawkbit-update-server/tree/master)
|
||||
|
||||
[hawkBit](https://projects.eclipse.org/projects/iot.hawkbit) is an domain independent back end solution for rolling out software updates to constrained edge devices as well as more powerful controllers and gateways connected to IP based networking infrastructure.
|
||||
|
||||
|
||||
# Compile
|
||||
```
|
||||
mvn install
|
||||
```
|
||||
|
||||
## Try out examples
|
||||
#### Standalone Test Application Server
|
||||
[Example Application](examples/hawkbit-example-app)
|
||||
#### Device Simulator using the DMF AMQP API
|
||||
[Device Simulator](examples/hawkbit-device-simulator)
|
||||
|
||||
# Modules
|
||||
`hawkbit-core` : core elements.
|
||||
`hawkbit-security-core` : core security elements.
|
||||
`hawkbit-security-integration` : security integration elements to integrate security into hawkbit.
|
||||
`hawkbit-artifact-repository-mongo` : artifact repository implementation to mongoDB.
|
||||
`hawkbit-autoconfigure` : spring-boot auto-configuration.
|
||||
`hawkbit-dmf-api` : API for the Device Management Integration.
|
||||
`hawkbit-dmf-amqp` : AMQP endpoint implementation for the DMF API.
|
||||
`hawkbit-repository` : repository implemenation based on SQL for all meta-data.
|
||||
`hawkbit-http-security` : implementation for security filters for HTTP.
|
||||
`hawkbit-rest-api` : API classes for the REST Management API.
|
||||
`hawkbit-rest-resource` : HTTP REST endpoints for the Management and the Direct Device API.
|
||||
`hawkbit-rest-resource` : Vaadin UI.
|
||||
`hawkbit-cache-redis` : spring cache manager configuration and implementation with redis, distributed cache and distributed events.
|
||||
|
||||
|
||||
# Device Integration
|
||||
There are two device integration APIs provided by the hawkbit update server.
|
||||
* [Direct Device Integration API (HTTP)](DDIA.md)
|
||||
* Device Management Federation API (AMQP)
|
||||
33
circle.yml
Executable file
33
circle.yml
Executable file
@@ -0,0 +1,33 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
machine:
|
||||
java:
|
||||
version: oraclejdk8
|
||||
environment:
|
||||
_JAVA_OPTIONS: "-Xms512m -Xmx1024m"
|
||||
dependencies:
|
||||
cache_directories:
|
||||
- "~/.embedmongo"
|
||||
override:
|
||||
- mvn install -DskipTests
|
||||
test:
|
||||
override:
|
||||
- sh sonarCircleCi.sh
|
||||
post:
|
||||
- mkdir -p $CIRCLE_TEST_REPORTS/junit/
|
||||
- find . -type f -regex ".*/target/surefire-reports/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \;
|
||||
general:
|
||||
artifacts:
|
||||
- "*.jar"
|
||||
- "pom.xml"
|
||||
notify:
|
||||
webhooks:
|
||||
# gitter hook
|
||||
- url: https://webhooks.gitter.im/e/a20a6bc2bda5a8a77d39
|
||||
295
eclipse_codeformatter.xml
Executable file
295
eclipse_codeformatter.xml
Executable file
@@ -0,0 +1,295 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<profiles version="12">
|
||||
<profile kind="CodeFormatterProfile" name="hawkBit" version="12">
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.source" value="1.8"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.8"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.8"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||
</profile>
|
||||
</profiles>
|
||||
2
examples/README.md
Executable file
2
examples/README.md
Executable file
@@ -0,0 +1,2 @@
|
||||
# Examples
|
||||
TODO
|
||||
2
examples/hawkbit-device-simulator/.gitignore
vendored
Executable file
2
examples/hawkbit-device-simulator/.gitignore
vendored
Executable file
@@ -0,0 +1,2 @@
|
||||
/bin/
|
||||
/target/
|
||||
18
examples/hawkbit-device-simulator/README.md
Executable file
18
examples/hawkbit-device-simulator/README.md
Executable file
@@ -0,0 +1,18 @@
|
||||
# hawkBit Device Simulator
|
||||
|
||||
The device simulator handles software update commands from the update server.
|
||||
|
||||
## Run
|
||||
```
|
||||
java -jar examples/hawkbit-device-simulator/target/hawkbit-device-simulator-*-SNAPSHOT.jar
|
||||
```
|
||||
Or:
|
||||
```
|
||||
run org.eclipse.hawkbit.simulator.DeviceSimulator
|
||||
```
|
||||
|
||||
## Usage
|
||||
The device simulator exposes an REST-API which can be used to trigger device creation.
|
||||
```
|
||||
http://localhost:8083/start?amount=10
|
||||
```
|
||||
61
examples/hawkbit-device-simulator/pom.xml
Executable file
61
examples/hawkbit-device-simulator/pom.xml
Executable file
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.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
|
||||
|
||||
-->
|
||||
|
||||
<project
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<artifactId>hawkbit-examples-parent</artifactId>
|
||||
</parent>
|
||||
|
||||
<artifactId>hawkbit-device-simulator</artifactId>
|
||||
<name>hawkBit :: Device Simulator</name>
|
||||
<description>Device Management Federation API based simulator</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-dmf-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.amqp</groupId>
|
||||
<artifactId>spring-rabbit</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 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.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* The main-method to start the Spring-Boot application.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class DeviceSimulator {
|
||||
|
||||
/**
|
||||
* Start the Spring Boot Application.
|
||||
*
|
||||
* @param args
|
||||
* the args
|
||||
*/
|
||||
public static void main(final String[] args) {
|
||||
SpringApplication.run(DeviceSimulator.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* 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;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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 SpSenderService spSenderService;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @return a response string that devices has been created
|
||||
*/
|
||||
@RequestMapping("/start")
|
||||
String start(@RequestParam(value = "name", defaultValue = "dmfSimulated") final String name,
|
||||
@RequestParam(value = "amount", defaultValue = "20") final int amount,
|
||||
@RequestParam(value = "tenant", defaultValue = "DEFAULT") final String tenant) {
|
||||
|
||||
for (int i = 0; i < amount; i++) {
|
||||
spSenderService.createOrUpdateThing(tenant, name + i);
|
||||
}
|
||||
|
||||
return "Updated " + amount + " DMF connected targets!";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* 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.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
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.rabbit.config.SimpleRabbitListenerContainerFactory;
|
||||
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.amqp.support.converter.MessageConverter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* The spring AMQP configuration to use a AMQP for communication with SP update
|
||||
* server.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(AmqpProperties.class)
|
||||
public class AmqpConfiguration {
|
||||
|
||||
@Autowired
|
||||
protected AmqpProperties amqpProperties;
|
||||
|
||||
@Autowired
|
||||
private ConnectionFactory connectionFactory;
|
||||
|
||||
@Autowired
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
/**
|
||||
* Create jackson message converter bean.
|
||||
*
|
||||
* @return the jackson message converter
|
||||
*/
|
||||
@Bean
|
||||
public MessageConverter jsonMessageConverter() {
|
||||
final Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
|
||||
rabbitTemplate.setMessageConverter(jackson2JsonMessageConverter);
|
||||
return jackson2JsonMessageConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the receiver queue from sp. Receive messages from sp.
|
||||
*
|
||||
* @return the queue
|
||||
*/
|
||||
@Bean
|
||||
public Queue receiverConnectorQueueFromSp() {
|
||||
return new Queue(amqpProperties.getReceiverConnectorQueueFromSp(), true, false, false,
|
||||
getDeadLetterExchangeArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the recevier exchange. Sp send messages to this exchange.
|
||||
*
|
||||
* @return the exchange
|
||||
*/
|
||||
@Bean
|
||||
public FanoutExchange exchangeQueueToConnector() {
|
||||
return new FanoutExchange(amqpProperties.getSenderForSpExchange());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the Binding
|
||||
* {@link AmqpConfiguration#receiverConnectorQueueFromSp()} to
|
||||
* {@link AmqpConfiguration#exchangeQueueToConnector()}.
|
||||
*
|
||||
* @return the binding and create the queue and exchange
|
||||
*/
|
||||
@Bean
|
||||
public Binding bindReceiverQueueToSpExchange() {
|
||||
return BindingBuilder.bind(receiverConnectorQueueFromSp()).to(exchangeQueueToConnector());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create dead letter queue.
|
||||
*
|
||||
* @return the queue
|
||||
*/
|
||||
@Bean
|
||||
public Queue deadLetterQueue() {
|
||||
return new Queue(amqpProperties.getDeadLetterQueue(), true, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the dead letter fanout exchange.
|
||||
*
|
||||
* @return the fanout exchange
|
||||
*/
|
||||
@Bean
|
||||
public FanoutExchange exchangeDeadLetter() {
|
||||
return new FanoutExchange(amqpProperties.getDeadLetterExchange());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the Binding deadLetterQueue to exchangeDeadLetter.
|
||||
*
|
||||
* @return the binding
|
||||
*/
|
||||
@Bean
|
||||
public Binding bindDeadLetterQueueToLwm2mExchange() {
|
||||
return BindingBuilder.bind(deadLetterQueue()).to(exchangeDeadLetter());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(false);
|
||||
containerFactory.setConnectionFactory(connectionFactory);
|
||||
return containerFactory;
|
||||
}
|
||||
|
||||
private Map<String, Object> getDeadLetterExchangeArgs() {
|
||||
final Map<String, Object> args = new HashMap<String, Object>();
|
||||
args.put("x-dead-letter-exchange", amqpProperties.getDeadLetterExchange());
|
||||
return args;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Bean which holds the necessary properties for configuring the AMQP
|
||||
* connection.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.device.simulator.amqp")
|
||||
public class AmqpProperties {
|
||||
|
||||
private String receiverConnectorQueueFromSp;
|
||||
private String senderForSpExchange;
|
||||
|
||||
private String deadLetterQueue;
|
||||
private String deadLetterExchange;
|
||||
|
||||
public String getReceiverConnectorQueueFromSp() {
|
||||
return receiverConnectorQueueFromSp;
|
||||
}
|
||||
|
||||
public void setReceiverConnectorQueueFromSp(final String receiverConnectorQueueFromSp) {
|
||||
this.receiverConnectorQueueFromSp = receiverConnectorQueueFromSp;
|
||||
}
|
||||
|
||||
public String getDeadLetterExchange() {
|
||||
return deadLetterExchange;
|
||||
}
|
||||
|
||||
public void setDeadLetterExchange(final String deadLetterExchange) {
|
||||
this.deadLetterExchange = deadLetterExchange;
|
||||
}
|
||||
|
||||
public String getDeadLetterQueue() {
|
||||
return deadLetterQueue;
|
||||
}
|
||||
|
||||
public void setDeadLetterQueue(final String deadLetterQueue) {
|
||||
this.deadLetterQueue = deadLetterQueue;
|
||||
}
|
||||
|
||||
public String getSenderForSpExchange() {
|
||||
return senderForSpExchange;
|
||||
}
|
||||
|
||||
public void setSenderForSpExchange(final String senderForSpExchange) {
|
||||
this.senderForSpExchange = senderForSpExchange;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* 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> T convertMessage(final Message message, final Class<T> clazz) {
|
||||
message.getMessageProperties().getHeaders().put(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME,
|
||||
clazz.getTypeName());
|
||||
return (T) rabbitTemplate.getMessageConverter().fromMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to verify if lwm2m header is set.
|
||||
*
|
||||
* @param message
|
||||
* the message with the header
|
||||
* @param header
|
||||
* the header to verify
|
||||
*/
|
||||
public void checkIfLwm2mHeaderEmpty(final Message message, final String header) {
|
||||
final Object headerObject = message.getMessageProperties().getHeaders().get(header);
|
||||
if (null == headerObject) {
|
||||
logAndThrowMessageError(message, "Header of " + header + "empty.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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.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 IllegalArgumentException("Content-Type is not JSON compatible");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* 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.core.Message;
|
||||
import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* Abstract calls for sender service objects.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class SenderService extends MessageService {
|
||||
|
||||
/**
|
||||
* 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 adress
|
||||
* the exchange name
|
||||
* @param message
|
||||
* the amqp message which will be send if its not null
|
||||
*/
|
||||
public void sendMessage(final String adress, final Message message) {
|
||||
if (message == null) {
|
||||
return;
|
||||
}
|
||||
rabbitTemplate.setExchange(adress);
|
||||
rabbitTemplate.send(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* 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 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* 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.Map;
|
||||
|
||||
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.ActionStatus;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DownloadAndUpdateRequest;
|
||||
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.messaging.handler.annotation.Header;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Handle all incoming Messages from SP.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class SpReceiverService extends ReceiverService {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ReceiverService.class);
|
||||
|
||||
public static final String SOFTWARE_MODULE_FIRMWARE = "firmware";
|
||||
|
||||
private final SpSenderService spSenderService;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param rabbitTemplate
|
||||
* the rabbit template
|
||||
* @param amqpProperties
|
||||
* the amqp properties
|
||||
* @param lwm2mSenderService
|
||||
* the lwm2mSenderService
|
||||
* @param spSenderService
|
||||
* the spSenderService
|
||||
*/
|
||||
@Autowired
|
||||
public SpReceiverService(final RabbitTemplate rabbitTemplate, final AmqpProperties amqpProperties,
|
||||
final SpSenderService spSenderService) {
|
||||
super(rabbitTemplate, amqpProperties);
|
||||
this.spSenderService = spSenderService;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the incoming Message from Queue with the property
|
||||
* (com.bosch.sp.lwm2m.connector.amqp.receiverConnectorQueueFromSp).
|
||||
*
|
||||
* @param message
|
||||
* the incoming message
|
||||
* @param type
|
||||
* the action type
|
||||
* @param contentType
|
||||
* the content type in message header
|
||||
* @param thingId
|
||||
* the thing id in message header
|
||||
*/
|
||||
@RabbitListener(queues = "${hawkbit.device.simulator.amqp.receiverConnectorQueueFromSp}", containerFactory = "listenerContainerFactory")
|
||||
public void recieveMessageSp(final Message message, @Header(MessageHeaderKey.TYPE) final String type,
|
||||
@Header(MessageHeaderKey.THING_ID) final String thingId) {
|
||||
checkContentTypeJson(message);
|
||||
delegateMessage(message, type, thingId);
|
||||
}
|
||||
|
||||
private void delegateMessage(final Message message, final String type, final String thingId) {
|
||||
final MessageType messageType = MessageType.valueOf(type);
|
||||
|
||||
switch (messageType) {
|
||||
case EVENT:
|
||||
handleEventMessage(message, thingId);
|
||||
break;
|
||||
default:
|
||||
LOGGER.info("No valid message type property.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
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<String, Object> 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, "Simulation canceled");
|
||||
}
|
||||
|
||||
private void handleUpdateProcess(final Message message, final String thingId) {
|
||||
final MessageProperties messageProperties = message.getMessageProperties();
|
||||
final Map<String, Object> headers = messageProperties.getHeaders();
|
||||
final String tenant = (String) headers.get(MessageHeaderKey.TENANT);
|
||||
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = convertMessage(message,
|
||||
DownloadAndUpdateRequest.class);
|
||||
final Long actionId = downloadAndUpdateRequest.getActionId();
|
||||
|
||||
spSenderService.sendActionStatusMessage(tenant, ActionStatus.RUNNING,
|
||||
"device Simulator retrieved update request. proceeding with simulation.", actionId);
|
||||
|
||||
final SimulatedUpdate update = new SimulatedUpdate(tenant, thingId, actionId);
|
||||
|
||||
spSenderService.finishUpdateProcess(update, "Simulation complete!");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
/**
|
||||
* 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.Map;
|
||||
|
||||
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.ActionStatus;
|
||||
import org.eclipse.hawkbit.dmf.json.model.ActionUpdateStatus;
|
||||
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;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Sender service to send message to SP.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
public class SpSenderService extends SenderService {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SpSenderService.class);
|
||||
|
||||
private final String spExchange;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param rabbitTemplate
|
||||
* the rabbit template
|
||||
* @param amqpProperties
|
||||
* the amqp properties
|
||||
*/
|
||||
@Autowired
|
||||
public SpSenderService(final RabbitTemplate rabbitTemplate, final AmqpProperties amqpProperties) {
|
||||
super(rabbitTemplate, amqpProperties);
|
||||
this.spExchange = AmqpSettings.DMF_EXCHANGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish the update process. This will send a action status to SP.
|
||||
*
|
||||
* @param update
|
||||
* the simulated update object
|
||||
* @param description
|
||||
* a description according the update process
|
||||
*/
|
||||
public void finishUpdateProcess(final SimulatedUpdate update, final String description) {
|
||||
final Message updateResultMessage = createUpdateResultMessage(update, ActionStatus.FINISHED, description);
|
||||
sendMessage(spExchange, updateResultMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish update process with error and send error to SP.
|
||||
*
|
||||
* @param update
|
||||
* the simulated update object
|
||||
* @param messageDescription
|
||||
* a description according the update process
|
||||
*/
|
||||
public void finishUpdateProcessWithError(final SimulatedUpdate update, final String messageDescription) {
|
||||
sendErrorgMessage(update, messageDescription);
|
||||
LOGGER.debug("Update process finished with error \"{}\" reported by thing {}", messageDescription,
|
||||
update.getThingId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an error message to SP.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant
|
||||
* @param messageDescription
|
||||
* the error message description to send
|
||||
* @param actionId
|
||||
* the ID of the action for the error message
|
||||
*/
|
||||
public void sendErrorMessage(final String tenant, final String messageDescription, final Long actionId) {
|
||||
final Message message = createActionStatusMessage(tenant, ActionStatus.ERROR, messageDescription, actionId);
|
||||
sendMessage(spExchange, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a warning message to SP.
|
||||
*
|
||||
* @param update
|
||||
* the simulated update object
|
||||
* @param warningMessage
|
||||
* a warning description
|
||||
*/
|
||||
public void sendWarningMessage(final SimulatedUpdate update, final String warningMessage) {
|
||||
final Message message = createActionStatusMessage(update, warningMessage, ActionStatus.WARNING);
|
||||
sendMessage(spExchange, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to send a action status to SP.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant
|
||||
* @param actionStatus
|
||||
* the action status
|
||||
* @param actionMessage
|
||||
* the message to get send
|
||||
* @param actionId
|
||||
* the cached value
|
||||
*/
|
||||
public void sendActionStatusMessage(final String tenant, final ActionStatus actionStatus,
|
||||
final String actionMessage, final Long actionId) {
|
||||
final Message message = createActionStatusMessage(tenant, actionStatus, actionMessage, actionId);
|
||||
sendMessage(message);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new thing created message and send to SP.
|
||||
*
|
||||
* @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) {
|
||||
|
||||
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());
|
||||
final Message convertedMessage = new Message(null, messagePropertiesForSP);
|
||||
sendMessage(spExchange, convertedMessage);
|
||||
LOGGER.debug("Created thing created message and send to SP for Thing \"{}\"", targetId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 messageDescription
|
||||
* a description according the update process
|
||||
*/
|
||||
private void sendErrorgMessage(final SimulatedUpdate update, final String messageDescription) {
|
||||
final Message message = createActionStatusMessage(update, messageDescription, ActionStatus.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 ActionStatus actionStatus,
|
||||
final String actionMessage, final Long actionId) {
|
||||
final MessageProperties messageProperties = new MessageProperties();
|
||||
final Map<String, Object> headers = messageProperties.getHeaders();
|
||||
final ActionUpdateStatus actionUpdateStatus = new ActionUpdateStatus();
|
||||
actionUpdateStatus.setActionStatus(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);
|
||||
if (!StringUtils.isEmpty(actionMessage)) {
|
||||
actionUpdateStatus.getMessage().add(actionMessage);
|
||||
}
|
||||
actionUpdateStatus.setActionId(actionId);
|
||||
return convertMessage(actionUpdateStatus, messageProperties);
|
||||
}
|
||||
|
||||
private Message createUpdateResultMessage(final SimulatedUpdate cacheValue, final ActionStatus actionStatus,
|
||||
final String updateResultMessage) {
|
||||
final MessageProperties messageProperties = new MessageProperties();
|
||||
final Map<String, Object> headers = messageProperties.getHeaders();
|
||||
final ActionUpdateStatus actionUpdateStatus = new ActionUpdateStatus();
|
||||
actionUpdateStatus.setActionStatus(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.getMessage().add(updateResultMessage);
|
||||
actionUpdateStatus.setActionId(cacheValue.getActionId());
|
||||
return convertMessage(actionUpdateStatus, messageProperties);
|
||||
}
|
||||
|
||||
private Message createActionStatusMessage(final SimulatedUpdate update, final String messageDescription,
|
||||
final ActionStatus status) {
|
||||
final Message sendMessage = createActionStatusMessage(update.getTenant(), status, messageDescription,
|
||||
update.getActionId());
|
||||
return sendMessage;
|
||||
}
|
||||
|
||||
}
|
||||
101
examples/hawkbit-device-simulator/src/main/resources/application.properties
Executable file
101
examples/hawkbit-device-simulator/src/main/resources/application.properties
Executable file
@@ -0,0 +1,101 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
|
||||
#########################################################################################
|
||||
# PUBLIC configuration, i.e. can be changed by users at runtime (defaults provided here)
|
||||
#########################################################################################
|
||||
## Configuration for RabbitMQ communication
|
||||
hawkbit.device.simulator.amqp.receiverConnectorQueueFromSp=sp_connector_receiver
|
||||
hawkbit.device.simulator.amqp.deadLetterQueue=simulator_deadletter
|
||||
hawkbit.device.simulator.amqp.deadLetterExchange=simulator.deadletter
|
||||
hawkbit.device.simulator.amqp.senderForSpExchange=simulator.replyTo
|
||||
|
||||
|
||||
## Configuration for 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
|
||||
|
||||
|
||||
#disable expose jmx beans
|
||||
spring.jmx.enabled=false
|
||||
# the context path of the monitor spring actuator which offers following endpoints
|
||||
# /autoconfig, /beans, /configprops, /dump, /env, /health, /info, /metrics, /mappings, /trace
|
||||
management.context-path=/system
|
||||
management.security.enabled=true
|
||||
management.security.sessions=stateless
|
||||
# ENDPOINTS
|
||||
endpoints.autoconfig.id=autoconfig
|
||||
endpoints.autoconfig.sensitive=true
|
||||
endpoints.autoconfig.enabled=false
|
||||
endpoints.beans.id=beans
|
||||
endpoints.beans.sensitive=true
|
||||
endpoints.beans.enabled=false
|
||||
endpoints.configprops.id=configprops
|
||||
endpoints.configprops.sensitive=true
|
||||
endpoints.configprops.enabled=true
|
||||
#endpoints.configprops.keys-to-sanitize=password,secret,key # suffix or regex
|
||||
endpoints.dump.id=dump
|
||||
endpoints.dump.sensitive=true
|
||||
endpoints.dump.enabled=false
|
||||
endpoints.env.id=env
|
||||
endpoints.env.sensitive=true
|
||||
endpoints.env.enabled=true
|
||||
#endpoints.env.keys-to-sanitize=password,secret,key # suffix or regex
|
||||
endpoints.health.id=health
|
||||
endpoints.health.sensitive=true
|
||||
endpoints.health.enabled=true
|
||||
endpoints.info.id=info
|
||||
endpoints.info.sensitive=true
|
||||
endpoints.info.enabled=true
|
||||
endpoints.metrics.id=metrics
|
||||
endpoints.metrics.sensitive=true
|
||||
endpoints.metrics.enabled=true
|
||||
endpoints.shutdown.id=shutdown
|
||||
endpoints.shutdown.sensitive=true
|
||||
endpoints.shutdown.enabled=false
|
||||
endpoints.trace.id=trace
|
||||
endpoints.trace.sensitive=true
|
||||
endpoints.trace.enabled=true
|
||||
|
||||
# HEALTH INDICATORS (previously health.*)
|
||||
management.health.db.enabled=true
|
||||
management.health.diskspace.enabled=true
|
||||
management.health.mongo.enabled=true
|
||||
management.health.rabbit.enabled=true
|
||||
management.health.redis.enabled=false
|
||||
management.health.solr.enabled=false
|
||||
management.health.diskspace.path=.
|
||||
management.health.diskspace.threshold=10485760
|
||||
management.health.status.order=DOWN, OUT_OF_SERVICE, UNKNOWN, UP
|
||||
|
||||
# SECURITY (SecurityProperties)
|
||||
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.enabled=true
|
||||
security.basic.realm=DeviceSimulator
|
||||
security.basic.path= /system/**
|
||||
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=
|
||||
|
||||
server.port=8083
|
||||
1
examples/hawkbit-example-app/.gitignore
vendored
Executable file
1
examples/hawkbit-example-app/.gitignore
vendored
Executable file
@@ -0,0 +1 @@
|
||||
/target/
|
||||
15
examples/hawkbit-example-app/README.md
Executable file
15
examples/hawkbit-example-app/README.md
Executable file
@@ -0,0 +1,15 @@
|
||||
# hawkBit Example Application
|
||||
The hawkBit example application is a standalone spring-boot application with an embedded servlet container to start the hawkBit.
|
||||
|
||||
## Run
|
||||
```
|
||||
java -jar examples/hawkbit-example-app/target/hawkbit-example-app-*-SNAPSHOT.jar
|
||||
```
|
||||
Or:
|
||||
```
|
||||
run org eclipse.hawkbit.app.Start
|
||||
```
|
||||
|
||||
## Usage
|
||||
The UI can be accessed via _http://localhost:8080/UI_.
|
||||
The REST API can be accessed via _http://localhost:8080/rest/v1_.
|
||||
105
examples/hawkbit-example-app/pom.xml
Executable file
105
examples/hawkbit-example-app/pom.xml
Executable file
@@ -0,0 +1,105 @@
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-examples-parent</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>hawkbit-example-app</artifactId>
|
||||
<name>hawkBit :: Example App</name>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${baseDir}</outputDirectory>
|
||||
<addResources>false</addResources>
|
||||
<mainClass>org.eclipse.hawkbit.app.Start</mainClass>
|
||||
<layout>JAR</layout>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- Hawkbit -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-autoconfigure</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-dmf-amqp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-ui</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-security-integration</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-http-security</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-aspects</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 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.HawkbitLoginUI;
|
||||
import org.eclipse.hawkbit.ui.themes.HawkbitTheme;
|
||||
|
||||
import com.vaadin.spring.annotation.SpringUI;
|
||||
|
||||
/**
|
||||
* 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 HawkbitLoginUI} 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)
|
||||
public class MyLoginUI extends HawkbitLoginUI {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
77
examples/hawkbit-example-app/src/main/java/org/eclipse/hawkbit/app/MyUI.java
Executable file
77
examples/hawkbit-example-app/src/main/java/org/eclipse/hawkbit/app/MyUI.java
Executable file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* 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.eventbus.EventSubscriber;
|
||||
import org.eclipse.hawkbit.eventbus.event.EntityEvent;
|
||||
import org.eclipse.hawkbit.ui.DispatcherRunnable;
|
||||
import org.eclipse.hawkbit.ui.HawkbitUI;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||
import org.vaadin.spring.events.EventBus.SessionEventBus;
|
||||
|
||||
import com.google.common.eventbus.AllowConcurrentEvents;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.vaadin.annotations.Push;
|
||||
import com.vaadin.server.VaadinSession;
|
||||
import com.vaadin.server.VaadinSession.State;
|
||||
import com.vaadin.server.WrappedSession;
|
||||
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 HawkbitUI}
|
||||
* and to annotated it with {@link SpringUI} as in this example.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@SpringUI
|
||||
@Push(value = PushMode.AUTOMATIC, transport = Transport.WEBSOCKET)
|
||||
@EventSubscriber
|
||||
public class MyUI extends HawkbitUI {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* An {@link com.google.common.eventbus.EventBus} subscriber which
|
||||
* subscribes {@link EntityEvent} from the repository to dispatch these
|
||||
* events to the UI {@link SessionEventBus}.
|
||||
*
|
||||
* @param event
|
||||
* the entity event which has been published from the repository
|
||||
*/
|
||||
@Override
|
||||
@Subscribe
|
||||
@AllowConcurrentEvents
|
||||
public void dispatch(final org.eclipse.hawkbit.eventbus.event.Event event) {
|
||||
final VaadinSession session = getSession();
|
||||
if (session != null && session.getState() == State.OPEN) {
|
||||
final WrappedSession wrappedSession = session.getSession();
|
||||
if (wrappedSession != null) {
|
||||
final SecurityContext userContext = (SecurityContext) wrappedSession
|
||||
.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
|
||||
if (eventSecurityCheck(userContext, event)) {
|
||||
final SecurityContext oldContext = SecurityContextHolder.getContext();
|
||||
try {
|
||||
access(new DispatcherRunnable(eventBus, session, userContext, event));
|
||||
} finally {
|
||||
SecurityContextHolder.setContext(oldContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 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.RepositoryApplicationConfiguration;
|
||||
import org.eclipse.hawkbit.autoconfigure.security.EnableHawkbitManagedSecurityConfiguration;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* A {@link SpringBootApplication} annoated class with a main method to start.
|
||||
* The minimal configuration for the standalone hawkBit server.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@Import({ RepositoryApplicationConfiguration.class })
|
||||
@EnableHawkbitManagedSecurityConfiguration
|
||||
public class Start {
|
||||
|
||||
/**
|
||||
* Main method to start the spring-boot application.
|
||||
*
|
||||
* @param args
|
||||
* the VM arguments.
|
||||
*/
|
||||
public static void main(final String[] args) {
|
||||
SpringApplication.run(Start.class, args);
|
||||
}
|
||||
}
|
||||
29
examples/hawkbit-example-app/src/main/resources/application.properties
Executable file
29
examples/hawkbit-example-app/src/main/resources/application.properties
Executable file
@@ -0,0 +1,29 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
# need to re-name these properties in the defaulthawkbit.properties and code!
|
||||
hawkbit.server.controller.security.authentication.anonymous.enabled=true
|
||||
hawkbit.server.controller.security.authentication.header.enabled=false
|
||||
hawkbit.server.controller.security.authentication.targettoken.enabled=false
|
||||
hawkbit.server.controller.security.authentication.gatewaytoken.enabled=false
|
||||
|
||||
spring.profiles.active=amqp
|
||||
|
||||
vaadin.servlet.params.productionMode=false
|
||||
vaadin.static.servlet.params.productionMode=false
|
||||
|
||||
## Configuration for RabbitMQ integration
|
||||
hawkbit.server.amqp.username=guest
|
||||
hawkbit.server.amqp.password=guest
|
||||
hawkbit.server.amqp.virtualHost=/
|
||||
hawkbit.server.amqp.host=localhost
|
||||
hawkbit.server.amqp.port=5672
|
||||
hawkbit.server.amqp.deadLetterQueue=sp_deadletter
|
||||
hawkbit.server.amqp.deadLetterExchange=sp.deadletter
|
||||
hawkbit.server.amqp.receiverQueue=sp_receiver
|
||||
30
examples/pom.xml
Executable file
30
examples/pom.xml
Executable file
@@ -0,0 +1,30 @@
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-parent</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hawkbit-examples-parent</artifactId>
|
||||
<name>hawkBit :: Examples Parent</name>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>hawkbit-device-simulator</module>
|
||||
<module>hawkbit-example-app</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
3
hawkbit-artifact-repository-mongo/README.md
Executable file
3
hawkbit-artifact-repository-mongo/README.md
Executable file
@@ -0,0 +1,3 @@
|
||||
# HawkBit Artifact Repositoy
|
||||
HawkBit Artifact Repository is library for storing binary artifacts and metadata into MongoDB.
|
||||
It has an spring-boot autoconfiguration for easily integration into spring-boot projects.
|
||||
83
hawkbit-artifact-repository-mongo/pom.xml
Executable file
83
hawkbit-artifact-repository-mongo/pom.xml
Executable file
@@ -0,0 +1,83 @@
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<artifactId>hawkbit-parent</artifactId>
|
||||
</parent>
|
||||
<artifactId>hawkbit-artifact-repository-mongo</artifactId>
|
||||
<name>hawkBit :: Artifact Repository Mongo</name>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>18.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- TEST -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easytesting</groupId>
|
||||
<artifactId>fest-assert-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.yandex.qatools.allure</groupId>
|
||||
<artifactId>allure-junit-adaptor</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- MongoDB -->
|
||||
<dependency>
|
||||
<groupId>de.flapdoodle.embed</groupId>
|
||||
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Mockito -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,280 @@
|
||||
/**
|
||||
* 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.File;
|
||||
import java.io.FileInputStream;
|
||||
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 java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.gridfs.GridFsOperations;
|
||||
|
||||
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 filestore.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ArtifactStore implements ArtifactRepository {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ArtifactStore.class);
|
||||
|
||||
/**
|
||||
* The mongoDB field which holds the filename of the file to download. SP
|
||||
* Server uses the SHA hash as a filename and lookup in the mongoDB.
|
||||
*/
|
||||
private static final String FILENAME = "filename";
|
||||
|
||||
/**
|
||||
* The mongoDB field which automatically calculated by the mongoDB.
|
||||
*/
|
||||
private static final String MD5 = "md5";
|
||||
|
||||
/**
|
||||
* The mongoDB field which holds the SHA1 hash, stored in the metadata
|
||||
* object.
|
||||
*/
|
||||
private static final String SHA1 = "sha1";
|
||||
|
||||
private static final String ID = "_id";
|
||||
|
||||
@Autowired
|
||||
private GridFsOperations gridFs;
|
||||
|
||||
MongoTemplate mongoTemplate;
|
||||
|
||||
/**
|
||||
* Retrieves a {@link GridFSDBFile} from the store by it's SHA1 hash.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant to retrieve the artifacts from, ignore case.
|
||||
* @param sha1Hash
|
||||
* the sha1-hash of the file to lookup.
|
||||
* @return The gridfs file object or {@code null} if no file exists.
|
||||
*/
|
||||
@Override
|
||||
public DbArtifact getArtifactBySha1(final String sha1Hash) {
|
||||
return map(gridFs.findOne(new Query().addCriteria(Criteria.where(FILENAME).is(sha1Hash))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a {@link GridFSDBFile} from the store by it's MD5 hash.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant to retrieve the artifacts from, ignore case.
|
||||
* @param md5Hash
|
||||
* the md5-hash of the file to lookup.
|
||||
* @return The gridfs file object or {@code null} if no file exists.
|
||||
*/
|
||||
public DbArtifact getArtifactByMd5(final String md5Hash) {
|
||||
return map(gridFs.findOne(new Query().addCriteria(Criteria.where(MD5).is(md5Hash))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a {@link GridFSDBFile} from the store by it's object id.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant to retrieve the artifacts from, ignore case.
|
||||
* @param id
|
||||
* the id of the file to lookup.
|
||||
* @return The gridfs file object or {@code null} if no file exists.
|
||||
*/
|
||||
@Override
|
||||
public DbArtifact getArtifactById(final String id) {
|
||||
return map(gridFs.findOne(new Query().addCriteria(Criteria.where(ID).is(id))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DbArtifact store(final InputStream content, final String filename, final String contentType) {
|
||||
return store(content, filename, contentType, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DbArtifact store(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 FileOutputStream os = new FileOutputStream(tempFile)) {
|
||||
return store(content, contentType, os, 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteById(final String artifactId) {
|
||||
try {
|
||||
deleteArtifact(gridFs.findOne(new Query().addCriteria(Criteria.where(ID).is(artifactId))));
|
||||
} catch (final MongoException e) {
|
||||
throw new ArtifactStoreException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteBySha1(final String sha1Hash) {
|
||||
try {
|
||||
deleteArtifact(gridFs.findOne(new Query().addCriteria(Criteria.where(FILENAME).is(sha1Hash))));
|
||||
} 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 DbArtifact store(final InputStream content, final String contentType, final FileOutputStream os,
|
||||
final File tempFile, final DbArtifactHash hash) {
|
||||
final GridFsArtifact storedArtifact;
|
||||
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)));
|
||||
if (null == result) {
|
||||
try (FileInputStream inputStream = new FileInputStream(tempFile)) {
|
||||
final BasicDBObject metadata = new BasicDBObject();
|
||||
metadata.put(SHA1, sha1Hash);
|
||||
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.getMessage(), e);
|
||||
}
|
||||
|
||||
if (hash != null && hash.getMd5() != null && !storedArtifact.getHashes().getMd5().equals(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 String computeSHA1Hash(final InputStream stream, final FileOutputStream os, final String providedSHA1Sum)
|
||||
throws NoSuchAlgorithmException, IOException {
|
||||
String sha1Hash;
|
||||
// compute digest
|
||||
final MessageDigest md = MessageDigest.getInstance("SHA-1");
|
||||
final DigestOutputStream dos = new DigestOutputStream(os, md);
|
||||
ByteStreams.copy(stream, dos);
|
||||
dos.close();
|
||||
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 paged list of {@link DbArtifact}s.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant
|
||||
* @param dbFiles
|
||||
* the list of mongoDB gridFs files.
|
||||
* @return a paged list of artifacts mapped from the given dbFiles
|
||||
*/
|
||||
private List<DbArtifact> map(final List<GridFSDBFile> dbFiles) {
|
||||
final List<DbArtifact> collect = dbFiles.stream().map(dbFile -> map(dbFile)).collect(Collectors.toList());
|
||||
return collect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of {@link GridFSDBFile} from the store by all SHA1
|
||||
* hashes.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant to retrieve the artifacts from, ignore case.
|
||||
* @param sha1Hashes
|
||||
* the sha1-hashes of the files to lookup.
|
||||
* @return list of artfiacts
|
||||
*/
|
||||
public List<DbArtifact> getArtifactsBySha1(final List<String> sha1Hashes) {
|
||||
return map(gridFs.find(new Query().addCriteria(Criteria.where(SHA1).in(sha1Hashes))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of {@link GridFSDBFile} from the store by all ids.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant to retrieve the artifacts from, ignore case.
|
||||
* @param ids
|
||||
* the ids of the files to lookup.
|
||||
* @return list of artfiacts
|
||||
*/
|
||||
public List<DbArtifact> getArtifactsByIds(final List<String> ids) {
|
||||
return map(gridFs.find(new Query().addCriteria(Criteria.where(ID).in(ids))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a single {@link GridFSFile} to {@link DbArtifact}.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant
|
||||
* @param dbFile
|
||||
* the mongoDB gridFs file.
|
||||
* @return a mapped artifact from the given dbFile
|
||||
*/
|
||||
private GridFsArtifact map(final GridFSFile fsFile) {
|
||||
if (fsFile == null) {
|
||||
return null;
|
||||
}
|
||||
final GridFsArtifact artifact = new GridFsArtifact(fsFile);
|
||||
artifact.setArtifactId(fsFile.getId().toString());
|
||||
artifact.setSize(fsFile.getLength());
|
||||
artifact.setContentType(fsFile.getContentType());
|
||||
artifact.setHashes(new DbArtifactHash(fsFile.getFilename(), fsFile.getMD5()));
|
||||
return artifact;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 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.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Auto configuration for the {@link ArtifactStore}.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ComponentScan
|
||||
@ConditionalOnMissingBean(value = ArtifactRepository.class)
|
||||
@Import(value = MongoConfiguration.class)
|
||||
public class ArtifactStoreAutoConfiguration {
|
||||
|
||||
/**
|
||||
* @return Default {@link ArtifactRepository} implementation.
|
||||
*/
|
||||
@Bean
|
||||
public ArtifactRepository artifactRepository() {
|
||||
return new ArtifactStore();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* 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.DbArtifact;
|
||||
|
||||
import com.mongodb.gridfs.GridFSDBFile;
|
||||
import com.mongodb.gridfs.GridFSFile;
|
||||
|
||||
/**
|
||||
* A wrapper object for the {@link DbArtifact} 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 DbArtifact {
|
||||
|
||||
private final GridFSFile dbFile;
|
||||
|
||||
/**
|
||||
* @param dbFile
|
||||
*/
|
||||
public GridFsArtifact(final GridFSFile dbFile) {
|
||||
this.dbFile = dbFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getFileInputStream() {
|
||||
if (dbFile instanceof GridFSDBFile) {
|
||||
return ((GridFSDBFile) dbFile).getInputStream();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* 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.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
|
||||
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoClient;
|
||||
import com.mongodb.MongoClientOptions;
|
||||
import com.mongodb.MongoClientOptions.Builder;
|
||||
import com.mongodb.MongoClientURI;
|
||||
import com.mongodb.ServerAddress;
|
||||
|
||||
/**
|
||||
* {@link AbstractMongoConfiguration} that uses {@link MongoClientURI} even when
|
||||
* port is configured for NON {@link Cloud} use cases.
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(MongoProperties.class)
|
||||
@ConditionalOnClass(Mongo.class)
|
||||
@ConditionalOnMissingBean(type = "org.springframework.data.mongodb.MongoDbFactory")
|
||||
@Profile({ "!cloud" })
|
||||
public class MongoConfiguration extends AbstractMongoConfiguration {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MongoConfiguration.class);
|
||||
|
||||
@Autowired
|
||||
private MongoProperties properties;
|
||||
|
||||
@Autowired(required = false)
|
||||
private MongoClientOptions options;
|
||||
|
||||
private Mongo mongo;
|
||||
|
||||
@Override
|
||||
public String getDatabaseName() {
|
||||
return properties.getMongoClientDatabase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes mongo client when destroyd.
|
||||
*/
|
||||
@PreDestroy
|
||||
public void close() {
|
||||
if (this.mongo != null) {
|
||||
this.mongo.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public Mongo mongo() throws UnknownHostException {
|
||||
final MongoClientURI uri = new MongoClientURI(properties.getUri(), createBuilderOutOfOptions(options));
|
||||
|
||||
if (properties.getPort() != null) {
|
||||
LOG.debug("Create mongo by properties (host: {}, port: {})", uri.getHosts().get(0), properties.getPort());
|
||||
this.mongo = new MongoClient(Arrays.asList(new ServerAddress(uri.getHosts().get(0), properties.getPort())),
|
||||
uri.getOptions());
|
||||
} else {
|
||||
LOG.debug("Create mongo by URI : {}", uri);
|
||||
this.mongo = new MongoClient(uri);
|
||||
}
|
||||
|
||||
return this.mongo;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates {@link MongoClientOptions} builder out of existing options as the
|
||||
* {@link MongoClientURI} expects a builder.
|
||||
*
|
||||
* Based on MongoProperties#builder method.
|
||||
*/
|
||||
private Builder createBuilderOutOfOptions(final MongoClientOptions options) {
|
||||
final Builder builder = MongoClientOptions.builder();
|
||||
if (options != null) {
|
||||
builder.alwaysUseMBeans(options.isAlwaysUseMBeans());
|
||||
builder.connectionsPerHost(options.getConnectionsPerHost());
|
||||
builder.connectTimeout(options.getConnectTimeout());
|
||||
builder.cursorFinalizerEnabled(options.isCursorFinalizerEnabled());
|
||||
builder.dbDecoderFactory(options.getDbDecoderFactory());
|
||||
builder.dbEncoderFactory(options.getDbEncoderFactory());
|
||||
builder.description(options.getDescription());
|
||||
builder.maxWaitTime(options.getMaxWaitTime());
|
||||
builder.readPreference(options.getReadPreference());
|
||||
builder.serverSelectionTimeout(options.getServerSelectionTimeout());
|
||||
builder.socketFactory(options.getSocketFactory());
|
||||
builder.socketKeepAlive(options.isSocketKeepAlive());
|
||||
builder.socketTimeout(options.getSocketTimeout());
|
||||
builder.threadsAllowedToBlockForConnectionMultiplier(options
|
||||
.getThreadsAllowedToBlockForConnectionMultiplier());
|
||||
builder.writeConcern(options.getWriteConcern());
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# Auto Configure
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.eclipse.hawkbit.artifact.repository.ArtifactStoreAutoConfiguration
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* 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 java.io.File;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class FreePortFileWriter {
|
||||
|
||||
private final String filePortPath;
|
||||
private final int from;
|
||||
private final int to;
|
||||
|
||||
/**
|
||||
* @param from
|
||||
* @param to
|
||||
*/
|
||||
public FreePortFileWriter(final int from, final int to, final String filePortPath) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.filePortPath = filePortPath;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return findFree();
|
||||
}
|
||||
|
||||
protected int findFree() {
|
||||
for (int i = from; i <= to; i++) {
|
||||
if (isFree(i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("No free port in range " + from + ":" + to);
|
||||
}
|
||||
|
||||
boolean isFree(final int port) {
|
||||
try {
|
||||
final File portFile = new File(filePortPath + File.separator + port + ".port");
|
||||
portFile.getParentFile().mkdirs();
|
||||
if (portFile.exists()) {
|
||||
return false;
|
||||
} else {
|
||||
boolean isFree = false;
|
||||
final ServerSocket sock = new ServerSocket();
|
||||
sock.setReuseAddress(true);
|
||||
sock.bind(new InetSocketAddress(port));
|
||||
if (portFile.createNewFile()) {
|
||||
portFile.deleteOnExit();
|
||||
isFree = true;
|
||||
}
|
||||
sock.close();
|
||||
// is free:
|
||||
return isFree;
|
||||
// We rely on an exception thrown to determine availability or
|
||||
// not availability.
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
// not free.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* 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 java.io.IOException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import de.flapdoodle.embed.mongo.Command;
|
||||
import de.flapdoodle.embed.mongo.MongodExecutable;
|
||||
import de.flapdoodle.embed.mongo.MongodProcess;
|
||||
import de.flapdoodle.embed.mongo.MongodStarter;
|
||||
import de.flapdoodle.embed.mongo.config.ArtifactStoreBuilder;
|
||||
import de.flapdoodle.embed.mongo.config.DownloadConfigBuilder;
|
||||
import de.flapdoodle.embed.mongo.config.IMongodConfig;
|
||||
import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
|
||||
import de.flapdoodle.embed.mongo.config.Net;
|
||||
import de.flapdoodle.embed.mongo.config.RuntimeConfigBuilder;
|
||||
import de.flapdoodle.embed.mongo.distribution.Version;
|
||||
import de.flapdoodle.embed.process.config.store.HttpProxyFactory;
|
||||
import de.flapdoodle.embed.process.runtime.Network;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class MongoDBTestRule implements TestRule {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MongoDBTestRule.class);
|
||||
private static volatile MongodExecutable mongodExecutable = null;
|
||||
private static volatile MongodProcess mongod;
|
||||
private final String id = UUID.randomUUID().toString();
|
||||
|
||||
@Override
|
||||
public Statement apply(final Statement base, final Description description) {
|
||||
return statement(base, description);
|
||||
}
|
||||
|
||||
private Statement statement(final Statement base, final Description description) {
|
||||
return new Statement() {
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
before(base, description);
|
||||
try {
|
||||
base.evaluate();
|
||||
} finally {
|
||||
after();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void after() {
|
||||
if (mongodExecutable != null) {
|
||||
LOG.info("Stop MongoDB...");
|
||||
mongodExecutable.stop();
|
||||
mongodExecutable = null;
|
||||
if (mongod != null) {
|
||||
mongod.stop();
|
||||
mongod = null;
|
||||
}
|
||||
LOG.info("MongoDB stopped... {}", id);
|
||||
}
|
||||
}
|
||||
|
||||
private void before(final Statement base, final Description description) throws UnknownHostException, IOException {
|
||||
final Command command = Command.MongoD;
|
||||
|
||||
final RuntimeConfigBuilder runtimeConfig = new RuntimeConfigBuilder().defaults(command);
|
||||
|
||||
int port = -1;
|
||||
if (System.getProperty("spring.data.mongodb.port") != null) {
|
||||
port = Integer.parseInt(System.getProperty("spring.data.mongodb.port"));
|
||||
} else {
|
||||
port = new FreePortFileWriter(27017, 27100, "./target/freeports").getPort();
|
||||
System.setProperty("spring.data.mongodb.port", String.valueOf(port));
|
||||
}
|
||||
|
||||
Version version = Version.V3_1_0;
|
||||
if (System.getProperty("inf.mongodb.version") != null) {
|
||||
version = Version.valueOf("V" + System.getProperty("inf.mongodb.version").trim().replaceAll("\\.", "_"));
|
||||
}
|
||||
|
||||
if (System.getProperty("http.proxyHost") != null) {
|
||||
runtimeConfig.artifactStore(new ArtifactStoreBuilder().defaults(command)
|
||||
.download(new DownloadConfigBuilder().defaultsForCommand(command)
|
||||
.proxyFactory(new HttpProxyFactory(System.getProperty("http.proxyHost").trim(),
|
||||
Integer.valueOf(System.getProperty("http.proxyPort"))))));
|
||||
}
|
||||
|
||||
final IMongodConfig mongodConfig = new MongodConfigBuilder().version(version)
|
||||
.net(new Net("127.0.0.1", port, Network.localhostIsIPv6())).build();
|
||||
|
||||
final MongodStarter starter = MongodStarter.getInstance(runtimeConfig.build());
|
||||
mongodExecutable = starter.prepare(mongodConfig);
|
||||
LOG.info("Start MongoDB...");
|
||||
mongod = mongodExecutable.start();
|
||||
|
||||
final Net net = mongod.getConfig().net();
|
||||
LOG.info("MongoDB started id {} on bind ip :{} Port:{} and version {}", id, net.getBindIp(), net.getPort(),
|
||||
mongodConfig.version().toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* 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 {
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* 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.fest.assertions.api.Assertions.assertThat;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.DigestInputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.eclipse.hawkbit.artifact.MongoDBTestRule;
|
||||
import org.eclipse.hawkbit.artifact.TestConfiguration;
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
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.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import com.mongodb.gridfs.GridFSDBFile;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = { ArtifactStoreAutoConfiguration.class, TestConfiguration.class })
|
||||
public class ArtifactStoreTest {
|
||||
|
||||
@ClassRule
|
||||
public static final MongoDBTestRule mongoDBRule = new MongoDBTestRule();
|
||||
|
||||
@Autowired
|
||||
private ArtifactStore artifactStoreUnderTest;
|
||||
|
||||
@Autowired
|
||||
private GridFsOperations gridFs;
|
||||
|
||||
@Test
|
||||
public void storeArtifactInMongoDB() {
|
||||
final int filelengthBytes = 128;
|
||||
final String filename = "testfile.json";
|
||||
final String contentType = "application/json";
|
||||
final DbArtifact storedFile = artifactStoreUnderTest.store(generateInputStream(filelengthBytes), filename,
|
||||
contentType);
|
||||
|
||||
assertThat(storedFile).isNotNull();
|
||||
assertThat(artifactStoreUnderTest.getArtifactById(storedFile.getArtifactId())).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findArtifactBySHA1Hash() 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(digestInputStream, filename, contentType);
|
||||
assertThat(artifactStoreUnderTest.getArtifactBySha1(
|
||||
BaseEncoding.base16().lowerCase().encode(digestInputStream.getMessageDigest().digest()))).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findArtifactByMD5Hash() throws NoSuchAlgorithmException {
|
||||
final int filelengthBytes = 128;
|
||||
final String filename = "testfile.json";
|
||||
final String contentType = "application/json";
|
||||
|
||||
final DigestInputStream digestInputStream = digestInputStream(generateInputStream(filelengthBytes), "MD5");
|
||||
artifactStoreUnderTest.store(digestInputStream, filename, contentType);
|
||||
assertThat(artifactStoreUnderTest.getArtifactByMd5(
|
||||
BaseEncoding.base16().lowerCase().encode(digestInputStream.getMessageDigest().digest()))).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInputStreamFromArtifact() throws IOException {
|
||||
final int filelengthBytes = 128;
|
||||
final String filename = "testfile.json";
|
||||
final String contentType = "application/json";
|
||||
|
||||
final ByteArrayInputStream inputStream = generateInputStream(filelengthBytes);
|
||||
final DbArtifact artifact = artifactStoreUnderTest
|
||||
.getArtifactById(artifactStoreUnderTest.store(inputStream, filename, contentType).getArtifactId());
|
||||
inputStream.reset();
|
||||
|
||||
final byte[] artifactBytes = new byte[filelengthBytes];
|
||||
final byte[] artifactStoredBytes = new byte[filelengthBytes];
|
||||
IOUtils.readFully(inputStream, artifactBytes);
|
||||
IOUtils.readFully(artifact.getFileInputStream(), artifactStoredBytes);
|
||||
|
||||
assertThat(artifactBytes).isEqualTo(artifactStoredBytes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteArtifactWithOnlyOneTenantLast() throws NoSuchAlgorithmException {
|
||||
final int filelengthBytes = 128;
|
||||
final String filename = "testfile.json";
|
||||
final String contentType = "application/json";
|
||||
|
||||
final DigestInputStream digestInputStream = digestInputStream(generateInputStream(filelengthBytes), "SHA-1");
|
||||
final DbArtifact store = artifactStoreUnderTest.store(digestInputStream, filename, contentType);
|
||||
|
||||
artifactStoreUnderTest.deleteById(store.getArtifactId());
|
||||
|
||||
final GridFSDBFile findOne = gridFs
|
||||
.findOne(new Query().addCriteria(Criteria.where("_id").is(store.getArtifactId())));
|
||||
assertThat(findOne).isNull();
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
81
hawkbit-autoconfigure/pom.xml
Executable file
81
hawkbit-autoconfigure/pom.xml
Executable file
@@ -0,0 +1,81 @@
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-parent</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>hawkbit-autoconfigure</artifactId>
|
||||
<name>hawkBit :: Spring Boot Autoconfigure</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-cache-redis</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-dmf-amqp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-ui</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-repository</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-http-security</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-security-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-rest-resource</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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.autoconfigure.amqp;
|
||||
|
||||
import org.eclipse.hawkbit.amqp.AmqpConfiguration;
|
||||
import org.eclipse.hawkbit.amqp.annotation.EnableAmqp;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* The amqp autoconfiguration.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(value = AmqpConfiguration.class)
|
||||
@EnableAmqp
|
||||
public class AmqpAutoConfiguration {
|
||||
|
||||
}
|
||||
197
hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheAutoConfiguration.java
vendored
Executable file
197
hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheAutoConfiguration.java
vendored
Executable file
@@ -0,0 +1,197 @@
|
||||
/**
|
||||
* 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.autoconfigure.cache;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.cache.TenancyCacheManager;
|
||||
import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.guava.GuavaCacheManager;
|
||||
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
|
||||
import org.springframework.cache.interceptor.SimpleCacheResolver;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* A configuration for configuring the spring {@link CacheManager} for specific
|
||||
* multi-tenancy caching. The caches between tenants must not interfere each
|
||||
* other.
|
||||
*
|
||||
* This is done by providing a special {@link TenantCacheResolver} which
|
||||
* generates a cache name included the current tenant.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
public class CacheAutoConfiguration extends CachingConfigurerSupport {
|
||||
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
|
||||
/**
|
||||
* @return the default cache manager bean if none other cache manager is
|
||||
* existing.
|
||||
*/
|
||||
@Override
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TenancyCacheManager cacheManager() {
|
||||
return new TenantAwareCacheManager(new GuavaCacheManager(), tenantAware);
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link SimpleCacheResolver} implementation which includes the
|
||||
* {@link TenantAware#getCurrentTenant()} into the cache name before
|
||||
* resolving it.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class TenantCacheResolver extends SimpleCacheResolver {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.cache.interceptor.AbstractCacheResolver#
|
||||
* resolveCaches(org.springframework
|
||||
* .cache.interceptor.CacheOperationInvocationContext)
|
||||
*/
|
||||
@Override
|
||||
public Collection<Cache> resolveCaches(final CacheOperationInvocationContext<?> context) {
|
||||
return super.resolveCaches(context).stream().map(cache -> new TenantCacheWrapper(cache))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.cache.interceptor.SimpleCacheResolver#
|
||||
* getCacheNames(org.springframework
|
||||
* .cache.interceptor.CacheOperationInvocationContext)
|
||||
*/
|
||||
@Override
|
||||
protected Collection<String> getCacheNames(final CacheOperationInvocationContext<?> context) {
|
||||
return super.getCacheNames(context).stream()
|
||||
.map(cacheName -> tenantAware.getCurrentTenant() + "." + cacheName).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An {@link Cache} wrapper which returns the name of the cache include the
|
||||
* {@link TenantAware#getCurrentTenant()}.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class TenantCacheWrapper implements Cache {
|
||||
private final Cache delegate;
|
||||
|
||||
/**
|
||||
* @param delegate
|
||||
*/
|
||||
public TenantCacheWrapper(final Cache delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see org.springframework.cache.Cache#getName()
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return tenantAware.getCurrentTenant() + "." + delegate.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see org.springframework.cache.Cache#getNativeCache()
|
||||
*/
|
||||
@Override
|
||||
public Object getNativeCache() {
|
||||
return delegate.getNativeCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key
|
||||
* @return
|
||||
* @see org.springframework.cache.Cache#get(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public ValueWrapper get(final Object key) {
|
||||
return delegate.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key
|
||||
* @param type
|
||||
* @return
|
||||
* @see org.springframework.cache.Cache#get(java.lang.Object,
|
||||
* java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public <T> T get(final Object key, final Class<T> type) {
|
||||
return delegate.get(key, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key
|
||||
* @param value
|
||||
* @see org.springframework.cache.Cache#put(java.lang.Object,
|
||||
* java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public void put(final Object key, final Object value) {
|
||||
delegate.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key
|
||||
* @param value
|
||||
* @return
|
||||
* @see org.springframework.cache.Cache#putIfAbsent(java.lang.Object,
|
||||
* java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public ValueWrapper putIfAbsent(final Object key, final Object value) {
|
||||
return delegate.putIfAbsent(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key
|
||||
* @see org.springframework.cache.Cache#evict(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public void evict(final Object key) {
|
||||
delegate.evict(key);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see org.springframework.cache.Cache#clear()
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
delegate.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 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.autoconfigure.cache;
|
||||
|
||||
import org.eclipse.hawkbit.cache.CacheConstants;
|
||||
import org.eclipse.hawkbit.cache.TenancyCacheManager;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* A configuration for configuring a cache for the download id's.
|
||||
*
|
||||
* This is done by providing a named cache.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
public class DownloadIdCacheAutoConfiguration {
|
||||
|
||||
@Autowired
|
||||
private CacheManager cacheManager;
|
||||
|
||||
/**
|
||||
* Bean for the downlod id cache.
|
||||
*
|
||||
* @return the cache
|
||||
*/
|
||||
@Bean(name = CacheConstants.DOWNLOAD_ID_CACHE)
|
||||
public Cache downloadIdCache() {
|
||||
if (cacheManager instanceof TenancyCacheManager) {
|
||||
return ((TenancyCacheManager) cacheManager).getDirectCache(CacheConstants.DOWNLOAD_ID_CACHE);
|
||||
}
|
||||
return cacheManager.getCache(CacheConstants.DOWNLOAD_ID_CACHE);
|
||||
}
|
||||
|
||||
}
|
||||
27
hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/RedisAutoConfiguration.java
vendored
Executable file
27
hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/RedisAutoConfiguration.java
vendored
Executable file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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.autoconfigure.cache;
|
||||
|
||||
import org.eclipse.hawkbit.cache.RedisConfiguration;
|
||||
import org.eclipse.hawkbit.cache.annotation.EnableRedis;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* A configuration for configuring the redis configuration.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(value = RedisConfiguration.class)
|
||||
@EnableRedis
|
||||
public class RedisAutoConfiguration {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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.autoconfigure.conf;
|
||||
|
||||
import org.eclipse.hawkbit.ControllerPollProperties;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Enable the Controlle Poll.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(ControllerPollProperties.class)
|
||||
@EnableConfigurationProperties(ControllerPollProperties.class)
|
||||
public class ControllerPollAutoConfiguration {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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.autoconfigure.conf;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
/**
|
||||
* Autoconfiguration which loads the default configuration properties for
|
||||
* hawkbit.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@PropertySource("classpath:/hawkbitdefaults.properties")
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public class DefaultPropertiesAutoConfiguration {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 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.autoconfigure.eventbus;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.EventBusSubscriberProcessor;
|
||||
import org.eclipse.hawkbit.eventbus.EventSubscriber;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.google.common.eventbus.AsyncEventBus;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
public class EventBusAutoConfiguration {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("asyncExecutor")
|
||||
private Executor executor;
|
||||
|
||||
/**
|
||||
* Server internal eventBus that allows parallel event processing if the
|
||||
* subscriber is marked as so.
|
||||
*
|
||||
* @return eventbus bean
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EventBus eventBus() {
|
||||
return new AsyncEventBus(executor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link EventBusSubscriberProcessor} to find classes annotated
|
||||
* with {@link EventSubscriber}.
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EventBusSubscriberProcessor eventBusSubscriberProcessor() {
|
||||
return new EventBusSubscriberProcessor();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 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.autoconfigure.scheduling;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.AsyncConfigurer;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@EnableAsync
|
||||
@ConditionalOnMissingBean(AsyncConfigurer.class)
|
||||
public class AsyncConfigurerAutoConfiguration implements AsyncConfigurer {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("asyncExecutor")
|
||||
private Executor executor;
|
||||
|
||||
@Override
|
||||
public Executor getAsyncExecutor() {
|
||||
return executor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
|
||||
return new SimpleAsyncUncaughtExceptionHandler();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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.autoconfigure.scheduling;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Properties for the async configurer.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.threadpool")
|
||||
public class AsyncConfigurerThreadpoolProperties {
|
||||
|
||||
private Integer queuesize = 250;
|
||||
|
||||
private Integer corethreads = 5;
|
||||
|
||||
private Integer maxthreads = 50;
|
||||
|
||||
private Long idletimeout = 10000L;
|
||||
|
||||
public Integer getQueuesize() {
|
||||
return queuesize;
|
||||
}
|
||||
|
||||
public void setQueuesize(final Integer queuesize) {
|
||||
this.queuesize = queuesize;
|
||||
}
|
||||
|
||||
public Integer getCorethreads() {
|
||||
return corethreads;
|
||||
}
|
||||
|
||||
public void setCorethreads(final Integer corethreads) {
|
||||
this.corethreads = corethreads;
|
||||
}
|
||||
|
||||
public Integer getMaxthreads() {
|
||||
return maxthreads;
|
||||
}
|
||||
|
||||
public void setMaxthreads(final Integer maxthreads) {
|
||||
this.maxthreads = maxthreads;
|
||||
}
|
||||
|
||||
public Long getIdletimeout() {
|
||||
return idletimeout;
|
||||
}
|
||||
|
||||
public void setIdletimeout(final Long idletimeout) {
|
||||
this.idletimeout = idletimeout;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* 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.autoconfigure.scheduling;
|
||||
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.RejectedExecutionHandler;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.concurrent.DelegatingSecurityContextExecutor;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(AsyncConfigurerThreadpoolProperties.class)
|
||||
public class ExecutorAutoConfiguration {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ExecutorAutoConfiguration.class);
|
||||
|
||||
@Autowired
|
||||
private AsyncConfigurerThreadpoolProperties asyncConfigurerProperties;
|
||||
|
||||
/**
|
||||
* @return ExecutorService for general pupose multi threaded operations
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public Executor asyncExecutor() {
|
||||
final BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable>(
|
||||
asyncConfigurerProperties.getQueuesize());
|
||||
final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
|
||||
asyncConfigurerProperties.getCorethreads(), asyncConfigurerProperties.getMaxthreads(),
|
||||
asyncConfigurerProperties.getIdletimeout(), TimeUnit.MILLISECONDS, blockingQueue,
|
||||
new ThreadFactoryBuilder().setNameFormat("central-executor-pool-%d").build());
|
||||
threadPoolExecutor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
|
||||
@Override
|
||||
public void rejectedExecution(final Runnable r, final java.util.concurrent.ThreadPoolExecutor executor) {
|
||||
LOGGER.warn("Reject runnable for centralExecutorService, reached limit of queue size {}", executor
|
||||
.getQueue().size());
|
||||
}
|
||||
});
|
||||
return new DelegatingSecurityContextExecutor(threadPoolExecutor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the executor for UI background processes.
|
||||
*/
|
||||
@Bean(name = "uiExecutor")
|
||||
@ConditionalOnMissingBean(name = "uiExecutor")
|
||||
public Executor uiExecutor() {
|
||||
final BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>(20);
|
||||
final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 20, 10000, TimeUnit.MILLISECONDS,
|
||||
blockingQueue, new ThreadFactoryBuilder().setNameFormat("ui-executor-pool-%d").build());
|
||||
threadPoolExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
return new DelegatingSecurityContextExecutor(threadPoolExecutor);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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.autoconfigure.security;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Annotation to enable the managed security configuration.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Import(SecurityManagedConfiguration.class)
|
||||
public @interface EnableHawkbitManagedSecurityConfiguration {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
/**
|
||||
* 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.autoconfigure.security;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.im.authentication.MultitenancyIndicator;
|
||||
import org.eclipse.hawkbit.im.authentication.PermissionService;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
||||
import org.eclipse.hawkbit.im.authentication.UserAuthenticationFilter;
|
||||
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
||||
import org.eclipse.hawkbit.security.SecurityProperties;
|
||||
import org.eclipse.hawkbit.security.SpringSecurityAuditorAware;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.domain.AuditorAware;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for security.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(SecurityProperties.class)
|
||||
public class SecurityAutoConfiguration {
|
||||
|
||||
/**
|
||||
* @return the {@link TenantAware} singleton bean which holds the current
|
||||
* {@link TenantAware} service and make it accessible in beans which
|
||||
* cannot access the service directly, e.g. JPA entities.
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TenantAware tenantAware() {
|
||||
return new SecurityContextTenantAware();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return permission service to check if current user has the necessary
|
||||
* permissions.
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public PermissionService permissionService() {
|
||||
return new PermissionService();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the auditore aware.
|
||||
*
|
||||
* @return the spring security auditore aware
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public AuditorAware<String> auditorAware() {
|
||||
return new SpringSecurityAuditorAware();
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto-configuration for the in-memory-user-management.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(value = { UserAuthenticationFilter.class })
|
||||
public static class InMemoryUserManagementConfiguration extends GlobalAuthenticationConfigurerAdapter {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(InMemoryUserManagementConfiguration.class);
|
||||
|
||||
@Autowired
|
||||
private AuthenticationConfiguration configuration;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.security.config.annotation.authentication.
|
||||
* configurers. GlobalAuthenticationConfigurerAdapter
|
||||
* #configure(org.springframework.security.config.annotation.
|
||||
* authentication.builders.AuthenticationManagerBuilder)
|
||||
*/
|
||||
@Override
|
||||
public void configure(final AuthenticationManagerBuilder auth) throws Exception {
|
||||
final DaoAuthenticationProvider userDaoAuthenticationProvider = new TenantDaoAuthenticationProvider();
|
||||
userDaoAuthenticationProvider.setUserDetailsService(userDetailsService());
|
||||
auth.authenticationProvider(userDaoAuthenticationProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the user details service to load a user from memory user
|
||||
* manager.
|
||||
*/
|
||||
@Bean
|
||||
public UserDetailsService userDetailsService() {
|
||||
final InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager(
|
||||
new ArrayList<>());
|
||||
inMemoryUserDetailsManager.setAuthenticationManager(null);
|
||||
inMemoryUserDetailsManager.createUser(new User("admin", "admin", getAllAuthorities()));
|
||||
return inMemoryUserDetailsManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the multi-tenancy indicator to disallow multi-tenancy
|
||||
*/
|
||||
@Bean
|
||||
public MultitenancyIndicator multiTenancyIndicator() {
|
||||
return new MultitenancyIndicator() {
|
||||
@Override
|
||||
public boolean isMultiTenancySupported() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Collection<SimpleGrantedAuthority> getAllAuthorities() {
|
||||
final List<SimpleGrantedAuthority> allPermissions = new ArrayList<>();
|
||||
final Field[] declaredFields = SpPermission.class.getDeclaredFields();
|
||||
for (final Field field : declaredFields) {
|
||||
if (Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers())) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
final String permissionName = (String) field.get(null);
|
||||
allPermissions.add(new SimpleGrantedAuthority(permissionName));
|
||||
} catch (final IllegalAccessException e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return allPermissions;
|
||||
}
|
||||
|
||||
private static class TenantDaoAuthenticationProvider extends DaoAuthenticationProvider {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.security.authentication.dao.
|
||||
* AbstractUserDetailsAuthenticationProvider
|
||||
* #createSuccessAuthentication(java.lang.Object,
|
||||
* org.springframework.security.core.Authentication,
|
||||
* org.springframework.security.core.userdetails.UserDetails)
|
||||
*/
|
||||
@Override
|
||||
protected Authentication createSuccessAuthentication(final Object principal,
|
||||
final Authentication authentication, final UserDetails user) {
|
||||
final UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(principal,
|
||||
authentication.getCredentials(), user.getAuthorities());
|
||||
result.setDetails(new TenantAwareAuthenticationDetails("DEFAULT", false));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link UserAuthenticationFilter} to include into the SP
|
||||
* security configuration.
|
||||
* @throws Exception
|
||||
* lazy bean exception maybe if the authentication manager
|
||||
* cannot be instantiated
|
||||
*/
|
||||
@Bean
|
||||
public UserAuthenticationFilter userAuthenticationFilter() throws Exception {
|
||||
return new UserAuthenticationFilterBasicAuth(configuration.getAuthenticationManager());
|
||||
}
|
||||
|
||||
private static final class UserAuthenticationFilterBasicAuth extends BasicAuthenticationFilter
|
||||
implements UserAuthenticationFilter {
|
||||
|
||||
private UserAuthenticationFilterBasicAuth(final AuthenticationManager authenticationManager) {
|
||||
super(authenticationManager);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,563 @@
|
||||
/**
|
||||
* 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.autoconfigure.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
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 javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.eclipse.hawkbit.ExcludePathAwareShallowETagFilter;
|
||||
import org.eclipse.hawkbit.cache.CacheConstants;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||
import org.eclipse.hawkbit.im.authentication.TenantUserPasswordAuthenticationToken;
|
||||
import org.eclipse.hawkbit.im.authentication.UserAuthenticationFilter;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.rest.resource.RestConstants;
|
||||
import org.eclipse.hawkbit.security.ControllerTenantAwareAuthenticationDetailsSource;
|
||||
import org.eclipse.hawkbit.security.DosFilter;
|
||||
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticateSecurityTokenFilter;
|
||||
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticatedGatewaySecurityTokenFilter;
|
||||
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticatedSecurityHeaderFilter;
|
||||
import org.eclipse.hawkbit.security.HttpDownloadAuthenticationFilter;
|
||||
import org.eclipse.hawkbit.security.PreAuthTokenSourceTrustAuthenticationProvider;
|
||||
import org.eclipse.hawkbit.security.SecurityProperties;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.boot.context.embedded.FilterRegistrationBean;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.annotation.AdviceMode;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter;
|
||||
import org.springframework.security.web.header.writers.frameoptions.StaticAllowFromStrategy;
|
||||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode;
|
||||
import org.vaadin.spring.security.VaadinSecurityContext;
|
||||
import org.vaadin.spring.security.annotation.EnableVaadinSecurity;
|
||||
import org.vaadin.spring.security.web.VaadinDefaultRedirectStrategy;
|
||||
import org.vaadin.spring.security.web.VaadinRedirectStrategy;
|
||||
import org.vaadin.spring.security.web.authentication.VaadinAuthenticationSuccessHandler;
|
||||
import org.vaadin.spring.security.web.authentication.VaadinUrlAuthenticationSuccessHandler;
|
||||
|
||||
/**
|
||||
* All configurations related to SP authentication and authorization layer.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, mode = AdviceMode.ASPECTJ, proxyTargetClass = true, securedEnabled = true)
|
||||
@EnableWebMvcSecurity
|
||||
@Order(value = Ordered.HIGHEST_PRECEDENCE)
|
||||
public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SecurityManagedConfiguration.class);
|
||||
|
||||
private static final String SP_SERVER_CONFIG_PREFIX = "hawkbit.server.";
|
||||
private RelaxedPropertyResolver environment;
|
||||
|
||||
@Override
|
||||
public void setEnvironment(final Environment environment) {
|
||||
this.environment = new RelaxedPropertyResolver(environment, SP_SERVER_CONFIG_PREFIX);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WebSecurityConfigurer} for the internal SP controller API.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@Order(300)
|
||||
static class ControllerSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private ControllerManagement controllerManagement;
|
||||
@Autowired
|
||||
private SystemManagement systemManagement;
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
@Autowired
|
||||
private SecurityProperties securityConfiguration;
|
||||
@Autowired
|
||||
private org.springframework.boot.autoconfigure.security.SecurityProperties springSecurityProperties;
|
||||
|
||||
@Override
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
final ControllerTenantAwareAuthenticationDetailsSource authenticationDetailsSource = new ControllerTenantAwareAuthenticationDetailsSource();
|
||||
|
||||
final HttpControllerPreAuthenticatedSecurityHeaderFilter securityHeaderFilter = new HttpControllerPreAuthenticatedSecurityHeaderFilter(
|
||||
securityConfiguration.getRpCnHeader(), securityConfiguration.getRpSslIssuerHashHeader(),
|
||||
systemManagement, tenantAware);
|
||||
securityHeaderFilter.setAuthenticationManager(authenticationManager());
|
||||
securityHeaderFilter.setCheckForPrincipalChanges(true);
|
||||
securityHeaderFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
||||
|
||||
final HttpControllerPreAuthenticateSecurityTokenFilter securityTokenFilter = new HttpControllerPreAuthenticateSecurityTokenFilter(
|
||||
systemManagement, tenantAware, controllerManagement);
|
||||
securityTokenFilter.setAuthenticationManager(authenticationManager());
|
||||
securityTokenFilter.setCheckForPrincipalChanges(true);
|
||||
securityTokenFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
||||
|
||||
final HttpControllerPreAuthenticatedGatewaySecurityTokenFilter gatewaySecurityTokenFilter = new HttpControllerPreAuthenticatedGatewaySecurityTokenFilter(
|
||||
systemManagement, tenantAware);
|
||||
gatewaySecurityTokenFilter.setAuthenticationManager(authenticationManager());
|
||||
gatewaySecurityTokenFilter.setCheckForPrincipalChanges(true);
|
||||
gatewaySecurityTokenFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
||||
|
||||
HttpSecurity httpSec = http.csrf().disable().headers()
|
||||
.addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.DENY)).contentTypeOptions()
|
||||
.xssProtection().httpStrictTransportSecurity().and();
|
||||
|
||||
if (springSecurityProperties.isRequireSsl()) {
|
||||
httpSec = httpSec.requiresChannel().anyRequest().requiresSecure().and();
|
||||
}
|
||||
|
||||
if (securityConfiguration.getAnonymousEnabled()) {
|
||||
LOG.info(
|
||||
"******************\n** Anonymous controller security enabled, should only use for developing purposes **\n******************");
|
||||
final AnonymousAuthenticationFilter anoymousFilter = new AnonymousAuthenticationFilter(
|
||||
"controllerAnonymousFilter", "anonymous", Collections.singletonList(
|
||||
new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS)));
|
||||
anoymousFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
||||
httpSec.requestMatchers().antMatchers("/*/controller/v1/**", "/*/controller/artifacts/v1/**").and()
|
||||
.securityContext().disable().anonymous().authenticationFilter(anoymousFilter);
|
||||
} else {
|
||||
httpSec.addFilter(securityHeaderFilter).addFilter(securityTokenFilter)
|
||||
.addFilter(gatewaySecurityTokenFilter).antMatcher("/*/controller/**").anonymous().disable()
|
||||
.authorizeRequests().anyRequest().authenticated().and().exceptionHandling()
|
||||
.authenticationEntryPoint(new AuthenticationEntryPoint() {
|
||||
@Override
|
||||
public void commence(final HttpServletRequest request, final HttpServletResponse response,
|
||||
final AuthenticationException authException) throws IOException, ServletException {
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
}
|
||||
}).and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.security.config.annotation.web.configuration.
|
||||
* WebSecurityConfigurerAdapter
|
||||
* #configure(org.springframework.security.config.annotation.
|
||||
* authentication.builders. AuthenticationManagerBuilder)
|
||||
*/
|
||||
@Override
|
||||
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.authenticationProvider(
|
||||
new PreAuthTokenSourceTrustAuthenticationProvider(securityConfiguration.getRpTrustedIPs()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter to protect the SP server against denial of service attacks.
|
||||
*
|
||||
* @return he spring filter registration bean for registering an denial of
|
||||
* service protection filter in the filter chain
|
||||
*/
|
||||
@Bean
|
||||
@Order(50)
|
||||
public FilterRegistrationBean dosFilter() {
|
||||
final FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
|
||||
|
||||
filterRegBean
|
||||
.setFilter(
|
||||
new DosFilter(environment.getProperty("security.dos.filter.maxRead", Integer.class, 100),
|
||||
environment.getProperty("security.dos.filter.maxWrite", Integer.class, 10),
|
||||
environment.getProperty("security.dos.filter.whitelist"), environment
|
||||
.getProperty("security.clients.blacklist"),
|
||||
environment.getProperty("security.rp.remote_ip_header", String.class, "X-Forwarded-For")));
|
||||
filterRegBean.addUrlPatterns("/{tenant}/controller/v1/*", "/rest/*");
|
||||
return filterRegBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter registration bean for spring etag filter.
|
||||
*
|
||||
* @return the spring filter registration bean for registering an etag
|
||||
* filter in the filter chain
|
||||
*/
|
||||
@Bean
|
||||
@Order(100)
|
||||
public FilterRegistrationBean eTagFilter() {
|
||||
final FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
|
||||
// eclude the URLs for downloading artifacts, so no eTag is generated in
|
||||
// the
|
||||
// ShallowEtagHeaderFilter, just using the SH1 hash of the artifact
|
||||
// itself as 'ETag', because
|
||||
// otherwise the file will be copied in memory!
|
||||
filterRegBean.setFilter(new ExcludePathAwareShallowETagFilter(
|
||||
"/rest/v1/softwaremodules/{smId}/artifacts/{artId}/download", "/{tenant}/controller/artifacts/**",
|
||||
"/{targetid}/softwaremodules/{softwareModuleId}/artifacts/**"));
|
||||
return filterRegBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Security configuration for the REST management API of the health url.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@Order(310)
|
||||
public static class HealthSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
http.regexMatcher("/system/health").csrf().disable().httpBasic().and().sessionManagement()
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Security configuration for the REST management API.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@Order(350)
|
||||
public static class RestSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
|
||||
@Autowired
|
||||
private UserAuthenticationFilter userAuthenticationFilter;
|
||||
@Autowired
|
||||
private SystemManagement systemManagement;
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
@Autowired
|
||||
private org.springframework.boot.autoconfigure.security.SecurityProperties springSecurityProperties;
|
||||
|
||||
@Override
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
|
||||
HttpSecurity httpSec = http.regexMatcher("\\/rest.*|\\/system.*").csrf().disable();
|
||||
if (springSecurityProperties.isRequireSsl()) {
|
||||
httpSec = httpSec.requiresChannel().anyRequest().requiresSecure().and();
|
||||
}
|
||||
httpSec.addFilterBefore(new Filter() {
|
||||
@Override
|
||||
public void init(final FilterConfig filterConfig) throws ServletException {
|
||||
userAuthenticationFilter.init(filterConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(final ServletRequest request, final ServletResponse response,
|
||||
final FilterChain chain) throws IOException, ServletException {
|
||||
userAuthenticationFilter.doFilter(request, response, chain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
userAuthenticationFilter.destroy();
|
||||
}
|
||||
}, RequestHeaderAuthenticationFilter.class)
|
||||
.addFilterAfter(
|
||||
new AuthenticationSuccessTenantMetadataCreationFilter(tenantAware, systemManagement),
|
||||
RequestHeaderAuthenticationFilter.class)
|
||||
.authorizeRequests().anyRequest().authenticated()
|
||||
.antMatchers(RestConstants.BASE_SYSTEM_MAPPING + "/admin/**")
|
||||
.hasAnyAuthority(SpPermission.SYSTEM_ADMIN).antMatchers(RestConstants.BASE_SYSTEM_MAPPING + "/**")
|
||||
.hasAnyAuthority(SpPermission.SYSTEM_DIAG);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WebSecurityConfigurer} for external (management) access.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@Order(400)
|
||||
@EnableVaadinSecurity
|
||||
public static class UISecurityConfigurationAdapter extends WebSecurityConfigurerAdapter
|
||||
implements EnvironmentAware {
|
||||
|
||||
private static final String XFRAME_OPTION_DENY = "DENY";
|
||||
private static final String XFRAME_OPTION_SAMEORIGIN = "SAMEORIGIN";
|
||||
private static final String XFAME_OPTION_ALLOW_FROM = "ALLOW-FROM";
|
||||
@Autowired
|
||||
private VaadinSecurityContext vaadinSecurityContext;
|
||||
@Autowired
|
||||
private org.springframework.boot.autoconfigure.security.SecurityProperties springSecurityProperties;
|
||||
|
||||
private RelaxedPropertyResolver environment;
|
||||
|
||||
@Override
|
||||
public void setEnvironment(final Environment environment) {
|
||||
this.environment = new RelaxedPropertyResolver(environment, SP_SERVER_CONFIG_PREFIX);
|
||||
}
|
||||
|
||||
/**
|
||||
* post construct for setting the authentication success handler for the
|
||||
* vaadin security context.
|
||||
*/
|
||||
@PostConstruct
|
||||
public void afterPropertiesSet() {
|
||||
this.vaadinSecurityContext.addAuthenticationSuccessHandler(redirectSaveHandler());
|
||||
}
|
||||
|
||||
@Bean(name = "authenticationManager")
|
||||
@Override
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The VaadinRedirectStategy
|
||||
*/
|
||||
@Bean
|
||||
public VaadinRedirectStrategy vaadinRedirectStrategy() {
|
||||
return new VaadinDefaultRedirectStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the vaadin success authentication handler
|
||||
*/
|
||||
@Bean
|
||||
public VaadinAuthenticationSuccessHandler redirectSaveHandler() {
|
||||
final VaadinUrlAuthenticationSuccessHandler handler = new TenantMetadataSavedRequestAwareVaadinAuthenticationSuccessHandler();
|
||||
handler.setRedirectStrategy(vaadinRedirectStrategy());
|
||||
handler.setDefaultTargetUrl("/UI/");
|
||||
handler.setTargetUrlParameter("r");
|
||||
return handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
|
||||
// configuration xframe-option
|
||||
final String confXframeOption = environment.getProperty("security.xframe.option", XFRAME_OPTION_DENY);
|
||||
final String confAllowFromUri = environment.getProperty("security.xframe.option.allowfrom");
|
||||
if (confXframeOption.equals(XFAME_OPTION_ALLOW_FROM) && confAllowFromUri == null) {
|
||||
// if allow-from option is specified but no allowFromUri throw
|
||||
// exception
|
||||
throw new IllegalStateException("hawkbit.server.security.xframe.option has been specified as ALLOW-FROM"
|
||||
+ " but no hawkbit.server.security.xframe.option.allowfrom has been set, "
|
||||
+ "please ensure to set allow from URIs");
|
||||
}
|
||||
|
||||
// workaround regex: we need to exclude the URL /UI/HEARTBEAT here
|
||||
// because we bound the
|
||||
// vaadin application to /UI and not to root, described in
|
||||
// vaadin-forum:
|
||||
// https://vaadin.com/forum#!/thread/3200565.
|
||||
HttpSecurity httpSec = http.regexMatcher("(?!.*HEARTBEAT)^.*\\/UI.*$")
|
||||
// disable as CSRF is handled by Vaadin
|
||||
.csrf().disable();
|
||||
|
||||
if (springSecurityProperties.isRequireSsl()) {
|
||||
httpSec = httpSec.requiresChannel().anyRequest().requiresSecure().and();
|
||||
} else {
|
||||
LOG.info(
|
||||
"\"******************\\n** Requires HTTPS Security has been disabled for UI, should only use for developing purposes **\\n******************\"");
|
||||
}
|
||||
|
||||
// for UI integrator we allow frame integration on same origin
|
||||
httpSec.headers()
|
||||
.addHeaderWriter(confXframeOption.equals(XFAME_OPTION_ALLOW_FROM)
|
||||
? new XFrameOptionsHeaderWriter(new StaticAllowFromStrategy(new URI(confAllowFromUri)))
|
||||
: new XFrameOptionsHeaderWriter(xframeOptionFromStr(confXframeOption)))
|
||||
.contentTypeOptions().xssProtection().httpStrictTransportSecurity().and()
|
||||
// UI
|
||||
.authorizeRequests().antMatchers("/UI/login/**").permitAll().antMatchers("/UI/UIDL/**").permitAll()
|
||||
.anyRequest().authenticated().and()
|
||||
// UI login / logout
|
||||
.exceptionHandling().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/UI/login/#/"))
|
||||
.and().logout().logoutUrl("/UI/logout").logoutSuccessUrl("/UI/login/#/");
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a given string into the {@link XFrameOptionsMode} enum. Only
|
||||
* {@link XFrameOptionsMode#DENY} and
|
||||
* {@link XFrameOptionsMode#SAMEORIGIN} any other string will be
|
||||
* converted to the default {@link XFrameOptionsMode#SAMEORIGIN}.
|
||||
*
|
||||
* @param xframeOption
|
||||
* the string of the xframe option
|
||||
* @return an {@link XFrameOptionsMode} by the given string, in case
|
||||
* string does not match an option then
|
||||
* {@link XFrameOptionsMode#SAMEORIGIN} is returned
|
||||
*/
|
||||
private XFrameOptionsMode xframeOptionFromStr(@NotNull final String xframeOption) {
|
||||
switch (xframeOption) {
|
||||
case XFRAME_OPTION_DENY:
|
||||
return XFrameOptionsMode.DENY;
|
||||
case XFRAME_OPTION_SAMEORIGIN:
|
||||
// fall through to default because the same
|
||||
default:
|
||||
return XFrameOptionsMode.SAMEORIGIN;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(final WebSecurity webSecurity) throws Exception {
|
||||
webSecurity.ignoring().antMatchers("/documentation/**", "/VAADIN/**", "/*.*", "/v2/api-docs/**",
|
||||
"/docs/**");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Websecruity config to handle and filter the download ids.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@Order(200)
|
||||
public static class IdRestSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private SecurityProperties securityConfiguration;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(CacheConstants.DOWNLOAD_ID_CACHE)
|
||||
private Cache downloadIdCache;
|
||||
|
||||
@Override
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
final HttpDownloadAuthenticationFilter downloadIdAuthenticationFilter = new HttpDownloadAuthenticationFilter(
|
||||
downloadIdCache);
|
||||
downloadIdAuthenticationFilter.setAuthenticationManager(authenticationManager());
|
||||
|
||||
http.csrf().disable();
|
||||
http.anonymous().disable();
|
||||
|
||||
http.regexMatcher(HttpDownloadAuthenticationFilter.REQUEST_ID_REGEX_PATTERN)
|
||||
.addFilterBefore(downloadIdAuthenticationFilter, FilterSecurityInterceptor.class);
|
||||
http.authorizeRequests().anyRequest().authenticated();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.authenticationProvider(
|
||||
new PreAuthTokenSourceTrustAuthenticationProvider(securityConfiguration.getRpTrustedIPs()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* After a successful login on the UI we need to ensure to create the tenant
|
||||
* meta data within SP.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class TenantMetadataSavedRequestAwareVaadinAuthenticationSuccessHandler extends VaadinUrlAuthenticationSuccessHandler {
|
||||
|
||||
@Autowired
|
||||
private SystemManagement systemManagement;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.vaadin.spring.security.web.authentication.
|
||||
* SavedRequestAwareVaadinAuthenticationSuccessHandler
|
||||
* #onAuthenticationSuccess(org.springframework.security.core.
|
||||
* Authentication)
|
||||
*/
|
||||
@Override
|
||||
public void onAuthenticationSuccess(final Authentication authentication) throws Exception {
|
||||
if (authentication.getClass().equals(TenantUserPasswordAuthenticationToken.class)) {
|
||||
systemManagement
|
||||
.getTenantMetadata(((TenantUserPasswordAuthenticationToken) authentication).getTenant().toString());
|
||||
} else if (authentication.getClass().equals(UsernamePasswordAuthenticationToken.class)) {
|
||||
// TODO: MECS-1078 vaadin4spring-ext-security does not give us the
|
||||
// fullyAuthenticatedToken
|
||||
// in the GenericVaadinSecurity class. Only the token which has been
|
||||
// created in the
|
||||
// LoginView. This needs to be changed with the update of
|
||||
// vaadin4spring 0.0.7 because it
|
||||
// has been fixed.
|
||||
systemManagement.getTenantMetadata("DEFAULT");
|
||||
}
|
||||
super.onAuthenticationSuccess(authentication);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sevletfilter to create metadata after successful authentication over RESTful.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class AuthenticationSuccessTenantMetadataCreationFilter implements Filter {
|
||||
|
||||
private final TenantAware tenantAware;
|
||||
private final SystemManagement systemManagement;
|
||||
|
||||
AuthenticationSuccessTenantMetadataCreationFilter(final TenantAware tenantAware,
|
||||
final SystemManagement systemManagement) {
|
||||
this.tenantAware = tenantAware;
|
||||
this.systemManagement = systemManagement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(final FilterConfig filterConfig) throws ServletException {
|
||||
// not needed
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
final String currentTenant = tenantAware.getCurrentTenant();
|
||||
if (currentTenant != null) {
|
||||
// lazy initialize tenant meta data after successful authentication
|
||||
systemManagement.getTenantMetadata(currentTenant);
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// not needed
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* 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.autoconfigure.swagger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.rest.resource.RestConstants;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.schema.ModelRef;
|
||||
import springfox.documentation.service.ApiInfo;
|
||||
import springfox.documentation.service.ResponseMessage;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
|
||||
/**
|
||||
* Swagger configuration for RESTful SP server APIs.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@EnableSwagger2
|
||||
public class SwaggerApiDocAutoConfiguration {
|
||||
|
||||
/**
|
||||
* Create the Springfox Docket, which generates the Information for the
|
||||
* REST-Swagger-UI. Rest paths are: /rest/v1/. and ./controller/v1/.
|
||||
*
|
||||
* @see springfox.documentation.spring.web.plugins.Docket
|
||||
*
|
||||
* @return the v1 docket
|
||||
*/
|
||||
@Bean
|
||||
public Docket customImplementation() {
|
||||
return createDocket();
|
||||
}
|
||||
|
||||
private Predicate<String> selectApiPaths() {
|
||||
return Predicates.or(PathSelectors.regex("/rest/v1/.*"), PathSelectors.regex("/.*/controller/v1/.*"));
|
||||
}
|
||||
|
||||
private Docket createDocket() {
|
||||
final List<ResponseMessage> authorizationMessages = globalAuhtorizationMessages();
|
||||
return new Docket(DocumentationType.SWAGGER_2).select().paths(selectApiPaths()).build()
|
||||
.useDefaultResponseMessages(true).globalResponseMessage(RequestMethod.GET, authorizationMessages)
|
||||
.globalResponseMessage(RequestMethod.POST, authorizationMessages)
|
||||
.globalResponseMessage(RequestMethod.PUT, authorizationMessages)
|
||||
.globalResponseMessage(RequestMethod.DELETE, authorizationMessages).apiInfo(apiInfo());
|
||||
}
|
||||
|
||||
private List<ResponseMessage> globalAuhtorizationMessages() {
|
||||
final List<ResponseMessage> messageList = new ArrayList<>();
|
||||
messageList.add(new ResponseMessage(200, "Request sucessfull", new ModelRef("com.")));
|
||||
messageList.add(new ResponseMessage(400, "Bad Request - e.g. invalid parameters", null));
|
||||
messageList.add(new ResponseMessage(401, "Unauthorized - The request requires user authentication.",
|
||||
|
||||
null));
|
||||
messageList.add(
|
||||
new ResponseMessage(403, "Forbidden - Insufficient permissions or data volume restriction applies.",
|
||||
new ModelRef("ExceptionInfo")));
|
||||
messageList.add(new ResponseMessage(405, "Method Not Allowed", null));
|
||||
messageList.add(new ResponseMessage(406,
|
||||
"Not Acceptable - In case accept header is specified and not application/json", null));
|
||||
messageList.add(new ResponseMessage(429,
|
||||
"Too many requests. The server will refuse further attemps and the client has to wait another second.",
|
||||
null));
|
||||
return messageList;
|
||||
}
|
||||
|
||||
private ApiInfo apiInfo() {
|
||||
return new ApiInfoBuilder().title("Software Provisioning API Descriptions").version(RestConstants.API_VERSION)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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.autoconfigure.ui;
|
||||
|
||||
import org.eclipse.hawkbit.DistributedResourceBundleMessageSource;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.vaadin.spring.annotation.EnableVaadinExtensions;
|
||||
import org.vaadin.spring.events.annotation.EnableEventBus;
|
||||
import org.vaadin.spring.security.annotation.EnableVaadinSecurity;
|
||||
|
||||
/**
|
||||
* The hawkbit-ui autoconfiguration.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableVaadinSecurity
|
||||
@EnableVaadinExtensions
|
||||
@EnableEventBus
|
||||
public class UIAutoConfiguration {
|
||||
|
||||
/**
|
||||
* A message source bean to add distributed message sources.
|
||||
*
|
||||
* @return the message bean.
|
||||
*/
|
||||
@Bean(name = "messageSource")
|
||||
public DistributedResourceBundleMessageSource messageSource() {
|
||||
return new DistributedResourceBundleMessageSource();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* 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.autoconfigure.url;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.eclipse.hawkbit.api.HostnameResolver;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
|
||||
/**
|
||||
* Autoconfiguration of the {@link HostnameResolver} based on a property.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(ServerProperties.class)
|
||||
public class PropertyHostnameResolverAutoConfiguration {
|
||||
|
||||
@Autowired
|
||||
private ServerProperties serverProperties;
|
||||
|
||||
/**
|
||||
* @return the default autoconfigure hostname resolver implementation which
|
||||
* is property based specified by the property {@link #url}
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(value = HostnameResolver.class)
|
||||
public HostnameResolver hostnameResolver() {
|
||||
return new HostnameResolver() {
|
||||
@Override
|
||||
public URL resolveHostname() {
|
||||
try {
|
||||
return new URL(serverProperties.getUrl());
|
||||
} catch (final MalformedURLException e) {
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.autoconfigure.url;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Properties for the server e.g. the server's URL which must be configured.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.server")
|
||||
public class ServerProperties {
|
||||
|
||||
private String url = "http://localhost:8080";
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(final String url) {
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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.autoconfigure.web;
|
||||
|
||||
import org.eclipse.hawkbit.controller.EnableDirectDeviceApi;
|
||||
import org.eclipse.hawkbit.rest.resource.EnableRestResources;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Auto-Configuration for enabling the REST-Resources.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ EnableDirectDeviceApi.class, EnableRestResources.class })
|
||||
@Import({ EnableDirectDeviceApi.class, EnableRestResources.class })
|
||||
public class ResourceControllerAutoConfiguration {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* 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.autoconfigure.web;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
/**
|
||||
* A configuration bean which disables the {@code useSuffixPatternMatch} feature
|
||||
* from Spring because it will truncate the dot in a REST URL which leads to
|
||||
* problem in case a controllerId contains dots and is a path parameter or
|
||||
* filename ending.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
public class WebMvcAutoConfiguration extends WebMvcConfigurerAdapter {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
|
||||
* #configurePathMatch
|
||||
* (org.springframework.web.servlet.config.annotation.PathMatchConfigurer)
|
||||
*/
|
||||
@Override
|
||||
public void configurePathMatch(final PathMatchConfigurer configurer) {
|
||||
configurer.setUseSuffixPatternMatch(false);
|
||||
configurer.setUseRegisteredSuffixPatternMatch(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.web.servlet.config.annotation.
|
||||
* WebMvcConfigurerAdapter# configureContentNegotiation
|
||||
* (org.springframework.web.servlet.config.annotation.
|
||||
* ContentNegotiationConfigurer)
|
||||
*/
|
||||
@Override
|
||||
public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) {
|
||||
configurer.favorPathExtension(false);
|
||||
}
|
||||
}
|
||||
16
hawkbit-autoconfigure/src/main/resources/META-INF/spring.factories
Executable file
16
hawkbit-autoconfigure/src/main/resources/META-INF/spring.factories
Executable file
@@ -0,0 +1,16 @@
|
||||
# Auto Configure
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.eclipse.hawkbit.autoconfigure.conf.DefaultPropertiesAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.ui.UIAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.security.SecurityAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.swagger.SwaggerApiDocAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.url.PropertyHostnameResolverAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.web.WebMvcAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.cache.CacheAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.cache.DownloadIdCacheAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.eventbus.EventBusAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.scheduling.AsyncConfigurerAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.cache.RedisAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.scheduling.ExecutorAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.conf.ControllerPollAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.amqp.AmqpAutoConfiguration
|
||||
57
hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties
Executable file
57
hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties
Executable file
@@ -0,0 +1,57 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
# Tomcat / Server
|
||||
server.tomcat.compression=on
|
||||
spring.http.gzip.mime-types=text/html,text/xml,text/plain,application/json,application/javascript,text/css,application/x-javascript,text/javascript,application/vnd.ms-fontobject,application/x-font-opentype,application/x-font-truetype,application/x-font-ttf,application/xml,font/eot,font/opentype,font/otf,image/svg+xml,image/vnd.microsoft.icon
|
||||
server.tomcat.compressable-mime-types=${spring.http.gzip.mime-types}
|
||||
spring.http.gzip.min-gzip-size=256
|
||||
|
||||
# JPA / Datasource
|
||||
spring.jpa.eclipselink.eclipselink.weaving=false
|
||||
spring.jpa.database=H2
|
||||
spring.jpa.show-sql=false
|
||||
spring.datasource.driverClassName=org.h2.Driver
|
||||
|
||||
# MongoDB for artifact-repository
|
||||
spring.data.mongodb.uri=mongodb://localhost/artifactrepo
|
||||
spring.data.mongo.repositories.enabled=true
|
||||
|
||||
# Flyway DDL
|
||||
flyway.enabled=true
|
||||
flyway.initOnMigrate=true
|
||||
flyway.sqlMigrationSuffix=${spring.jpa.database}.sql
|
||||
|
||||
# Vaadin Servlet
|
||||
vaadin.static.servlet.params.resourceCacheTime=${spring.resources.cache-period}
|
||||
vaadin.static.servlet.params.productionMode=true
|
||||
vaadin.servlet.params.productionMode=true
|
||||
vaadin.servlet.params.resourceCacheTime=${spring.resources.cache-period}
|
||||
vaadin.servlet.urlMapping=/UI/*
|
||||
vaadin.servlet.params.heartbeatInterval=60
|
||||
vaadin.servlet.params.closeIdleSessions=false
|
||||
|
||||
# Spring MVC
|
||||
spring.mvc.favicon.enabled=false
|
||||
|
||||
|
||||
# Defines the thread pool executor
|
||||
hawkbit.threadpool.corethreads=5
|
||||
hawkbit.threadpool.maxthreads=20
|
||||
hawkbit.threadpool.idletimeout=10000
|
||||
hawkbit.threadpool.queuesize=250
|
||||
|
||||
# Defines the polling time for the controllers in HH:MM:SS notation
|
||||
hawkbit.controller.pollingTime=00:05:00
|
||||
hawkbit.controller.pollingOverdueTime=00:05:00
|
||||
|
||||
## Configuration for RabbitMQ integration
|
||||
hawkbit.dmf.rabbitmq.deadLetterQueue=dmf_connector_deadletter
|
||||
hawkbit.dmf.rabbitmq.deadLetterExchange=dmf.connector.deadletter
|
||||
hawkbit.dmf.rabbitmq.receiverQueue=dmf_receiver
|
||||
70
hawkbit-cache-redis/pom.xml
Executable file
70
hawkbit-cache-redis/pom.xml
Executable file
@@ -0,0 +1,70 @@
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-parent</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>hawkbit-cache-redis</artifactId>
|
||||
<name>hawkBit :: Redis Cache Manager</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easytesting</groupId>
|
||||
<artifactId>fest-assert-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easytesting</groupId>
|
||||
<artifactId>fest-assert</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.hateoas</groupId>
|
||||
<artifactId>spring-hateoas</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.yandex.qatools.allure</groupId>
|
||||
<artifactId>allure-junit-adaptor</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
109
hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisConfiguration.java
vendored
Executable file
109
hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisConfiguration.java
vendored
Executable file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* 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.cache;
|
||||
|
||||
import org.eclipse.hawkbit.cache.eventbus.EventDistributor;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.cache.RedisCacheManager;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
|
||||
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
|
||||
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
|
||||
|
||||
/**
|
||||
* The spring Redis configuration which is enabled by using the profile
|
||||
* {@code redis} to use a Redis server as cache.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(RedisProperties.class)
|
||||
public class RedisConfiguration {
|
||||
|
||||
@Autowired
|
||||
private RedisProperties redisProperties;
|
||||
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
|
||||
/**
|
||||
* @return the {@link EventDistributor} to distribute and consume the events
|
||||
* from Redis
|
||||
*/
|
||||
@Bean
|
||||
public EventDistributor eventDistributor() {
|
||||
return new EventDistributor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the spring redis cache manager.
|
||||
*/
|
||||
@Bean
|
||||
public CacheManager cacheManager() {
|
||||
return new TenantAwareCacheManager(new RedisCacheManager(redisTemplate()), tenantAware);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the redis connection factory to create a redis connection based
|
||||
* on the {@link RedisProperties}
|
||||
*/
|
||||
@Bean
|
||||
public JedisConnectionFactory jedisConnectionFactory() {
|
||||
final JedisConnectionFactory factory = new JedisConnectionFactory();
|
||||
factory.setHostName(redisProperties.getHost());
|
||||
factory.setPort(redisProperties.getPort());
|
||||
factory.setUsePool(true);
|
||||
return factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the spring {@link RedisTemplate} configured with the necessary
|
||||
* object serializers
|
||||
*/
|
||||
@Bean
|
||||
public RedisTemplate<String, Object> redisTemplate() {
|
||||
final RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
|
||||
redisTemplate.setConnectionFactory(jedisConnectionFactory());
|
||||
redisTemplate.setKeySerializer(new JdkSerializationRedisSerializer());
|
||||
redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
|
||||
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
|
||||
return redisTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the spring-redis message listener adapter to consume messages
|
||||
* from the Redis server
|
||||
*/
|
||||
@Bean
|
||||
public MessageListenerAdapter messageListenerAdapter() {
|
||||
final MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(eventDistributor());
|
||||
messageListenerAdapter.setSerializer(new JdkSerializationRedisSerializer());
|
||||
return messageListenerAdapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the spring-redis message listener container to register the
|
||||
* message listener adapter
|
||||
*/
|
||||
@Bean
|
||||
public RedisMessageListenerContainer redisContainer() {
|
||||
final RedisMessageListenerContainer container = new RedisMessageListenerContainer();
|
||||
container.setConnectionFactory(jedisConnectionFactory());
|
||||
container.addMessageListener(messageListenerAdapter(), eventDistributor().getTopics());
|
||||
return container;
|
||||
}
|
||||
|
||||
}
|
||||
56
hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisProperties.java
vendored
Executable file
56
hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisProperties.java
vendored
Executable file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* 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.cache;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Bean which holds the necessary properties for configuring the Redis
|
||||
* connection.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.server.redis")
|
||||
public class RedisProperties {
|
||||
|
||||
private String host;
|
||||
private int port;
|
||||
|
||||
/**
|
||||
* @return the host
|
||||
*/
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param host
|
||||
* the host to set
|
||||
*/
|
||||
public void setHost(final String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the port
|
||||
*/
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param port
|
||||
* the port to set
|
||||
*/
|
||||
public void setPort(final int port) {
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
29
hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/annotation/EnableRedis.java
vendored
Executable file
29
hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/annotation/EnableRedis.java
vendored
Executable file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 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.cache.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.eclipse.hawkbit.cache.RedisConfiguration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Annotation to enable redis caching.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Import(RedisConfiguration.class)
|
||||
public @interface EnableRedis {
|
||||
|
||||
}
|
||||
138
hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/eventbus/EventDistributor.java
vendored
Executable file
138
hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/eventbus/EventDistributor.java
vendored
Executable file
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* 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.cache.eventbus;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.EventSubscriber;
|
||||
import org.eclipse.hawkbit.eventbus.event.DistributedEvent;
|
||||
import org.eclipse.hawkbit.eventbus.event.Event;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.listener.PatternTopic;
|
||||
import org.springframework.data.redis.listener.Topic;
|
||||
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
@EventSubscriber
|
||||
public class EventDistributor {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(EventDistributor.class);
|
||||
/**
|
||||
* the node id to filter self published events in the redis message
|
||||
* subscriber.
|
||||
*/
|
||||
private static final String NODE_ID = UUID.randomUUID().toString();
|
||||
|
||||
private static final String DISTRIBUTION_CHANNEL_TOPIC = "com/bosch/sp/distEvent";
|
||||
private static final String SEND_DISTRIBUTION_CHANNEL = DISTRIBUTION_CHANNEL_TOPIC + "/" + NODE_ID;
|
||||
private static final String SUB_DISTRIBUTION_CHANNEL = DISTRIBUTION_CHANNEL_TOPIC + "*";
|
||||
|
||||
@Autowired(required = false)
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Autowired
|
||||
private EventBus eventBus;
|
||||
|
||||
/**
|
||||
* consumes all {@link DistributedEvent}s posted on the {@link EventBus} and
|
||||
* distribute them to the Redis server.
|
||||
*
|
||||
* @param event
|
||||
* the distributed event posted on the {@link EventBus}
|
||||
*/
|
||||
@Subscribe
|
||||
public void distribute(final DistributedEvent event) {
|
||||
if (redisTemplate != null) {
|
||||
if (!NODE_ID.equals(event.getNodeId())) {
|
||||
logDistributingEvent(event, SEND_DISTRIBUTION_CHANNEL);
|
||||
event.setOriginNodeId(NODE_ID);
|
||||
redisTemplate.convertAndSend(SEND_DISTRIBUTION_CHANNEL, event);
|
||||
}
|
||||
} else {
|
||||
logNotDistributingEvent(event, SEND_DISTRIBUTION_CHANNEL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* message listener callback method for the {@link MessageListenerAdapter}
|
||||
* which calls the method in case a message is received from the Redis
|
||||
* server of the type {@link DistributedEventWrapper}.
|
||||
*
|
||||
* @param event
|
||||
* the {@link DistributedEventWrapper} event which was received
|
||||
* by the Redis client
|
||||
* @param channel
|
||||
* the on which the event was received
|
||||
*/
|
||||
public void handleMessage(final DistributedEvent event, final String channel) {
|
||||
LOGGER.trace("retrieving event from redis {} on channel {}, posting to the local event bus", event, channel);
|
||||
if (!NODE_ID.equals(event.getOriginNodeId())) {
|
||||
event.setNodeId(NODE_ID);
|
||||
eventBus.post(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a collection of all topics which this Redis message listener
|
||||
* wants to subscribe
|
||||
*/
|
||||
public Collection<Topic> getTopics() {
|
||||
final List<Topic> topics = new ArrayList<Topic>();
|
||||
topics.add(new PatternTopic(SUB_DISTRIBUTION_CHANNEL));
|
||||
return topics;
|
||||
}
|
||||
|
||||
private void logDistributingEvent(final Event event, final String channel) {
|
||||
LOGGER.trace("distributing event {} from node {} to topic {}", event, NODE_ID, channel);
|
||||
}
|
||||
|
||||
private void logNotDistributingEvent(final Event event, final String channel) {
|
||||
LOGGER.debug("no redis template configured, event {} will not be distributed to channel {} from node {}", event,
|
||||
channel, NODE_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* testing purposes.
|
||||
*
|
||||
* @param redisTemplate
|
||||
* the redisTemplate to set
|
||||
*/
|
||||
void setRedisTemplate(final RedisTemplate<String, Object> redisTemplate) {
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* testing purposes.
|
||||
*
|
||||
* @param eventBus
|
||||
* the eventBus to set
|
||||
*/
|
||||
void setEventBus(final EventBus eventBus) {
|
||||
this.eventBus = eventBus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the nodeId
|
||||
*/
|
||||
static String getNodeId() {
|
||||
return NODE_ID;
|
||||
}
|
||||
}
|
||||
222
hawkbit-cache-redis/src/test/java/org/eclipse/hawkbit/cache/eventbus/EventDistributorTest.java
vendored
Executable file
222
hawkbit-cache-redis/src/test/java/org/eclipse/hawkbit/cache/eventbus/EventDistributorTest.java
vendored
Executable file
@@ -0,0 +1,222 @@
|
||||
/**
|
||||
* 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.cache.eventbus;
|
||||
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.event.DownloadProgressEvent;
|
||||
import org.eclipse.hawkbit.eventbus.event.EntityEvent;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.listener.Topic;
|
||||
import org.springframework.hateoas.Identifiable;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class EventDistributorTest {
|
||||
|
||||
@Mock
|
||||
private RedisTemplate<String, Object> redisTemplateMock;
|
||||
|
||||
@Mock
|
||||
private EventBus eventBusMock;
|
||||
|
||||
private EventDistributor underTest;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
underTest = new EventDistributor();
|
||||
underTest.setEventBus(eventBusMock);
|
||||
underTest.setRedisTemplate(redisTemplateMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void distributeDistributedEventSendsToRedis() {
|
||||
|
||||
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 10);
|
||||
underTest.distribute(event);
|
||||
|
||||
// origin node ID should be set by distributing the event
|
||||
assertThat(event.getOriginNodeId()).isNotNull();
|
||||
verify(redisTemplateMock).convertAndSend(anyString(), eq(event));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dontDistributeDistributedEventIfSameNode() {
|
||||
final String knownNodeId = EventDistributor.getNodeId();
|
||||
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 10);
|
||||
event.setNodeId(knownNodeId);
|
||||
|
||||
// test
|
||||
underTest.distribute(event);
|
||||
|
||||
assertThat(event.getOriginNodeId()).isNull();
|
||||
verify(redisTemplateMock, times(0)).convertAndSend(anyString(), eq(event));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleDistributedMessageFromRedis() {
|
||||
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 10);
|
||||
final String knownChannel = "someChannel";
|
||||
|
||||
underTest.handleMessage(event, knownChannel);
|
||||
|
||||
assertThat(event.getNodeId()).isEqualTo(EventDistributor.getNodeId());
|
||||
verify(eventBusMock).post(eq(event));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleDistributedMessageFilteredIfSameNodeId() {
|
||||
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 10);
|
||||
final String knownChannel = "someChannel";
|
||||
event.setOriginNodeId(EventDistributor.getNodeId());
|
||||
|
||||
underTest.handleMessage(event, knownChannel);
|
||||
|
||||
assertThat(event.getNodeId()).isNull();
|
||||
verify(eventBusMock, times(0)).post(eq(event));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subscribedTopicsContains2PatternTopics() {
|
||||
final Collection<Topic> topics = underTest.getTopics();
|
||||
assertThat(topics).hasSize(1);
|
||||
}
|
||||
|
||||
private class TestEntityEvent implements EntityEvent {
|
||||
|
||||
private String originNodeId;
|
||||
private String nodeId;
|
||||
private final String tenant;
|
||||
private final MyEntity entity;
|
||||
|
||||
/**
|
||||
* @param myEntity
|
||||
*/
|
||||
public TestEntityEvent(final MyEntity myEntity, final String tenant) {
|
||||
this.entity = myEntity;
|
||||
this.tenant = tenant;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.hawkbit.server.eventbus.event.Event#getRevision()
|
||||
*/
|
||||
@Override
|
||||
public long getRevision() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.eventbus.event.NodeAware#getOriginNodeId()
|
||||
*/
|
||||
@Override
|
||||
public String getOriginNodeId() {
|
||||
return originNodeId;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.eventbus.event.NodeAware#setOriginNodeId(
|
||||
* java. lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void setOriginNodeId(final String originNodeId) {
|
||||
this.originNodeId = originNodeId;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.hawkbit.server.eventbus.event.NodeAware#getNodeId()
|
||||
*/
|
||||
@Override
|
||||
public String getNodeId() {
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.eventbus.event.NodeAware#setNodeId(java.
|
||||
* lang. String)
|
||||
*/
|
||||
@Override
|
||||
public void setNodeId(final String nodeId) {
|
||||
this.nodeId = nodeId;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.eventbus.event.EntityEvent#getEntity(java.
|
||||
* lang. Class)
|
||||
*/
|
||||
@Override
|
||||
public <E> E getEntity(final Class<E> entityClass) {
|
||||
return entityClass.cast(entity);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.eventbus.event.EntityEvent#getEntity()
|
||||
*/
|
||||
@Override
|
||||
public Object getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.eventbus.event.EntityEvent#getTenant()
|
||||
*/
|
||||
@Override
|
||||
public String getTenant() {
|
||||
return tenant;
|
||||
}
|
||||
}
|
||||
|
||||
private class MyEntity implements Identifiable<String> {
|
||||
private final String id = "123";
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.hateoas.Identifiable#getId()
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
31
hawkbit-cache-redis/src/test/java/org/eclipse/hawkbit/cache/redis/RedisPropertiesTest.java
vendored
Executable file
31
hawkbit-cache-redis/src/test/java/org/eclipse/hawkbit/cache/redis/RedisPropertiesTest.java
vendored
Executable file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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.cache.redis;
|
||||
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
|
||||
import org.eclipse.hawkbit.cache.RedisProperties;
|
||||
import org.junit.Test;
|
||||
|
||||
public class RedisPropertiesTest {
|
||||
|
||||
@Test
|
||||
public void setAndGetProps() {
|
||||
final String knownHost = "bumlux";
|
||||
final int knownPort = 1234;
|
||||
|
||||
final RedisProperties underTest = new RedisProperties();
|
||||
underTest.setHost(knownHost);
|
||||
underTest.setPort(knownPort);
|
||||
|
||||
assertThat(underTest.getHost()).isEqualTo(knownHost);
|
||||
assertThat(underTest.getPort()).isEqualTo(knownPort);
|
||||
}
|
||||
|
||||
}
|
||||
50
hawkbit-core/pom.xml
Executable file
50
hawkbit-core/pom.xml
Executable file
@@ -0,0 +1,50 @@
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-parent</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>hawkbit-core</artifactId>
|
||||
<name>hawkBit :: Core</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>18.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.yandex.qatools.allure</groupId>
|
||||
<artifactId>allure-junit-adaptor</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
42
hawkbit-core/src/main/java/org/eclipse/hawkbit/ControllerPollProperties.java
Executable file
42
hawkbit-core/src/main/java/org/eclipse/hawkbit/ControllerPollProperties.java
Executable file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Defines the polling time for the controllers in HH:MM:SS notation.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
@ConfigurationProperties(prefix = "hawkbit.controller")
|
||||
public class ControllerPollProperties {
|
||||
|
||||
private String pollingTime = "00:05:00";
|
||||
private String pollingOverdueTime = "00:05:00";
|
||||
|
||||
public String getPollingTime() {
|
||||
return pollingTime;
|
||||
}
|
||||
|
||||
public void setPollingTime(final String pollingTime) {
|
||||
this.pollingTime = pollingTime;
|
||||
}
|
||||
|
||||
public String getPollingOverdueTime() {
|
||||
return pollingOverdueTime;
|
||||
}
|
||||
|
||||
public void setPollingOverdueTime(final String pollingOverdue) {
|
||||
this.pollingOverdueTime = pollingOverdue;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
|
||||
/**
|
||||
* This resource bundles using specified basenames, to resource loading. This
|
||||
* MessageSource implementation supports more than 1 properties file with the
|
||||
* same name. All properties files will be merged.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class DistributedResourceBundleMessageSource extends ReloadableResourceBundleMessageSource {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DistributedResourceBundleMessageSource.class);
|
||||
private static final String PROPERTIES_SUFFIX = ".properties";
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
/**
|
||||
* Constructor to set Defaults. Default base name is classpath*:/messages.
|
||||
* So all messages_ will be found.
|
||||
*/
|
||||
public DistributedResourceBundleMessageSource() {
|
||||
setBasename("classpath*:/messages");
|
||||
setDefaultEncoding("UTF-8");
|
||||
setUseCodeAsDefaultMessage(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PropertiesHolder refreshProperties(final String filename, final PropertiesHolder propHolder) {
|
||||
final Properties properties = new Properties();
|
||||
long lastModified = -1;
|
||||
if (!(resourceLoader instanceof ResourcePatternResolver)) {
|
||||
LOGGER.warn(
|
||||
"Resource Loader {} doensn't support getting multiple resources. Default properties mechanism will used",
|
||||
resourceLoader.getClass().getName());
|
||||
return super.refreshProperties(filename, propHolder);
|
||||
}
|
||||
|
||||
try {
|
||||
final Resource[] resources = ((ResourcePatternResolver) resourceLoader)
|
||||
.getResources(filename + PROPERTIES_SUFFIX);
|
||||
for (final Resource resource : resources) {
|
||||
final String sourcePath = resource.getURI().toString().replace(PROPERTIES_SUFFIX, "");
|
||||
final PropertiesHolder holder = super.refreshProperties(sourcePath, propHolder);
|
||||
properties.putAll(holder.getProperties());
|
||||
if (lastModified < resource.lastModified()) {
|
||||
lastModified = resource.lastModified();
|
||||
}
|
||||
}
|
||||
} catch (final IOException ignored) {
|
||||
LOGGER.warn("Resource with filname " + filename + " couldn't load", ignored);
|
||||
}
|
||||
return new PropertiesHolder(properties, lastModified);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResourceLoader(final ResourceLoader resourceLoader) {
|
||||
this.resourceLoader = resourceLoader;
|
||||
super.setResourceLoader(resourceLoader);
|
||||
}
|
||||
|
||||
}
|
||||
28
hawkbit-core/src/main/java/org/eclipse/hawkbit/api/HostnameResolver.java
Executable file
28
hawkbit-core/src/main/java/org/eclipse/hawkbit/api/HostnameResolver.java
Executable file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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.api;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Resolve to reach the server url.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface HostnameResolver {
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
URL resolveHostname();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* 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 java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash;
|
||||
|
||||
/**
|
||||
* ArtifactRepository service interface.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface ArtifactRepository {
|
||||
|
||||
/**
|
||||
* Stores an artifact into the repository.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant to store the artifact
|
||||
* @param content
|
||||
* the content to store
|
||||
* @param filename
|
||||
* the filename of the artifact
|
||||
* @param contentType
|
||||
* the content type of the artifact
|
||||
* @return the stored artifact
|
||||
* @throws ArtifactStoreException
|
||||
* in case storing of the artifact was not successful
|
||||
*/
|
||||
DbArtifact store(final InputStream content, final String filename, final String contentType);
|
||||
|
||||
/**
|
||||
* Stores an artifact into the repository.
|
||||
*
|
||||
* @param content
|
||||
* the content to store
|
||||
* @param filename
|
||||
* the filename of the artifact
|
||||
* @param contentType
|
||||
* the content type of the artifact
|
||||
* @param hash
|
||||
* the hashes of the artifact to do hash-checks after storing the
|
||||
* artifact, might be {@code null}
|
||||
* @return the stored artifact
|
||||
* @throws ArtifactStoreException
|
||||
* in case storing of the artifact was not successful
|
||||
* @throws HashNotMatchException
|
||||
* in case {@code hash} is provided and not matching to the
|
||||
* calculated hashes during storing
|
||||
*/
|
||||
DbArtifact store(final InputStream content, final String filename, final String contentType, DbArtifactHash hash);
|
||||
|
||||
/**
|
||||
* Deletes an artifact by its ID.
|
||||
*
|
||||
* @param artifactId
|
||||
* the ID of the artifact to delete
|
||||
*/
|
||||
void deleteById(final String artifactId);
|
||||
|
||||
/**
|
||||
* Deletes an artifact by its SHA1 hash.
|
||||
*
|
||||
* @param sha1Hash
|
||||
* the sha1-hash of the artifact to delete
|
||||
*/
|
||||
void deleteBySha1(final String sha1Hash);
|
||||
|
||||
/**
|
||||
* Retrieves a {@link DbArtifact} from the store by it's SHA1 hash.
|
||||
*
|
||||
* @param sha1Hash
|
||||
* the sha1-hash of the file to lookup.
|
||||
* @return The artifact file object or {@code null} if no file exists.
|
||||
*/
|
||||
DbArtifact getArtifactBySha1(String sha1);
|
||||
|
||||
/**
|
||||
* Retrieves a {@link DbArtifact} from the store by it's ID.
|
||||
*
|
||||
* @param id
|
||||
* the ID of the artifact to retrieve
|
||||
* @return The artifact file object or {@code null} if no file exists.
|
||||
*/
|
||||
DbArtifact getArtifactById(final String id);
|
||||
|
||||
/**
|
||||
* Retrieves a list of {@link GridFSDBFile} from the store by all SHA1
|
||||
* hashes.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant to retrieve the artifacts from, ignore case.
|
||||
* @param sha1Hashes
|
||||
* the sha1-hashes of the files to lookup.
|
||||
* @return list of artfiacts
|
||||
*/
|
||||
List<DbArtifact> getArtifactsBySha1(final List<String> sha1Hashes);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* {@link ArtifactStoreException} is thrown in case storing of an artifact was
|
||||
* not successful.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ArtifactStoreException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Constructs a ArtifactStoreException with message and cause.
|
||||
*
|
||||
* @param message
|
||||
* the message of the exception
|
||||
* @param cause
|
||||
* the cause of the exception
|
||||
*/
|
||||
public ArtifactStoreException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ArtifactStoreException with message.
|
||||
*
|
||||
* @param message
|
||||
* the message of the exception
|
||||
*/
|
||||
public ArtifactStoreException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Thrown when provided hashes and hashes caluclated during storing are not
|
||||
* matching.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class HashNotMatchException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static final String SHA1 = "SHA-1";
|
||||
public static final String MD5 = "MD5";
|
||||
|
||||
private final String hashFunction;
|
||||
|
||||
/**
|
||||
* Constructs a HashNotMatchException with message and cause.
|
||||
*
|
||||
* @param message
|
||||
* the message of the exception
|
||||
* @param cause
|
||||
* the cause of the exception
|
||||
* @param hashFunction
|
||||
* the hash function which caused this exception
|
||||
*/
|
||||
public HashNotMatchException(final String message, final Throwable cause, final String hashFunction) {
|
||||
super(message, cause);
|
||||
this.hashFunction = hashFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a HashNotMatchException with message.
|
||||
*
|
||||
* @param message
|
||||
* the message of the exception
|
||||
* @param hashFunction
|
||||
* the hash function which caused this exception
|
||||
*/
|
||||
public HashNotMatchException(final String message, final String hashFunction) {
|
||||
super(message);
|
||||
this.hashFunction = hashFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the hashFunction
|
||||
*/
|
||||
public String getHashFunction() {
|
||||
return hashFunction;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* 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.model;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Database representation of artifact.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class DbArtifact {
|
||||
|
||||
private String artifactId;
|
||||
|
||||
private DbArtifactHash hashes;
|
||||
|
||||
private Long size;
|
||||
|
||||
private String contentType;
|
||||
|
||||
private InputStream fileInputStream;
|
||||
|
||||
private OutputStream fileOutputStream;
|
||||
|
||||
public void setArtifactId(final String artifactId) {
|
||||
this.artifactId = artifactId;
|
||||
}
|
||||
|
||||
public String getArtifactId() {
|
||||
return artifactId;
|
||||
}
|
||||
|
||||
public DbArtifactHash getHashes() {
|
||||
return hashes;
|
||||
}
|
||||
|
||||
public void setHashes(final DbArtifactHash hashes) {
|
||||
this.hashes = hashes;
|
||||
}
|
||||
|
||||
public Long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setSize(final Long size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public void setContentType(final String contentType) {
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public void setFileInputStream(final InputStream fileInputStream) {
|
||||
this.fileInputStream = fileInputStream;
|
||||
}
|
||||
|
||||
public InputStream getFileInputStream() {
|
||||
return fileInputStream;
|
||||
}
|
||||
|
||||
public OutputStream getFileOutputStream() {
|
||||
return fileOutputStream;
|
||||
}
|
||||
|
||||
public void setFileOutputStream(final OutputStream fileOutputStream) {
|
||||
this.fileOutputStream = fileOutputStream;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* 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.model;
|
||||
|
||||
/**
|
||||
* Database representation of artifact hash.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class DbArtifactHash {
|
||||
|
||||
private String sha1;
|
||||
|
||||
private String md5;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param sha1
|
||||
* the sha1 hash
|
||||
* @param md5
|
||||
* the md5 hash
|
||||
*/
|
||||
public DbArtifactHash(final String sha1, final String md5) {
|
||||
super();
|
||||
this.sha1 = sha1;
|
||||
this.md5 = md5;
|
||||
}
|
||||
|
||||
public void setSha1(final String sha1) {
|
||||
this.sha1 = sha1;
|
||||
}
|
||||
|
||||
public void setMd5(final String md5) {
|
||||
this.md5 = md5;
|
||||
}
|
||||
|
||||
public String getSha1() {
|
||||
return sha1;
|
||||
}
|
||||
|
||||
public String getMd5() {
|
||||
return md5;
|
||||
}
|
||||
|
||||
}
|
||||
27
hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/CacheConstants.java
vendored
Executable file
27
hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/CacheConstants.java
vendored
Executable file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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.cache;
|
||||
|
||||
/**
|
||||
* Cache Constants.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class CacheConstants {
|
||||
|
||||
/**
|
||||
* Constant for download cache id.
|
||||
*/
|
||||
public static final String DOWNLOAD_ID_CACHE = "DowonloadIdCache";
|
||||
|
||||
private CacheConstants() {
|
||||
}
|
||||
|
||||
}
|
||||
44
hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/DownloadArtifactCache.java
vendored
Executable file
44
hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/DownloadArtifactCache.java
vendored
Executable file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* 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.cache;
|
||||
|
||||
/**
|
||||
* Cache Object for download a Artifact.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class DownloadArtifactCache {
|
||||
|
||||
private final DownloadType downloadType;
|
||||
private final String id;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param downloadType
|
||||
* the type for searching the artifact.
|
||||
* @param id
|
||||
* the searching id e.g. sha1, md5
|
||||
*/
|
||||
public DownloadArtifactCache(final DownloadType downloadType, final String id) {
|
||||
super();
|
||||
this.downloadType = downloadType;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public DownloadType getDownloadType() {
|
||||
return downloadType;
|
||||
}
|
||||
|
||||
}
|
||||
19
hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/DownloadType.java
vendored
Executable file
19
hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/DownloadType.java
vendored
Executable file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* 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.cache;
|
||||
|
||||
/**
|
||||
* The type of the id which is saved.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public enum DownloadType {
|
||||
BY_SHA1
|
||||
}
|
||||
40
hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenancyCacheManager.java
vendored
Executable file
40
hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenancyCacheManager.java
vendored
Executable file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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.cache;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface TenancyCacheManager extends CacheManager {
|
||||
|
||||
/**
|
||||
* A direct access for retrieving the cache without including the current
|
||||
* tenant key. This is necessary e.g. for retrieving caches not for the
|
||||
* current tenant.
|
||||
*
|
||||
* @param name
|
||||
* the name of the cache to retrieve directly
|
||||
* @return the cache associated with the name without tenancy separation
|
||||
*/
|
||||
Cache getDirectCache(String name);
|
||||
|
||||
/**
|
||||
* Evicts all caches for a given tenant. All caches under a certain tenant
|
||||
* gets evicted.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant to evict caches
|
||||
*/
|
||||
void evictCaches(final String tenant);
|
||||
|
||||
}
|
||||
102
hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenantAwareCacheManager.java
vendored
Executable file
102
hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenantAwareCacheManager.java
vendored
Executable file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* 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.cache;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
|
||||
/**
|
||||
* A {@link CacheManager} delegator which wraps the
|
||||
* {@link CacheManager#getCache(String)} and
|
||||
* {@link CacheManager#getCacheNames()} to include the
|
||||
* {@link TenantAware#getCurrentTenant()} when accessing a cache, so caches are
|
||||
* seperated.
|
||||
*
|
||||
* Additionally it also provide functionality to retrieve all caches overall
|
||||
* tenants at once, for monitoring and system access.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class TenantAwareCacheManager implements TenancyCacheManager {
|
||||
|
||||
private static final String TENANT_CACHE_DELIMITER = "|";
|
||||
|
||||
private final CacheManager delegate;
|
||||
|
||||
private final TenantAware tenantAware;
|
||||
|
||||
/**
|
||||
* @param delegate
|
||||
* the {@link CacheManager} to delegate to.
|
||||
* @param tenantAware
|
||||
* the tenant aware to retrieve the current tenant
|
||||
*/
|
||||
public TenantAwareCacheManager(final CacheManager delegate, final TenantAware tenantAware) {
|
||||
this.delegate = delegate;
|
||||
this.tenantAware = tenantAware;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cache getCache(final String name) {
|
||||
final String currentTenant = tenantAware.getCurrentTenant().toUpperCase();
|
||||
if (currentTenant.contains(TENANT_CACHE_DELIMITER)) {
|
||||
return null;
|
||||
}
|
||||
return delegate.getCache(currentTenant + TENANT_CACHE_DELIMITER + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getCacheNames() {
|
||||
final String currentTenant = tenantAware.getCurrentTenant().toUpperCase();
|
||||
if (currentTenant.contains(TENANT_CACHE_DELIMITER)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return getCacheNames(currentTenant);
|
||||
}
|
||||
|
||||
/**
|
||||
* A direct access for retrieving all cache names overall tenants.
|
||||
*
|
||||
* @return all cache names without tenant check
|
||||
*/
|
||||
public Collection<String> getDirectCacheNames() {
|
||||
return delegate.getCacheNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cache getDirectCache(final String name) {
|
||||
return delegate.getCache(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.cache.TenancyCacheManager#evictCaches(java.
|
||||
* lang. String)
|
||||
*/
|
||||
@Override
|
||||
public void evictCaches(final String tenant) {
|
||||
getCacheNames(tenant)
|
||||
.forEach(cachename -> delegate.getCache(tenant + TENANT_CACHE_DELIMITER + cachename).clear());
|
||||
}
|
||||
|
||||
private Collection<String> getCacheNames(final String tenant) {
|
||||
final String tenantWithDelimiter = tenant + TENANT_CACHE_DELIMITER;
|
||||
return delegate.getCacheNames().parallelStream().filter(cacheName -> cacheName.startsWith(tenantWithDelimiter))
|
||||
.map(cacheName -> cacheName.substring(tenantWithDelimiter.length())).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 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.eventbus;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.eventbus.DeadEvent;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
/**
|
||||
* Catches all dead events by means of events with no fitting subscriber on the
|
||||
* bus.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@EventSubscriber
|
||||
public class DeadEventListener {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DeadEventListener.class);
|
||||
|
||||
/**
|
||||
* Listens for dead vents and prints them into LOG.
|
||||
*
|
||||
* @param event
|
||||
* to print
|
||||
*/
|
||||
@Subscribe
|
||||
public void listen(final DeadEvent event) {
|
||||
LOG.info("DeadEvent on bus! {}", event.getEvent());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* 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.eventbus;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
/**
|
||||
* An {@link BeanPostProcessor} implementation which registers all beans as a
|
||||
* event bus subscriber if the classes are annotated with
|
||||
* {@link EventSubscriber} and have at least one method annotated with the
|
||||
* guava's {@link Subscribe} annoation.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
public class EventBusSubscriberProcessor implements BeanPostProcessor {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(EventBusSubscriberProcessor.class);
|
||||
|
||||
@Autowired
|
||||
private EventBus eventBus;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.beans.factory.config.BeanPostProcessor#
|
||||
* postProcessBeforeInitialization (java.lang.Object, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(final Object bean, final String beanName) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.beans.factory.config.BeanPostProcessor#
|
||||
* postProcessAfterInitialization( java.lang.Object, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(final Object bean, final String beanName) {
|
||||
final Class<? extends Object> beanClass = bean.getClass();
|
||||
final EventSubscriber eventSubscriber = beanClass.getAnnotation(EventSubscriber.class);
|
||||
if (eventSubscriber != null) {
|
||||
LOGGER.trace("Found bean {} with {} annotation ", bean.getClass().getName(),
|
||||
EventSubscriber.class.getSimpleName());
|
||||
final Method[] declaredMethods = beanClass.getDeclaredMethods();
|
||||
for (final Method method : declaredMethods) {
|
||||
final Subscribe subscriber = method.getAnnotation(Subscribe.class);
|
||||
if (subscriber != null) {
|
||||
LOGGER.trace("Found method {} for bean {} with {} annotation", method.getName(),
|
||||
bean.getClass().getName(), Subscribe.class.getSimpleName());
|
||||
eventBus.register(bean);
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (eventSubscriber != null) {
|
||||
LOGGER.debug("Found bean {} with {} annotation but without any method with necessary {} annotation",
|
||||
bean.getClass().getName(), EventSubscriber.class.getSimpleName(), Subscribe.class.getSimpleName());
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* package private setter for testing purposes.
|
||||
*
|
||||
* @param eventBus
|
||||
* the event bus
|
||||
*/
|
||||
void setEventBus(final EventBus eventBus) {
|
||||
this.eventBus = eventBus;
|
||||
}
|
||||
}
|
||||
42
hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/EventSubscriber.java
Executable file
42
hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/EventSubscriber.java
Executable file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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.eventbus;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Marks an class as an event subscriber to listen on event on the event bus
|
||||
* without explicit register this class to the event bus.
|
||||
*
|
||||
* <pre>
|
||||
* @EventSubscriber
|
||||
* public class MySubscriber {
|
||||
* @Subscribe
|
||||
* public void listen(MyEvent event) {
|
||||
* System.out.println("event received: " + event);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Target({ TYPE })
|
||||
@Retention(RUNTIME)
|
||||
@Service
|
||||
public @interface EventSubscriber {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* 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.eventbus.event;
|
||||
|
||||
/**
|
||||
* An abstract class of the {@link DistributedEvent} implementation which holds
|
||||
* all the necessary information of distributing events to other nodes.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractDistributedEvent implements DistributedEvent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final long revision;
|
||||
private String originNodeId;
|
||||
private String nodeId;
|
||||
private final String tenant;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param revision
|
||||
* the revision of this event
|
||||
* @param tenant
|
||||
* the tenant for this event
|
||||
*/
|
||||
protected AbstractDistributedEvent(final long revision, final String tenant) {
|
||||
this.revision = revision;
|
||||
this.tenant = tenant;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.eventbus.event.NodeAware#setOriginNodeId(java.
|
||||
* lang. String)
|
||||
*/
|
||||
@Override
|
||||
public void setOriginNodeId(final String originNodeId) {
|
||||
this.originNodeId = originNodeId;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.eventbus.event.NodeAware#setNodeId(java.lang.
|
||||
* String)
|
||||
*/
|
||||
@Override
|
||||
public void setNodeId(final String nodeId) {
|
||||
this.nodeId = nodeId;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.eventbus.event.NodeAware#getOriginNodeId()
|
||||
*/
|
||||
@Override
|
||||
public String getOriginNodeId() {
|
||||
return this.originNodeId;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.hawkbit.server.eventbus.event.NodeAware#getNodeId()
|
||||
*/
|
||||
@Override
|
||||
public String getNodeId() {
|
||||
return this.nodeId;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.hawkbit.server.eventbus.event.Event#getRevision()
|
||||
*/
|
||||
@Override
|
||||
public long getRevision() {
|
||||
return revision;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.hawkbit.server.eventbus.event.EntityEvent#getTenant()
|
||||
*/
|
||||
@Override
|
||||
public String getTenant() {
|
||||
return tenant;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* 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.eventbus.event;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* Event that gets sent when the assignment of a distribution set to a target
|
||||
* gets canceled.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class CancelTargetAssignmentEvent {
|
||||
|
||||
private final String controllerId;
|
||||
private final Long actionId;
|
||||
private final URI targetAdress;
|
||||
|
||||
/**
|
||||
* Creates a new {@link CancelTargetAssignmentEvent}.
|
||||
*
|
||||
* @param controllerId
|
||||
* the ID of the controller
|
||||
* @param actionId
|
||||
* the action id of the assignment
|
||||
* @param targetAdress
|
||||
* the targetAdress of the target
|
||||
*/
|
||||
public CancelTargetAssignmentEvent(final String controllerId, final Long actionId, final URI targetAdress) {
|
||||
this.controllerId = controllerId;
|
||||
this.actionId = actionId;
|
||||
this.targetAdress = targetAdress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the action id of the assignment
|
||||
*/
|
||||
public Long getActionId() {
|
||||
return actionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the controllerId of the Target which has been assigned to the
|
||||
* distribution set
|
||||
*/
|
||||
public String getControllerId() {
|
||||
return controllerId;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the targetr adress.
|
||||
*/
|
||||
public URI getTargetAdress() {
|
||||
return targetAdress;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TargetAssignDistributionSetEvent [targetAdress=" + targetAdress + ", controllerId=" + controllerId
|
||||
+ ", actionId=" + actionId + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* 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.eventbus.event;
|
||||
|
||||
/**
|
||||
* Events to be published to refresh data on UI.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public enum CustomEvents {
|
||||
|
||||
TARGETS_CREATED_EVENT,
|
||||
|
||||
DISTRIBUTION_CREATED_EVENT
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* 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.eventbus.event;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Marks an event to as an distributed event which will be distributed to other
|
||||
* nodes.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface DistributedEvent extends Event, NodeAware, Serializable {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 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.eventbus.event;
|
||||
|
||||
/**
|
||||
* Event that contains an updated download progress for a given Action.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class DownloadProgressEvent extends AbstractDistributedEvent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final Long statusId;
|
||||
private final int progressPercent;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant for this event
|
||||
* @param statusId
|
||||
* of {@link UpdateActionStatus}
|
||||
* @param progressPercent
|
||||
* number (1-100)
|
||||
*/
|
||||
public DownloadProgressEvent(final String tenant, final Long statusId, final int progressPercent) {
|
||||
// the revision of the DownloadProgressEvent is just equal the
|
||||
// progressPercentage due the
|
||||
// percentage is going from 0 to 100.
|
||||
super(statusId, tenant);
|
||||
this.statusId = statusId;
|
||||
this.progressPercent = progressPercent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the statusId
|
||||
*/
|
||||
public Long getStatusId() {
|
||||
return statusId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the progressPercent
|
||||
*/
|
||||
public int getProgressPercent() {
|
||||
return progressPercent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* 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.eventbus.event;
|
||||
|
||||
/**
|
||||
* An event interface which declares event types that an entity has been
|
||||
* changed. {@link EntityEvent}s should not implement {@link DistributedEvent}
|
||||
* due all {@link EntityEvent}s will be distributed to other nodes.
|
||||
*
|
||||
* Retrieving an {@link EntityEvent} on a different node the entity will be load
|
||||
* lazy.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface EntityEvent extends Event, NodeAware {
|
||||
|
||||
/**
|
||||
* A typesafe way to retrieve the entity from the event, which might be
|
||||
* loaded lazy in case the event has been distributed from another node.
|
||||
*
|
||||
* @param entityClass
|
||||
* the class of the entity to retrieve
|
||||
* @return the entity might be lazy loaded. Might be {@code null} in case
|
||||
* the entity e.g. is queried lazy on a different node and has been
|
||||
* already deleted from the database
|
||||
* @throws ClassCastException
|
||||
* in case a wrong entity class is given for this event
|
||||
*/
|
||||
<E> E getEntity(Class<E> entityClass);
|
||||
|
||||
/**
|
||||
* An unsafe way to retrieve the entity from this event which might be
|
||||
* loaded lazy in case the event has been distributed from another node.
|
||||
*
|
||||
* @return the entity might be lazy loaded. Might be {@code null} in case
|
||||
* the entity e.g. is queried lazy on a different node and has been
|
||||
* already deleted from the database
|
||||
*/
|
||||
Object getEntity();
|
||||
}
|
||||
32
hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/Event.java
Executable file
32
hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/Event.java
Executable file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 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.eventbus.event;
|
||||
|
||||
/**
|
||||
* An event declaration which holds an revision for each event so consumers have
|
||||
* the chance to know if they might already retrieved an newer event.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface Event {
|
||||
|
||||
/**
|
||||
* @return the revision of this event which should be increment or each new
|
||||
* event in case the event have a causalität. Might be {@code -1} in
|
||||
* case the events does not provide any revision.
|
||||
*/
|
||||
long getRevision();
|
||||
|
||||
/**
|
||||
* @return the tenant of the entity.
|
||||
*/
|
||||
String getTenant();
|
||||
}
|
||||
52
hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/NodeAware.java
Executable file
52
hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/NodeAware.java
Executable file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 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.eventbus.event;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by events which are distributed to other nodes
|
||||
* where it's necessary to know which node sent an event and which nodes
|
||||
* retrieved the event from which node. Using the EventDistributor the
|
||||
* implementation only needs to contain the necessary node IDs, setting and
|
||||
* retrieving the node IDs is transparent by the EventDistributor so the event
|
||||
* distributor does not hang in an endless loop of distributing the events which
|
||||
* self posted.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface NodeAware {
|
||||
|
||||
/**
|
||||
* @return the origin node ID in case the event has been forwarded to other
|
||||
* nodes or {@code null} if the event has not been forwarded to
|
||||
* other nodes
|
||||
*/
|
||||
String getOriginNodeId();
|
||||
|
||||
/**
|
||||
* @param originNodeId
|
||||
* the origin node ID where this event has been sent originally
|
||||
*/
|
||||
void setOriginNodeId(String originNodeId);
|
||||
|
||||
/**
|
||||
* @return the node ID which is processing this event locally, set by the
|
||||
* EventDistributor so he can determine if this event has been
|
||||
* received by another node and is processing on the current node.
|
||||
*/
|
||||
String getNodeId();
|
||||
|
||||
/**
|
||||
* @param nodeId
|
||||
* the ID of the node this event is processing.
|
||||
*/
|
||||
void setNodeId(String nodeId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* 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.eventbus.event;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class TargetDeletedEvent extends AbstractDistributedEvent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final long targetId;
|
||||
|
||||
/**
|
||||
* @param tenant
|
||||
* the tenant for this event
|
||||
* @param targetId
|
||||
* the ID of the target which has been deleted
|
||||
*/
|
||||
public TargetDeletedEvent(final String tenant, final long targetId) {
|
||||
super(-1, tenant);
|
||||
this.targetId = targetId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the targetId
|
||||
*/
|
||||
public long getTargetId() {
|
||||
return targetId;
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user