diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000..0825468a3
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,10 @@
+* text eol=lf
+# Denote all files that are truly binary and should not be modified.
+*.png binary
+*.jpg binary
+*.pdf binary
+*.PNG binary
+*.pptx binary
+*.eot binary
+*.ttf binary
+*.woff binary
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..dad7bec10
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,50 @@
+# Directories #
+/build/
+/*/build/
+/bin/
+/*/bin/
+/target/
+/*/target/
+/*/*/target/
+
+# OS Files #
+.DS_Store
+
+*.class
+
+# Package Files #
+*.jar
+*.war
+
+# Eclipse IDE
+
+*.pydevproject
+.project
+.metadata
+bin/**
+tmp/**
+tmp/**/*
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.classpath
+.settings/
+.loadpath
+
+# External tool builders
+.externalToolBuilders/
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# CDT-specific
+.cproject
+
+# PDT-specific
+.buildpath
+
+# Maven
+maven.properties
+/*/maven.properties
diff --git a/3rd-dependencies/compile.txt b/3rd-dependencies/compile.txt
old mode 100755
new mode 100644
diff --git a/3rd-dependencies/provided.txt b/3rd-dependencies/provided.txt
old mode 100755
new mode 100644
diff --git a/3rd-dependencies/test.txt b/3rd-dependencies/test.txt
old mode 100755
new mode 100644
diff --git a/CONTRUBUTING.md b/CONTRUBUTING.md
old mode 100755
new mode 100644
diff --git a/DDIA.md b/DDIA.md
old mode 100755
new mode 100644
diff --git a/DMFA.md b/DMFA.md
new file mode 100644
index 000000000..6653f3d9f
--- /dev/null
+++ b/DMFA.md
@@ -0,0 +1,127 @@
+# !!! DRAFT !!! #
+# Device Management Federation API #
+
+This document describes the **DMF API**. This API is based on AMQP [(AMQP-Specification)](ht1tp://www.amqp.org/sites/amqp.org/files/amqp.pdf "AMQP-Specification"). The SP Update server provides a message queue (default: "*dmf_receiver*") on the corresponding Rabbit MQ service, which accepts all incoming messages.
+
+Every Service, which wants to communicate, has to offer a own queue, to which the SP update server can send messages. The name of this queue is sent
+
+## Authentication ##
+???
+
+## Regular update process ##
+
+### Step 1: Creating a Thing on SP ###
+
+At the beginning every connecting service has to register its targets at the Sp update server. During the creating process the service has to send the name of the queue, which accepts messages, which are sent back from the Sp update server.
+
+The message which is sent by the connecting service to the SP update service has to fulfill the following format. The connecting service has to set the attributes in the header. The name of the tenent (*tenant*, an unique identifier of the thing/target (*thingId*) and an string which identifies the sending service (*sender*). Furthermore it has to set the *replyTo*-Property which defines the name of the queue, which receives messages sent by the SP Update Server. The body of the message is not analyzed and can be empty.
+
+**Header**
+
+
+### Step 2: Begin of update process ###
+Afterwards an distribution set can be assigned to the created thing. This can be done on the UI or with the REST API. To start the update process the SP update server sends a message over the registered queue back to the connecting service.
+
+Inside the message send from the Sp update service the header specifies the target which has to be updated. Therefor the *tenent* and the unique *thingId* are used. The body contains an identifier which defines the update process (*actionId*) and the information of the software modules. The *actionId* is important to send the progress of the update process to the server. The information about the software describes all modules which are included in the current update process, their identifier, their type, their version and the corresponding artifacts with the urls where the target can download the artifacts.
+
+**Header**
+
+
+### Step 3: Sending the state update process ###
+
+During the update progress the connected service can inform the sp update service about the progress and eventual warnings or errors. Therefore the *actionId* and the *softwareModuleId* are used to specify for which process and for which software module the progress update is for. Additionally in the Body there is a field *actionStatus*. This field is used to describe the type of the progress update and there are several allowed values:
+
+- **RETRIEVED**: general acknowledge message
+- **DOWNLOAD**: describes all messages related to the download prorgess
+- **RUNNING**:
+- **WARNING**: A smaller problem which influence the update process, but no need for stop it.
+- **ERROR**: A big issues which not allows continuing the update process.
+- **FINISHED**: Successfully finished the update process.
+- **CANCELED**: Response to a cancel request, when the process is canceled.
+- **CANCEL_REJECTED**: Response to a cancel request, when canceling is not possible.
+
+The update process is marked as running until the connected Server sends a **FINISHED**, an **ERROR** or a **CANCELED** message. Additionally the connected service can put some human readable information into the message, which describes the state of the action more detailed.
+
+**Header**
+
+{
+"actionId":115,
+"softwareModuleId":3,
+"actionStatus":"DOWNLOAD",
+"message":["The download has started"]
+}
+
+
+## Cancel process ##
+
+During the update process the SP update server has the chance to cancel an update. Therefore it sends the following message. This message includes the *tenant* and the corresponding *thingId* on theheader.
+
+**Header**
+
+
+Receiving this message the connected service has to decide if an update can be canceled or not. If it is the update has to be canceled and a **CANCELED** message has to be sent to the SP server. Otherwise a **CANCEL_REJECTED** message has to be sent.
+
+ 
\ No newline at end of file
diff --git a/LICENCE_HEADER_TEMPLATE.txt b/LICENCE_HEADER_TEMPLATE.txt
old mode 100755
new mode 100644
diff --git a/README.md b/README.md
old mode 100755
new mode 100644
index f6d1e03c7..52b7e848d
--- a/README.md
+++ b/README.md
@@ -33,4 +33,4 @@ mvn install
# 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)
+* [Device Management Federation API (AMQP)](DMFA.md)
diff --git a/circle.yml b/circle.yml
old mode 100755
new mode 100644
diff --git a/eclipse_codeformatter.xml b/eclipse_codeformatter.xml
old mode 100755
new mode 100644
diff --git a/examples/README.md b/examples/README.md
old mode 100755
new mode 100644
diff --git a/examples/hawkbit-device-simulator/.gitignore b/examples/hawkbit-device-simulator/.gitignore
old mode 100755
new mode 100644
diff --git a/examples/hawkbit-device-simulator/README.md b/examples/hawkbit-device-simulator/README.md
old mode 100755
new mode 100644
index caa86c3c0..b5db3d7ef
--- a/examples/hawkbit-device-simulator/README.md
+++ b/examples/hawkbit-device-simulator/README.md
@@ -11,8 +11,29 @@ Or:
run org.eclipse.hawkbit.simulator.DeviceSimulator
```
+## Notes
+
+The simulator has user authentication enabled by default. Default credentials:
+* username : admin
+* passwd : admin
+
+This can be configured/disabled by spring boot properties
+
## Usage
The device simulator exposes an REST-API which can be used to trigger device creation.
+
+Optional parameters:
+* name : name prefix simulated devices (default: "dmfSimulated"), followed by counter
+* amount : number of simulated devices (default: 20, capped at: 4000)
+* tenant : in a multi-tenenat ready hawkBit installation (default: "DEFAULT")
+
+
+Example: for 20 simulated devices (default)
```
-http://localhost:8083/start?amount=10
+http://localhost:8083/start
+```
+
+Example: for 10 simulated devices that start with the name prefix "activeSim":
+```
+http://localhost:8083/start?amount=10&name=activeSim
```
diff --git a/examples/hawkbit-device-simulator/pom.xml b/examples/hawkbit-device-simulator/pom.xml
old mode 100755
new mode 100644
index 4bc38985e..9e9fc86dc
--- a/examples/hawkbit-device-simulator/pom.xml
+++ b/examples/hawkbit-device-simulator/pom.xml
@@ -9,53 +9,81 @@
http://www.eclipse.org/legal/epl-v10.html
-->
+
+ 4.0.0
+
+ org.eclipse.hawkbit
+ 0.1.0-SNAPSHOT
+ hawkbit-examples-parent
+
-
- 4.0.0
-
- org.eclipse.hawkbit
- 0.1.0-SNAPSHOT
- hawkbit-examples-parent
-
+ hawkbit-device-simulator
+ hawkBit :: Device Simulator
+ Device Management Federation API based simulator
- hawkbit-device-simulator
- hawkBit :: Device Simulator
- Device Management Federation API based simulator
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ repackage
+
+
+ ${baseDir}
+ false
+ org.eclipse.hawkbit.simulator.DeviceSimulator
+ JAR
+
+
+
+
+
+
-
-
- org.eclipse.hawkbit
- hawkbit-dmf-api
- ${project.version}
-
-
- org.springframework.amqp
- spring-rabbit
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.boot
- spring-boot-starter
-
-
- org.springframework.boot
- spring-boot-starter-logging
-
-
-
-
- org.springframework.boot
- spring-boot-starter-log4j2
-
-
- org.springframework.boot
- spring-boot-autoconfigure
-
-
+
+
+ org.eclipse.hawkbit
+ hawkbit-dmf-api
+ ${project.version}
+
+
+ org.springframework.amqp
+ spring-rabbit
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.security
+ spring-security-web
+
+
+ org.springframework.security
+ spring-security-config
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-log4j2
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure
+
+
diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulator.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulator.java
old mode 100755
new mode 100644
index aa74665dc..37812a19d
--- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulator.java
+++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulator.java
@@ -20,6 +20,10 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DeviceSimulator {
+ private DeviceSimulator() {
+ // utility class
+ }
+
/**
* Start the Spring Boot Application.
*
diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationController.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationController.java
old mode 100755
new mode 100644
diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpConfiguration.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpConfiguration.java
old mode 100755
new mode 100644
index b99f24800..c4968c849
--- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpConfiguration.java
+++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpConfiguration.java
@@ -48,7 +48,7 @@ public class AmqpConfiguration {
/**
* Create jackson message converter bean.
- *
+ *
* @return the jackson message converter
*/
@Bean
@@ -60,7 +60,7 @@ public class AmqpConfiguration {
/**
* Create the receiver queue from sp. Receive messages from sp.
- *
+ *
* @return the queue
*/
@Bean
@@ -71,7 +71,7 @@ public class AmqpConfiguration {
/**
* Create the recevier exchange. Sp send messages to this exchange.
- *
+ *
* @return the exchange
*/
@Bean
@@ -83,7 +83,7 @@ public class AmqpConfiguration {
* Create the Binding
* {@link AmqpConfiguration#receiverConnectorQueueFromSp()} to
* {@link AmqpConfiguration#exchangeQueueToConnector()}.
- *
+ *
* @return the binding and create the queue and exchange
*/
@Bean
@@ -93,7 +93,7 @@ public class AmqpConfiguration {
/**
* Create dead letter queue.
- *
+ *
* @return the queue
*/
@Bean
@@ -103,7 +103,7 @@ public class AmqpConfiguration {
/**
* Create the dead letter fanout exchange.
- *
+ *
* @return the fanout exchange
*/
@Bean
@@ -113,7 +113,7 @@ public class AmqpConfiguration {
/**
* Create the Binding deadLetterQueue to exchangeDeadLetter.
- *
+ *
* @return the binding
*/
@Bean
@@ -123,7 +123,7 @@ public class AmqpConfiguration {
/**
* Returns the Listener factory.
- *
+ *
* @return the {@link SimpleMessageListenerContainer} that gets used receive
* AMQP messages
*/
@@ -136,7 +136,7 @@ public class AmqpConfiguration {
}
private Map getDeadLetterExchangeArgs() {
- final Map args = new HashMap();
+ final Map args = new HashMap<>();
args.put("x-dead-letter-exchange", amqpProperties.getDeadLetterExchange());
return args;
}
diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpProperties.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpProperties.java
old mode 100755
new mode 100644
diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/MessageHandlerCacheConstant.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/MessageHandlerCacheConstant.java
old mode 100755
new mode 100644
diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/MessageService.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/MessageService.java
old mode 100755
new mode 100644
diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/ReceiverService.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/ReceiverService.java
old mode 100755
new mode 100644
diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SenderService.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SenderService.java
old mode 100755
new mode 100644
index e8b82b6f0..6ed6ff0cb
--- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SenderService.java
+++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SenderService.java
@@ -11,6 +11,7 @@ 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.amqp.support.converter.AbstractJavaTypeMapper;
import org.springframework.beans.factory.annotation.Autowired;
/**
@@ -48,6 +49,7 @@ public abstract class SenderService extends MessageService {
if (message == null) {
return;
}
+ message.getMessageProperties().getHeaders().remove(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME);
rabbitTemplate.setExchange(adress);
rabbitTemplate.send(message);
}
diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SimulatedUpdate.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SimulatedUpdate.java
old mode 100755
new mode 100644
diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SpReceiverService.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SpReceiverService.java
old mode 100755
new mode 100644
index 3cf8891f0..5884a2645
--- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SpReceiverService.java
+++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SpReceiverService.java
@@ -131,11 +131,23 @@ public class SpReceiverService extends ReceiverService {
DownloadAndUpdateRequest.class);
final Long actionId = downloadAndUpdateRequest.getActionId();
+ try {
+ Thread.sleep(1_000);
+ } catch (final InterruptedException e) {
+ LOGGER.error("Sleep interrupted", e);
+ }
+
spSenderService.sendActionStatusMessage(tenant, ActionStatus.RUNNING,
"device Simulator retrieved update request. proceeding with simulation.", actionId);
final SimulatedUpdate update = new SimulatedUpdate(tenant, thingId, actionId);
+ try {
+ Thread.sleep(1_000);
+ } catch (final InterruptedException e) {
+ LOGGER.error("Sleep interrupted", e);
+ }
+
spSenderService.finishUpdateProcess(update, "Simulation complete!");
}
diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SpSenderService.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SpSenderService.java
old mode 100755
new mode 100644
index 1a66c2aa1..2358bf013
--- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SpSenderService.java
+++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SpSenderService.java
@@ -216,9 +216,7 @@ public class SpSenderService extends SenderService {
private Message createActionStatusMessage(final SimulatedUpdate update, final String messageDescription,
final ActionStatus status) {
- final Message sendMessage = createActionStatusMessage(update.getTenant(), status, messageDescription,
- update.getActionId());
- return sendMessage;
+ return createActionStatusMessage(update.getTenant(), status, messageDescription, update.getActionId());
}
}
diff --git a/examples/hawkbit-device-simulator/src/main/resources/application.properties b/examples/hawkbit-device-simulator/src/main/resources/application.properties
old mode 100755
new mode 100644
index eaac2999e..19dd2cb77
--- a/examples/hawkbit-device-simulator/src/main/resources/application.properties
+++ b/examples/hawkbit-device-simulator/src/main/resources/application.properties
@@ -12,7 +12,7 @@
# 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.receiverConnectorQueueFromSp=simulator_receiver
hawkbit.device.simulator.amqp.deadLetterQueue=simulator_deadletter
hawkbit.device.simulator.amqp.deadLetterExchange=simulator.deadletter
hawkbit.device.simulator.amqp.senderForSpExchange=simulator.replyTo
@@ -27,58 +27,6 @@ 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}
@@ -87,7 +35,7 @@ security.require-ssl=false
security.enable-csrf=false
security.basic.enabled=true
security.basic.realm=DeviceSimulator
-security.basic.path= /system/**
+security.basic.path= /**
security.basic.authorize-mode=ROLE
security.filter-order=0
security.headers.xss=false
diff --git a/examples/hawkbit-example-app/.gitignore b/examples/hawkbit-example-app/.gitignore
old mode 100755
new mode 100644
diff --git a/examples/hawkbit-example-app/README.md b/examples/hawkbit-example-app/README.md
old mode 100755
new mode 100644
diff --git a/examples/hawkbit-example-app/pom.xml b/examples/hawkbit-example-app/pom.xml
old mode 100755
new mode 100644
index ed4403cc5..cd238945a
--- a/examples/hawkbit-example-app/pom.xml
+++ b/examples/hawkbit-example-app/pom.xml
@@ -48,6 +48,11 @@
hawkbit-autoconfigure${project.version}
+
+ org.eclipse.hawkbit
+ hawkbit-rest-resource
+ ${project.version}
+ org.eclipse.hawkbithawkbit-dmf-amqp
@@ -92,10 +97,6 @@
org.springframework.securityspring-security-aspects
-
- io.springfox
- springfox-swagger2
- com.h2databaseh2
diff --git a/examples/hawkbit-example-app/src/main/java/org/eclipse/hawkbit/app/MyLoginUI.java b/examples/hawkbit-example-app/src/main/java/org/eclipse/hawkbit/app/MyLoginUI.java
old mode 100755
new mode 100644
diff --git a/examples/hawkbit-example-app/src/main/java/org/eclipse/hawkbit/app/MyUI.java b/examples/hawkbit-example-app/src/main/java/org/eclipse/hawkbit/app/MyUI.java
old mode 100755
new mode 100644
diff --git a/examples/hawkbit-example-app/src/main/java/org/eclipse/hawkbit/app/Start.java b/examples/hawkbit-example-app/src/main/java/org/eclipse/hawkbit/app/Start.java
old mode 100755
new mode 100644
index b87b53fef..a517dbb08
--- a/examples/hawkbit-example-app/src/main/java/org/eclipse/hawkbit/app/Start.java
+++ b/examples/hawkbit-example-app/src/main/java/org/eclipse/hawkbit/app/Start.java
@@ -10,25 +10,27 @@ package org.eclipse.hawkbit.app;
import org.eclipse.hawkbit.RepositoryApplicationConfiguration;
import org.eclipse.hawkbit.autoconfigure.security.EnableHawkbitManagedSecurityConfiguration;
+import org.eclipse.hawkbit.controller.EnableDirectDeviceApi;
+import org.eclipse.hawkbit.rest.resource.EnableRestResources;
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.
- *
- *
+ * A {@link SpringBootApplication} annotated class with a main method to start.
+ * The minimal configuration for the stand alone hawkBit server.
*
*/
@SpringBootApplication
@Import({ RepositoryApplicationConfiguration.class })
@EnableHawkbitManagedSecurityConfiguration
+@EnableRestResources
+@EnableDirectDeviceApi
public class Start {
/**
* Main method to start the spring-boot application.
- *
+ *
* @param args
* the VM arguments.
*/
diff --git a/examples/hawkbit-example-app/src/main/resources/application.properties b/examples/hawkbit-example-app/src/main/resources/application.properties
old mode 100755
new mode 100644
diff --git a/examples/hawkbit-mgmt-api-client/.gitignore b/examples/hawkbit-mgmt-api-client/.gitignore
new file mode 100644
index 000000000..0f630157f
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/.gitignore
@@ -0,0 +1,2 @@
+/target/
+/bin/
diff --git a/examples/hawkbit-mgmt-api-client/README.md b/examples/hawkbit-mgmt-api-client/README.md
new file mode 100644
index 000000000..7eb32f9e6
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/README.md
@@ -0,0 +1,3 @@
+Example client that shows how to efficiently use the hawkBit management API.
+
+Powered by [Feign](https://github.com/Netflix/feign).
\ No newline at end of file
diff --git a/examples/hawkbit-mgmt-api-client/pom.xml b/examples/hawkbit-mgmt-api-client/pom.xml
new file mode 100644
index 000000000..cd0977cf5
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/pom.xml
@@ -0,0 +1,70 @@
+
+
+ 4.0.0
+
+ org.eclipse.hawkbit
+ hawkbit-examples-parent
+ 0.1.0-SNAPSHOT
+
+ hawkbit-mgmt-api-client
+ hawkBit Management API example client
+
+
+
+
+ org.eclipse.hawkbit
+ hawkbit-rest-api
+ ${project.version}
+
+
+ com.netflix.feign
+ feign-jackson
+ 8.12.1
+
+
+ com.netflix.feign
+ feign-core
+ 8.12.1
+
+
+
+
+ org.eclipse.hawkbit
+ hawkbit-example-app
+ ${project.version}
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ ru.yandex.qatools.allure
+ allure-junit-adaptor
+ test
+
+
+ org.easytesting
+ fest-assert-core
+ test
+
+
+ org.easytesting
+ fest-assert
+ test
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/DistributionSetResource.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/DistributionSetResource.java
new file mode 100644
index 000000000..747432cd0
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/DistributionSetResource.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.mgmt.api.client;
+
+import java.util.List;
+
+import org.eclipse.hawkbit.rest.resource.RestConstants;
+import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetRequestBodyPost;
+import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetsRest;
+
+import feign.Headers;
+import feign.RequestLine;
+
+/**
+ * Client binding for the Distribution resource of the management API.
+ */
+public interface DistributionSetResource {
+
+ /**
+ * Creates a list of distrbution sets.
+ *
+ * @param sets
+ * the request body java bean containing the necessary attributes
+ * for creating a distribution set.
+ * @return the list of targets which have been created
+ */
+ @RequestLine("POST " + RestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING)
+ @Headers("Content-Type: application/json")
+ DistributionSetsRest createDistributionSets(final List sets);
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/DistrubutionSetTagResource.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/DistrubutionSetTagResource.java
new file mode 100644
index 000000000..fe7a147a8
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/DistrubutionSetTagResource.java
@@ -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.mgmt.api.client;
+
+import java.util.List;
+
+import org.eclipse.hawkbit.rest.resource.RestConstants;
+import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetsRest;
+import org.eclipse.hawkbit.rest.resource.model.tag.AssignedDistributionSetRequestBody;
+import org.eclipse.hawkbit.rest.resource.model.tag.DistributionSetTagAssigmentResultRest;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagRequestBodyPut;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagRest;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagsRest;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetsRest;
+
+import feign.Headers;
+import feign.Param;
+import feign.RequestLine;
+
+/**
+ * Client binding for the DistributionSetTag resource of the management API.
+ */
+public interface DistrubutionSetTagResource {
+
+ /**
+ * Retrieves a single distributionset tag based on the given ID.
+ *
+ * @param dsTagId
+ * the ID of the distributionset tag to retrieve
+ * @return a deserialized java bean containing the attributes of the
+ * returned distributionset tag
+ */
+ @RequestLine("GET " + RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING + "/{dsTagId}")
+ TagRest getDistributionSetTag(@Param("dsTagId") Long dsTagId);
+
+ /**
+ * Creates a list of distributionset tags.
+ *
+ * @param tags
+ * the tags to be created
+ * @return the created tag list
+ */
+ @RequestLine("POST " + RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING)
+ @Headers("Content-Type: application/json")
+ TagsRest createDistributionSetTags(List tags);
+
+ /**
+ * Update attributes of a distributionset tag.
+ *
+ * @param dsTagId
+ * the distributionset tag id to be updated
+ * @param tag
+ * the request body
+ * @return the updated distributionset tag
+ */
+ @RequestLine("PUT " + RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING + "/{dsTagId}")
+ @Headers("Content-Type: application/json")
+ TagRest updateDistributionSetTag(@Param("dsTagId") Long dsTagId, TagRequestBodyPut tag);
+
+ /**
+ * Deletes given distributionset tag on given ID.
+ *
+ * @param dsTagId
+ * to be deleted
+ */
+ @RequestLine("DELETE " + RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING + "/{dsTagId}")
+ void deleteDistributionSetTag(@Param("dsTagId") final Long dsTagId);
+
+ /**
+ * Retrieves a all assigned targets on the given distributionset tag id.
+ *
+ * @param dsTagId
+ * the ID of the distributionset tag to retrieve
+ * @return a list of targets
+ */
+ @RequestLine("GET " + RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING
+ + RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING)
+ DistributionSetsRest getAssignedDistributionSets(@Param("dsTagId") final Long dsTagId);
+
+ /**
+ * Toggle the tag assignment all assigned targets will be unassigned and all
+ * unassigned targets will be assigned.
+ *
+ * @param dsTagId
+ * the ID of the distributionset tag to toggle
+ * @param assignedTargetRequestBodies
+ * a list of controller ids
+ * @return a list of assigned and unassigned targets
+ */
+ @RequestLine("POST " + RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING
+ + RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING + "/toggleTagAssignment")
+ @Headers("Content-Type: application/json")
+ DistributionSetTagAssigmentResultRest toggleTagAssignment(@Param("dsTagId") final Long dsTagId,
+ final List assignedTargetRequestBodies);
+
+ /**
+ * Assign targets to a given distributionset tag id.
+ *
+ * @param dsTagId
+ * the ID of the distributionset tag to add the targets
+ * @param assignedTargetRequestBodies
+ * a list of controller ids
+ * @return a list of assigned targets
+ */
+ @RequestLine("POST " + RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING
+ + RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING)
+ @Headers("Content-Type: application/json")
+ TargetsRest assignDistributionSets(@Param("dsTagId") final Long dsTagId,
+ final List assignedTargetRequestBodies);
+
+ /**
+ * Unassign targets to a given distributionset tag id.
+ *
+ * @param dsTagId
+ * the ID of the distributionset tag to add the targets
+ */
+ @RequestLine("DELETE " + RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING
+ + RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING)
+ void unassignDistributionSets(@Param("dsTagId") final Long dsTagId);
+
+ /**
+ * Unassign one target to a given distributionset tag id.
+ *
+ * @param dsTagId
+ * the ID of the distributionset tag to add the targets param
+ * @param dsId
+ * the distributionset id
+ */
+ @RequestLine("DELETE " + RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING
+ + RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING + "/{dsId}")
+ void unassignDistributionSet(@Param("dsTagId") final Long dsTagId, @Param("dsId") final Long dsId);
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/TargetResource.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/TargetResource.java
new file mode 100644
index 000000000..66c147426
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/TargetResource.java
@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.mgmt.api.client;
+
+import java.util.List;
+
+import org.eclipse.hawkbit.rest.resource.model.target.TargetPagedList;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetRequestBody;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetRest;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetsRest;
+
+import feign.Headers;
+import feign.Param;
+import feign.RequestLine;
+
+/**
+ * Client binding for the Target resource of the management API.
+ */
+public interface TargetResource {
+
+ /**
+ * Retrieves a single target based on the given ID.
+ *
+ * @param targetId
+ * the ID of the target to retrieve
+ * @return a deserialized java bean containing the attributes of the
+ * returned target
+ */
+ @RequestLine("GET /rest/v1/targets/{targetId}")
+ TargetRest getTarget(@Param("targetId") final String targetId);
+
+ /**
+ * Paged query of targets resource.
+ *
+ * @param pagingOffsetParam
+ * of the paged query
+ * @param pagingLimitParam
+ * of the paged query
+ * @return paged list of target entries
+ */
+ @RequestLine("GET /rest/v1/targets?offset={pagingOffsetParam}&limit={pagingLimitParam}")
+ TargetPagedList getTargets(@Param("pagingOffsetParam") int pagingOffsetParam,
+ @Param("pagingLimitParam") int pagingLimitParam);
+
+ /**
+ * Paged query of targets resource with default offset and limit.
+ *
+ * @return paged list of target entries
+ */
+ @RequestLine("GET /rest/v1/targets")
+ TargetPagedList getTargets();
+
+ /**
+ * Deletes given target based on given ID.
+ *
+ * @param targetId
+ * to be deleted
+ */
+ @RequestLine("DELETE /rest/v1/targets/{targetId}")
+ void deleteTarget(@Param("targetId") final String targetId);
+
+ /**
+ * Creates a list of targets.
+ *
+ * @param targets
+ * the request body java bean containing the necessary attributes
+ * for creating a target.
+ * @return the list of targets which have been created
+ */
+ @RequestLine("POST /rest/v1/targets/")
+ @Headers("Content-Type: application/json")
+ TargetsRest createTargets(List targets);
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/TargetTagResource.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/TargetTagResource.java
new file mode 100644
index 000000000..bd74e52d7
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/TargetTagResource.java
@@ -0,0 +1,137 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.mgmt.api.client;
+
+import java.util.List;
+
+import org.eclipse.hawkbit.rest.resource.RestConstants;
+import org.eclipse.hawkbit.rest.resource.model.tag.AssignedTargetRequestBody;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagRequestBodyPut;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagRest;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagsRest;
+import org.eclipse.hawkbit.rest.resource.model.tag.TargetTagAssigmentResultRest;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetsRest;
+
+import feign.Headers;
+import feign.Param;
+import feign.RequestLine;
+
+/**
+ * Client binding for the Target resource of the management API.
+ */
+public interface TargetTagResource {
+
+ /**
+ * Retrieves a single target tag based on the given ID.
+ *
+ * @param targetTagId
+ * the ID of the target tag to retrieve
+ * @return a deserialized java bean containing the attributes of the
+ * returned target tag
+ */
+ @RequestLine("GET " + RestConstants.TARGET_TAG_V1_REQUEST_MAPPING + "/{targetTagId}")
+ TagRest getTargetTag(@Param("targetTagId") Long targetTagId);
+
+ /**
+ * Creates a list of target tags.
+ *
+ * @param tags
+ * the tags to be created
+ * @return the created tag list
+ */
+ @RequestLine("POST " + RestConstants.TARGET_TAG_V1_REQUEST_MAPPING)
+ @Headers("Content-Type: application/json")
+ TagsRest createTargetTag(List tags);
+
+ /**
+ * Update attributes of a target tag.
+ *
+ * @param targetTagId
+ * the target tag id to be updated
+ * @param tag
+ * the request body
+ * @return the updated target tag
+ */
+ @RequestLine("PUT " + RestConstants.TARGET_TAG_V1_REQUEST_MAPPING + "/{targetTagId}")
+ @Headers("Content-Type: application/json")
+ TagRest updateTagretTag(@Param("targetTagId") Long targetTagId, TagRequestBodyPut tag);
+
+ /**
+ * Deletes given target tag on given ID.
+ *
+ * @param targetTagId
+ * to be deleted
+ */
+ @RequestLine("DELETE " + RestConstants.TARGET_TAG_V1_REQUEST_MAPPING + "/{targetTagId}")
+ void deleteTargetTag(@Param("targetTagId") final Long targetTagId);
+
+ /**
+ * Retrieves a all assigned targets on the given target tag id.
+ *
+ * @param targetTagId
+ * the ID of the target tag to retrieve
+ * @return a list of targets
+ */
+ @RequestLine("GET " + RestConstants.TARGET_TAG_V1_REQUEST_MAPPING
+ + RestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING)
+ TargetsRest getAssignedTargets(@Param("targetTagId") final Long targetTagId);
+
+ /**
+ * Toggle the tag assignment all assigned targets will be unassigned and all
+ * unassigned targets will be assigned.
+ *
+ * @param targetTagId
+ * the ID of the target tag to toggle
+ * @param assignedTargetRequestBodies
+ * a list of controller ids
+ * @return a list of assigned and unassigned targets
+ */
+ @RequestLine("POST " + RestConstants.TARGET_TAG_V1_REQUEST_MAPPING
+ + RestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING + "/toggleTagAssignment")
+ @Headers("Content-Type: application/json")
+ TargetTagAssigmentResultRest toggleTagAssignment(@Param("targetTagId") final Long targetTagId,
+ final List assignedTargetRequestBodies);
+
+ /**
+ * Assign targets to a given target tag id.
+ *
+ * @param targetTagId
+ * the ID of the target tag to add the targets
+ * @param assignedTargetRequestBodies
+ * a list of controller ids
+ * @return a list of assigned targets
+ */
+ @RequestLine("POST " + RestConstants.TARGET_TAG_V1_REQUEST_MAPPING
+ + RestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING)
+ @Headers("Content-Type: application/json")
+ TargetsRest assignTargets(@Param("targetTagId") final Long targetTagId,
+ final List assignedTargetRequestBodies);
+
+ /**
+ * Unassign targets to a given target tag id.
+ *
+ * @param targetTagId
+ * the ID of the target tag to add the targets
+ */
+ @RequestLine("DELETE " + RestConstants.TARGET_TAG_V1_REQUEST_MAPPING
+ + RestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING)
+ void unassignTargets(@Param("targetTagId") final Long targetTagId);
+
+ /**
+ * Unassign one target to a given target tag id.
+ *
+ * @param targetTagId
+ * the ID of the target tag to add the targets param
+ * @param controllerId
+ * the controller id
+ */
+ @RequestLine("DELETE " + RestConstants.TARGET_TAG_V1_REQUEST_MAPPING
+ + RestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING + "/{controllerId}")
+ void unassignTarget(@Param("targetTagId") final Long targetTagId, @Param("controllerId") final String controllerId);
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/test/java/org/eclipse/hawkbit/mgmt/api/client/DistributionSetTagTest.java b/examples/hawkbit-mgmt-api-client/src/test/java/org/eclipse/hawkbit/mgmt/api/client/DistributionSetTagTest.java
new file mode 100644
index 000000000..17384c211
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/test/java/org/eclipse/hawkbit/mgmt/api/client/DistributionSetTagTest.java
@@ -0,0 +1,186 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.mgmt.api.client;
+
+import static org.fest.assertions.api.Assertions.assertThat;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.hawkbit.app.Start;
+import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetRequestBodyPost;
+import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetRest;
+import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetsRest;
+import org.eclipse.hawkbit.rest.resource.model.tag.AssignedDistributionSetRequestBody;
+import org.eclipse.hawkbit.rest.resource.model.tag.DistributionSetTagAssigmentResultRest;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagRequestBodyPut;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagRest;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagsRest;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.springframework.boot.SpringApplication;
+import org.springframework.context.annotation.Description;
+
+import ru.yandex.qatools.allure.annotations.Features;
+import ru.yandex.qatools.allure.annotations.Stories;
+import feign.Feign;
+import feign.Logger;
+import feign.auth.BasicAuthRequestInterceptor;
+import feign.jackson.JacksonDecoder;
+import feign.jackson.JacksonEncoder;
+
+@Features("Example Tests - Management RESTful API Client")
+@Stories("DistrubutionSet Tag Resource")
+public class DistributionSetTagTest {
+
+ private DistrubutionSetTagResource distrubutionSetTagResource;
+
+ private static List assignedTargetRequestBodies;
+
+ @BeforeClass
+ public static void startupServer() {
+ SpringApplication.run(Start.class, new String[0]);
+ createTargetsAssignment();
+ assignedTargetRequestBodies.add(new AssignedDistributionSetRequestBody().setDistributionSetId(100L));
+ }
+
+ @Before
+ public void setup() {
+ this.distrubutionSetTagResource = createDistrubutionSetTagResource();
+ }
+
+ // disabled as this runs not on CI environments.
+ @Test
+ @Description("Simple request of distrubutionset tag by ID")
+ @Ignore
+ public void getDistributionSetTag() {
+ final TagsRest result = createDistributionSetTags(2);
+
+ assertThat(distrubutionSetTagResource.getDistributionSetTag(result.get(0).getTagId()).getName()).isEqualTo(
+ "Tag0");
+
+ deleteDistributionSets(result);
+ }
+
+ // disabled as this runs not on CI environments.
+ @Test
+ @Description("Simple update of a distrubutionset tag")
+ @Ignore
+ public void updateDistributionSetTag() {
+ final TagsRest created = createDistributionSetTags(10);
+
+ distrubutionSetTagResource.updateDistributionSetTag(created.get(0).getTagId(), new TagRequestBodyPut()
+ .setDescription("Test").setName("Test").setColour("Green"));
+
+ final TagRest targetTag = distrubutionSetTagResource.getDistributionSetTag(created.get(0).getTagId());
+ assertThat(targetTag.getName()).isEqualTo("Test");
+ assertThat(targetTag.getDescription()).isEqualTo("Test");
+ assertThat(targetTag.getColour()).isEqualTo("Green");
+
+ deleteDistributionSets(created);
+ }
+
+ // disabled as this runs not on CI environments.
+ @Test
+ @Description("Simple request of all assigned distrubutionsets by a distrubutionset tag.")
+ @Ignore
+ public void getDistributionSetByTagId() {
+ final TagsRest created = createDistributionSetTags(10);
+ distrubutionSetTagResource.assignDistributionSets(created.get(2).getTagId(), assignedTargetRequestBodies);
+
+ final DistributionSetsRest distributionSetsRest = distrubutionSetTagResource
+ .getAssignedDistributionSets(created.get(2).getTagId());
+ assertThat(distributionSetsRest).hasSize(5);
+
+ distrubutionSetTagResource.unassignDistributionSets(created.get(2).getTagId());
+ deleteDistributionSets(created);
+ }
+
+ @Test
+ @Description("Toggle request to unassigned all assigned distrubutionset and assign all unassigned distrubutionset.")
+ @Ignore
+ public void toggleTagAssignment() {
+ final TagsRest created = createDistributionSetTags(10);
+ final Long id = created.get(2).getTagId();
+
+ distrubutionSetTagResource.assignDistributionSets(id, assignedTargetRequestBodies);
+ distrubutionSetTagResource.unassignDistributionSet(id, assignedTargetRequestBodies.get(0)
+ .getDistributionSetId());
+
+ DistributionSetTagAssigmentResultRest assigmentResultRest = distrubutionSetTagResource.toggleTagAssignment(id,
+ assignedTargetRequestBodies);
+
+ final TagRest targetTag = distrubutionSetTagResource.getDistributionSetTag(created.get(2).getTagId());
+ assertThat(assigmentResultRest.getAssignedDistributionSets()).hasSize(1);
+ assertThat(assigmentResultRest.getUnassignedDistributionSets()).hasSize(0);
+
+ assigmentResultRest = distrubutionSetTagResource.toggleTagAssignment(id, assignedTargetRequestBodies);
+ assertThat(assigmentResultRest.getAssignedDistributionSets()).hasSize(0);
+ assertThat(assigmentResultRest.getUnassignedDistributionSets()).hasSize(5);
+
+ distrubutionSetTagResource.unassignDistributionSets(targetTag.getTagId());
+ deleteDistributionSets(created);
+ }
+
+ private void deleteDistributionSets(final List tags) {
+ for (final TagRest tag : tags) {
+ distrubutionSetTagResource.deleteDistributionSetTag(tag.getTagId());
+ }
+ }
+
+ private TagsRest createDistributionSetTags(final int number) {
+
+ final List tags = new ArrayList<>();
+ for (int i = 0; i < number; i++) {
+ tags.add(new TagRequestBodyPut().setDescription("Tag " + i).setName("Tag" + i).setColour("Red"));
+ }
+
+ final TagsRest result = distrubutionSetTagResource.createDistributionSetTags(tags);
+
+ assertThat(result).hasSize(number);
+ return result;
+ }
+
+ private DistrubutionSetTagResource createDistrubutionSetTagResource() {
+ final DistrubutionSetTagResource distrubutionSetTagResource = Feign.builder().logger(new Logger.ErrorLogger())
+ .logLevel(Logger.Level.BASIC).decoder(new JacksonDecoder()).encoder(new JacksonEncoder())
+ .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin"))
+ .target(DistrubutionSetTagResource.class, "http://localhost:8080");
+ return distrubutionSetTagResource;
+ }
+
+ private static void createTargetsAssignment() {
+
+ final List sets = new ArrayList<>();
+ assignedTargetRequestBodies = new ArrayList<>();
+ for (int i = 0; i < 5; i++) {
+ final DistributionSetRequestBodyPost bodyPost = (DistributionSetRequestBodyPost) new DistributionSetRequestBodyPost()
+ .setName("Ds" + i).setDescription("Ds" + i).setVersion("" + i);
+ sets.add(bodyPost);
+ }
+
+ final DistributionSetsRest result = createDistributionSetResource().createDistributionSets(sets);
+ for (final DistributionSetRest rest : result) {
+ assignedTargetRequestBodies.add(new AssignedDistributionSetRequestBody().setDistributionSetId(rest
+ .getDsId()));
+ }
+
+ }
+
+ private static DistributionSetResource createDistributionSetResource() {
+ final DistributionSetResource distributionSetResource = Feign.builder().logger(new Logger.ErrorLogger())
+ .logLevel(Logger.Level.BASIC).decoder(new JacksonDecoder()).encoder(new JacksonEncoder())
+ .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin"))
+ .target(DistributionSetResource.class, "http://localhost:8080");
+ return distributionSetResource;
+ }
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/test/java/org/eclipse/hawkbit/mgmt/api/client/TargetTagTest.java b/examples/hawkbit-mgmt-api-client/src/test/java/org/eclipse/hawkbit/mgmt/api/client/TargetTagTest.java
new file mode 100644
index 000000000..10f18b704
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/test/java/org/eclipse/hawkbit/mgmt/api/client/TargetTagTest.java
@@ -0,0 +1,182 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.mgmt.api.client;
+
+import static org.fest.assertions.api.Assertions.assertThat;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.hawkbit.app.Start;
+import org.eclipse.hawkbit.rest.resource.model.tag.AssignedTargetRequestBody;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagRequestBodyPut;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagRest;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagsRest;
+import org.eclipse.hawkbit.rest.resource.model.tag.TargetTagAssigmentResultRest;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetRequestBody;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetRest;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetsRest;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.springframework.boot.SpringApplication;
+import org.springframework.context.annotation.Description;
+
+import ru.yandex.qatools.allure.annotations.Features;
+import ru.yandex.qatools.allure.annotations.Stories;
+import feign.Feign;
+import feign.Logger;
+import feign.auth.BasicAuthRequestInterceptor;
+import feign.jackson.JacksonDecoder;
+import feign.jackson.JacksonEncoder;
+
+@Features("Example Tests - Management RESTful API Client")
+@Stories("Target Tag Resource")
+public class TargetTagTest {
+
+ private TargetTagResource targetTagResource;
+
+ private static List assignedTargetRequestBodies;
+
+ @BeforeClass
+ public static void startupServer() {
+ SpringApplication.run(Start.class, new String[0]);
+ createTargetsAssignment();
+ assignedTargetRequestBodies.add(new AssignedTargetRequestBody().setControllerId("NotExist"));
+ }
+
+ @Before
+ public void setup() {
+ this.targetTagResource = createTargetTagResource();
+ }
+
+ // disabled as this runs not on CI environments.
+ @Test
+ @Description("Simple request of target tag by ID")
+ @Ignore
+ public void getTargetTag() {
+ final TagsRest result = createTargetTags(2);
+
+ assertThat(targetTagResource.getTargetTag(result.get(0).getTagId()).getName()).isEqualTo("Tag0");
+
+ deleteTargets(result);
+ }
+
+ // disabled as this runs not on CI environments.
+ @Test
+ @Description("Simple update of a target tag")
+ @Ignore
+ public void updateTargetTag() {
+ final TagsRest created = createTargetTags(10);
+
+ targetTagResource.updateTagretTag(created.get(0).getTagId(), new TagRequestBodyPut().setDescription("Test")
+ .setName("Test").setColour("Green"));
+
+ final TagRest targetTag = targetTagResource.getTargetTag(created.get(0).getTagId());
+ assertThat(targetTag.getName()).isEqualTo("Test");
+ assertThat(targetTag.getDescription()).isEqualTo("Test");
+ assertThat(targetTag.getColour()).isEqualTo("Green");
+
+ deleteTargets(created);
+ }
+
+ // disabled as this runs not on CI environments.
+ @Test
+ @Description("Simple request of all assigned targets by a target tag.")
+ @Ignore
+ public void getTargetsByTargetTagId() {
+ final TagsRest created = createTargetTags(10);
+ final Long tagId = created.get(2).getTagId();
+ targetTagResource.assignTargets(tagId, assignedTargetRequestBodies);
+
+ final TagRest targetTag = targetTagResource.getTargetTag(tagId);
+ assertThat(targetTagResource.getAssignedTargets(tagId)).hasSize(5);
+
+ targetTagResource.unassignTargets(targetTag.getTagId());
+ deleteTargets(created);
+ }
+
+ @Test
+ @Description("Toggle request to unassigned all assigned targets and assign all unassigned targets.")
+ @Ignore
+ public void toggleTagAssignment() {
+ final TagsRest created = createTargetTags(10);
+ final Long id = created.get(2).getTagId();
+
+ targetTagResource.assignTargets(id, assignedTargetRequestBodies);
+ targetTagResource.unassignTarget(id, assignedTargetRequestBodies.get(0).getControllerId());
+
+ TargetTagAssigmentResultRest assigmentResultRest = targetTagResource.toggleTagAssignment(id,
+ assignedTargetRequestBodies);
+
+ final TagRest targetTag = targetTagResource.getTargetTag(created.get(2).getTagId());
+ assertThat(assigmentResultRest.getAssignedTargets()).hasSize(1);
+ assertThat(assigmentResultRest.getUnassignedTargets()).hasSize(0);
+
+ assigmentResultRest = targetTagResource.toggleTagAssignment(id, assignedTargetRequestBodies);
+ assertThat(assigmentResultRest.getAssignedTargets()).hasSize(0);
+ assertThat(assigmentResultRest.getUnassignedTargets()).hasSize(5);
+
+ targetTagResource.unassignTargets(targetTag.getTagId());
+ deleteTargets(created);
+ }
+
+ private void deleteTargets(final List tags) {
+ for (final TagRest tag : tags) {
+ targetTagResource.deleteTargetTag(tag.getTagId());
+ }
+ }
+
+ private TagsRest createTargetTags(final int number) {
+
+ final List tags = new ArrayList<>();
+ for (int i = 0; i < number; i++) {
+ tags.add(new TagRequestBodyPut().setDescription("Tag " + i).setName("Tag" + i).setColour("Red"));
+ }
+
+ final TagsRest result = targetTagResource.createTargetTag(tags);
+
+ assertThat(result).hasSize(number);
+ return result;
+ }
+
+ private TargetTagResource createTargetTagResource() {
+ final TargetTagResource targetResource = Feign.builder().logger(new Logger.ErrorLogger())
+ .logLevel(Logger.Level.BASIC).decoder(new JacksonDecoder()).encoder(new JacksonEncoder())
+ .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin"))
+ .target(TargetTagResource.class, "http://localhost:8080");
+ return targetResource;
+ }
+
+ private static void createTargetsAssignment() {
+
+ final List targets = new ArrayList<>();
+ assignedTargetRequestBodies = new ArrayList<>();
+ for (int i = 0; i < 5; i++) {
+
+ targets.add(new TargetRequestBody().setControllerId("test" + i).setName("testDevice"));
+ }
+
+ final TargetsRest result = createTargetResource().createTargets(targets);
+ for (final TargetRest rest : result) {
+ assignedTargetRequestBodies.add(new AssignedTargetRequestBody().setControllerId(rest.getControllerId()));
+ }
+
+ }
+
+ private static TargetResource createTargetResource() {
+ final TargetResource targetResource = Feign.builder().logger(new Logger.ErrorLogger())
+ .logLevel(Logger.Level.BASIC).decoder(new JacksonDecoder()).encoder(new JacksonEncoder())
+ .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin"))
+ .target(TargetResource.class, "http://localhost:8080");
+ return targetResource;
+ }
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/test/java/org/eclipse/hawkbit/mgmt/api/client/TargetTest.java b/examples/hawkbit-mgmt-api-client/src/test/java/org/eclipse/hawkbit/mgmt/api/client/TargetTest.java
new file mode 100644
index 000000000..745b119f6
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/test/java/org/eclipse/hawkbit/mgmt/api/client/TargetTest.java
@@ -0,0 +1,119 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.mgmt.api.client;
+
+import static org.fest.assertions.api.Assertions.assertThat;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.hawkbit.app.Start;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetPagedList;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetRequestBody;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetRest;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetsRest;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.springframework.boot.SpringApplication;
+import org.springframework.context.annotation.Description;
+
+import feign.Feign;
+import feign.Logger;
+import feign.auth.BasicAuthRequestInterceptor;
+import feign.jackson.JacksonDecoder;
+import feign.jackson.JacksonEncoder;
+import ru.yandex.qatools.allure.annotations.Features;
+import ru.yandex.qatools.allure.annotations.Stories;
+
+@Features("Example Tests - Management RESTful API Client")
+@Stories("Target Resource")
+public class TargetTest {
+
+ @BeforeClass
+ public static void startupServer() {
+ SpringApplication.run(Start.class, new String[0]);
+ }
+
+ // disabled as this runs not on CI environments.
+ @Test
+ @Description("Simple request of target by ID")
+ @Ignore
+ public void getTarget() {
+ final TargetResource targetResource = createTargetResource();
+ final TargetsRest result = createTargets(targetResource, 1);
+
+ assertThat(targetResource.getTarget("test0").getName()).isEqualTo("testDevice");
+
+ deleteTargets(targetResource, result);
+ }
+
+ // disabled as this runs not on CI environments.
+ @Test
+ @Description("Simple request of all targets with defined page sizing information (i.e. offset and limit).")
+ @Ignore
+ public void getTargetsAsPagedListWithDefinedPageSizing() {
+ final TargetResource targetResource = createTargetResource();
+ final TargetsRest created = createTargets(targetResource, 20);
+
+ final TargetPagedList queryResult = targetResource.getTargets(0, 10);
+
+ assertThat(queryResult.getContent()).hasSize(10);
+ assertThat(queryResult.getTotal()).isEqualTo(20);
+ assertThat(queryResult.getSize()).isEqualTo(10);
+
+ deleteTargets(targetResource, created);
+ }
+
+ // disabled as this runs not on CI environments.
+ @Test
+ @Description("Simple request of all targets with defualt paging parameters.")
+ @Ignore
+ public void getTargetsAsPagedListWithDefaultPageSizing() {
+ final TargetResource targetResource = createTargetResource();
+ final TargetsRest created = createTargets(targetResource, 20);
+
+ final TargetPagedList queryResult = targetResource.getTargets();
+
+ assertThat(queryResult.getContent()).hasSize(20);
+ assertThat(queryResult.getTotal()).isEqualTo(20);
+ assertThat(queryResult.getSize()).isEqualTo(20);
+
+ deleteTargets(targetResource, created);
+ }
+
+ private void deleteTargets(final TargetResource targetResource, final List targets) {
+ for (final TargetRest targetRest : targets) {
+ targetResource.deleteTarget(targetRest.getControllerId());
+ }
+ }
+
+ private TargetsRest createTargets(final TargetResource targetResource, final int number) {
+
+ final List targets = new ArrayList<>();
+ for (int i = 0; i < number; i++) {
+
+ targets.add(new TargetRequestBody().setControllerId("test" + i).setName("testDevice"));
+ }
+
+ final TargetsRest result = targetResource.createTargets(targets);
+
+ assertThat(result).hasSize(number);
+ return result;
+ }
+
+ private TargetResource createTargetResource() {
+ final TargetResource targetResource = Feign.builder().logger(new Logger.ErrorLogger())
+ .logLevel(Logger.Level.BASIC).decoder(new JacksonDecoder()).encoder(new JacksonEncoder())
+ .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin"))
+ .target(TargetResource.class, "http://localhost:8080");
+ return targetResource;
+ }
+
+}
diff --git a/examples/pom.xml b/examples/pom.xml
old mode 100755
new mode 100644
index b4a99b16f..d23eb0098
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -25,6 +25,7 @@
hawkbit-device-simulatorhawkbit-example-app
+ hawkbit-mgmt-api-client
\ No newline at end of file
diff --git a/hawkbit-artifact-repository-mongo/README.md b/hawkbit-artifact-repository-mongo/README.md
old mode 100755
new mode 100644
diff --git a/hawkbit-artifact-repository-mongo/pom.xml b/hawkbit-artifact-repository-mongo/pom.xml
old mode 100755
new mode 100644
index 8eb7534b2..b8d73e256
--- a/hawkbit-artifact-repository-mongo/pom.xml
+++ b/hawkbit-artifact-repository-mongo/pom.xml
@@ -41,7 +41,6 @@
com.google.guavaguava
- 18.0
diff --git a/hawkbit-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactStore.java b/hawkbit-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactStore.java
old mode 100755
new mode 100644
index c5cf03016..78658da91
--- a/hawkbit-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactStore.java
+++ b/hawkbit-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactStore.java
@@ -199,8 +199,8 @@ public class ArtifactStore implements ArtifactRepository {
}
- private String computeSHA1Hash(final InputStream stream, final FileOutputStream os, final String providedSHA1Sum)
- throws NoSuchAlgorithmException, IOException {
+ private static 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");
@@ -240,6 +240,7 @@ public class ArtifactStore implements ArtifactRepository {
* the sha1-hashes of the files to lookup.
* @return list of artfiacts
*/
+ @Override
public List getArtifactsBySha1(final List sha1Hashes) {
return map(gridFs.find(new Query().addCriteria(Criteria.where(SHA1).in(sha1Hashes))));
}
diff --git a/hawkbit-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactStoreAutoConfiguration.java b/hawkbit-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactStoreAutoConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/GridFsArtifact.java b/hawkbit-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/GridFsArtifact.java
old mode 100755
new mode 100644
diff --git a/hawkbit-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/MongoConfiguration.java b/hawkbit-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/MongoConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-artifact-repository-mongo/src/main/resources/META-INF/spring.factories b/hawkbit-artifact-repository-mongo/src/main/resources/META-INF/spring.factories
old mode 100755
new mode 100644
diff --git a/hawkbit-artifact-repository-mongo/src/test/java/org/eclipse/hawkbit/artifact/FreePortFileWriter.java b/hawkbit-artifact-repository-mongo/src/test/java/org/eclipse/hawkbit/artifact/FreePortFileWriter.java
old mode 100755
new mode 100644
diff --git a/hawkbit-artifact-repository-mongo/src/test/java/org/eclipse/hawkbit/artifact/MongoDBTestRule.java b/hawkbit-artifact-repository-mongo/src/test/java/org/eclipse/hawkbit/artifact/MongoDBTestRule.java
old mode 100755
new mode 100644
diff --git a/hawkbit-artifact-repository-mongo/src/test/java/org/eclipse/hawkbit/artifact/TestConfiguration.java b/hawkbit-artifact-repository-mongo/src/test/java/org/eclipse/hawkbit/artifact/TestConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-artifact-repository-mongo/src/test/java/org/eclipse/hawkbit/artifact/repository/ArtifactStoreTest.java b/hawkbit-artifact-repository-mongo/src/test/java/org/eclipse/hawkbit/artifact/repository/ArtifactStoreTest.java
old mode 100755
new mode 100644
diff --git a/hawkbit-autoconfigure/pom.xml b/hawkbit-autoconfigure/pom.xml
old mode 100755
new mode 100644
index 73e93e830..1f8e08b7d
--- a/hawkbit-autoconfigure/pom.xml
+++ b/hawkbit-autoconfigure/pom.xml
@@ -67,11 +67,6 @@
hawkbit-rest-resource${project.version}true
-
-
- io.springfox
- springfox-swagger2
- trueorg.springframework
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/amqp/AmqpAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/amqp/AmqpAutoConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheAutoConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/DownloadIdCacheAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/DownloadIdCacheAutoConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/RedisAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/RedisAutoConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/conf/ControllerPollAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/conf/ControllerPollAutoConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/conf/DefaultPropertiesAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/conf/DefaultPropertiesAutoConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/eventbus/EventBusAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/eventbus/EventBusAutoConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerAutoConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerThreadpoolProperties.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerThreadpoolProperties.java
old mode 100755
new mode 100644
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/ExecutorAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/ExecutorAutoConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/EnableHawkbitManagedSecurityConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/EnableHawkbitManagedSecurityConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityAutoConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java
old mode 100755
new mode 100644
index 1c8b32ffb..63e1e8ad1
--- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java
+++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java
@@ -19,8 +19,6 @@ 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;
@@ -47,6 +45,7 @@ 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.boot.context.embedded.ServletListenerRegistrationBean;
import org.springframework.cache.Cache;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.AdviceMode;
@@ -68,9 +67,7 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
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;
@@ -78,6 +75,7 @@ import org.springframework.security.web.authentication.preauth.RequestHeaderAuth
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.springframework.security.web.session.HttpSessionEventPublisher;
import org.vaadin.spring.security.VaadinSecurityContext;
import org.vaadin.spring.security.annotation.EnableVaadinSecurity;
import org.vaadin.spring.security.web.VaadinDefaultRedirectStrategy;
@@ -161,31 +159,35 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
}
if (securityConfiguration.getAnonymousEnabled()) {
- LOG.info(
- "******************\n** Anonymous controller security enabled, should only use for developing purposes **\n******************");
+ 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)));
+ "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);
+ httpSec.addFilter(securityHeaderFilter)
+ .addFilter(securityTokenFilter)
+ .addFilter(gatewaySecurityTokenFilter)
+ .antMatcher("/*/controller/**")
+ .anonymous()
+ .disable()
+ .authorizeRequests()
+ .anyRequest()
+ .authenticated()
+ .and()
+ .exceptionHandling()
+ .authenticationEntryPoint(
+ (request, response, authException) -> response.setStatus(HttpStatus.UNAUTHORIZED
+ .value())).and().sessionManagement()
+ .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
/*
* (non-Javadoc)
- *
+ *
* @see
* org.springframework.security.config.annotation.web.configuration.
* WebSecurityConfigurerAdapter
@@ -194,8 +196,8 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
*/
@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
- auth.authenticationProvider(
- new PreAuthTokenSourceTrustAuthenticationProvider(securityConfiguration.getRpTrustedIPs()));
+ auth.authenticationProvider(new PreAuthTokenSourceTrustAuthenticationProvider(securityConfiguration
+ .getRpTrustedIPs()));
}
}
@@ -210,12 +212,10 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
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"),
+ filterRegBean.setFilter(new DosFilter(environment
+ .getProperty("security.dos.filter.maxRead", Integer.class, 200), environment.getProperty(
+ "security.dos.filter.maxWrite", Integer.class, 50), 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;
@@ -301,8 +301,7 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
}, RequestHeaderAuthenticationFilter.class)
.addFilterAfter(
new AuthenticationSuccessTenantMetadataCreationFilter(tenantAware, systemManagement),
- RequestHeaderAuthenticationFilter.class)
- .authorizeRequests().anyRequest().authenticated()
+ RequestHeaderAuthenticationFilter.class).authorizeRequests().anyRequest().authenticated()
.antMatchers(RestConstants.BASE_SYSTEM_MAPPING + "/admin/**")
.hasAnyAuthority(SpPermission.SYSTEM_ADMIN).antMatchers(RestConstants.BASE_SYSTEM_MAPPING + "/**")
.hasAnyAuthority(SpPermission.SYSTEM_DIAG);
@@ -311,14 +310,12 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
/**
* {@link WebSecurityConfigurer} for external (management) access.
- *
- *
+ *
*/
@Configuration
@Order(400)
@EnableVaadinSecurity
- public static class UISecurityConfigurationAdapter extends WebSecurityConfigurerAdapter
- implements EnvironmentAware {
+ public static class UISecurityConfigurationAdapter extends WebSecurityConfigurerAdapter implements EnvironmentAware {
private static final String XFRAME_OPTION_DENY = "DENY";
private static final String XFRAME_OPTION_SAMEORIGIN = "SAMEORIGIN";
@@ -370,6 +367,18 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
return handler;
}
+ /**
+ * Listener to redirect to login page after session timeout. Close the
+ * vaadin session, because it's is not possible to redirect in
+ * atmospehere.
+ *
+ * @return the servlet listener.
+ */
+ @Bean
+ public ServletListenerRegistrationBean httpSessionEventPublisher() {
+ return new ServletListenerRegistrationBean<>(new HttpSessionEventPublisher());
+ }
+
@Override
protected void configure(final HttpSecurity http) throws Exception {
@@ -379,9 +388,10 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
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");
+ 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
@@ -390,22 +400,23 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
// vaadin-forum:
// https://vaadin.com/forum#!/thread/3200565.
HttpSecurity httpSec = http.regexMatcher("(?!.*HEARTBEAT)^.*\\/UI.*$")
- // disable as CSRF is handled by Vaadin
+ // 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******************\"");
+ 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()
+ .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()
@@ -439,8 +450,8 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
@Override
public void configure(final WebSecurity webSecurity) throws Exception {
- webSecurity.ignoring().antMatchers("/documentation/**", "/VAADIN/**", "/*.*", "/v2/api-docs/**",
- "/docs/**");
+ webSecurity.ignoring()
+ .antMatchers("/documentation/**", "/VAADIN/**", "/*.*", "/v2/api-docs/**", "/docs/**");
}
}
@@ -471,15 +482,15 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
http.csrf().disable();
http.anonymous().disable();
- http.regexMatcher(HttpDownloadAuthenticationFilter.REQUEST_ID_REGEX_PATTERN)
- .addFilterBefore(downloadIdAuthenticationFilter, FilterSecurityInterceptor.class);
+ 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()));
+ auth.authenticationProvider(new PreAuthTokenSourceTrustAuthenticationProvider(securityConfiguration
+ .getRpTrustedIPs()));
}
}
@@ -499,7 +510,7 @@ class TenantMetadataSavedRequestAwareVaadinAuthenticationSuccessHandler extends
/*
* (non-Javadoc)
- *
+ *
* @see org.vaadin.spring.security.web.authentication.
* SavedRequestAwareVaadinAuthenticationSuccessHandler
* #onAuthenticationSuccess(org.springframework.security.core.
@@ -508,8 +519,8 @@ class TenantMetadataSavedRequestAwareVaadinAuthenticationSuccessHandler extends
@Override
public void onAuthenticationSuccess(final Authentication authentication) throws Exception {
if (authentication.getClass().equals(TenantUserPasswordAuthenticationToken.class)) {
- systemManagement
- .getTenantMetadata(((TenantUserPasswordAuthenticationToken) authentication).getTenant().toString());
+ 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
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/swagger/SwaggerApiDocAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/swagger/SwaggerApiDocAutoConfiguration.java
deleted file mode 100755
index ae405242c..000000000
--- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/swagger/SwaggerApiDocAutoConfiguration.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- */
-package org.eclipse.hawkbit.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 selectApiPaths() {
- return Predicates.or(PathSelectors.regex("/rest/v1/.*"), PathSelectors.regex("/.*/controller/v1/.*"));
- }
-
- private Docket createDocket() {
- final List 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 globalAuhtorizationMessages() {
- final List 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();
- }
-
-}
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/ui/UIAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/ui/UIAutoConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/url/PropertyHostnameResolverAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/url/PropertyHostnameResolverAutoConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/url/ServerProperties.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/url/ServerProperties.java
old mode 100755
new mode 100644
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/web/ResourceControllerAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/web/ResourceControllerAutoConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/web/WebMvcAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/web/WebMvcAutoConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-autoconfigure/src/main/resources/META-INF/spring.factories b/hawkbit-autoconfigure/src/main/resources/META-INF/spring.factories
old mode 100755
new mode 100644
index c0563d7c9..5d8d005d9
--- a/hawkbit-autoconfigure/src/main/resources/META-INF/spring.factories
+++ b/hawkbit-autoconfigure/src/main/resources/META-INF/spring.factories
@@ -3,7 +3,6 @@ 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,\
diff --git a/hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties b/hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties
old mode 100755
new mode 100644
diff --git a/hawkbit-cache-redis/pom.xml b/hawkbit-cache-redis/pom.xml
old mode 100755
new mode 100644
diff --git a/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisConfiguration.java b/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisConfiguration.java
old mode 100755
new mode 100644
diff --git a/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisProperties.java b/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisProperties.java
old mode 100755
new mode 100644
diff --git a/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/annotation/EnableRedis.java b/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/annotation/EnableRedis.java
old mode 100755
new mode 100644
diff --git a/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/eventbus/EventDistributor.java b/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/eventbus/EventDistributor.java
old mode 100755
new mode 100644
diff --git a/hawkbit-cache-redis/src/test/java/org/eclipse/hawkbit/cache/eventbus/EventDistributorTest.java b/hawkbit-cache-redis/src/test/java/org/eclipse/hawkbit/cache/eventbus/EventDistributorTest.java
old mode 100755
new mode 100644
diff --git a/hawkbit-cache-redis/src/test/java/org/eclipse/hawkbit/cache/redis/RedisPropertiesTest.java b/hawkbit-cache-redis/src/test/java/org/eclipse/hawkbit/cache/redis/RedisPropertiesTest.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/pom.xml b/hawkbit-core/pom.xml
old mode 100755
new mode 100644
index 64dea1bbf..403f7aeb2
--- a/hawkbit-core/pom.xml
+++ b/hawkbit-core/pom.xml
@@ -31,7 +31,6 @@
com.google.guavaguava
- 18.0
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/ControllerPollProperties.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/ControllerPollProperties.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/DistributedResourceBundleMessageSource.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/DistributedResourceBundleMessageSource.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/HostnameResolver.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/HostnameResolver.java
old mode 100755
new mode 100644
index 09cd1e9df..2491e85e2
--- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/HostnameResolver.java
+++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/HostnameResolver.java
@@ -12,15 +12,14 @@ import java.net.URL;
/**
* Resolve to reach the server url.
- *
- *
*
*/
+@FunctionalInterface
public interface HostnameResolver {
/**
- *
- *
+ *
+ *
* @return
*/
URL resolveHostname();
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactRepository.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactRepository.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactStoreException.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactStoreException.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/artifact/repository/HashNotMatchException.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/artifact/repository/HashNotMatchException.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/artifact/repository/model/DbArtifact.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/artifact/repository/model/DbArtifact.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/artifact/repository/model/DbArtifactHash.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/artifact/repository/model/DbArtifactHash.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/CacheConstants.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/CacheConstants.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/DownloadArtifactCache.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/DownloadArtifactCache.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/DownloadType.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/DownloadType.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenancyCacheManager.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenancyCacheManager.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenantAwareCacheManager.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenantAwareCacheManager.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/DeadEventListener.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/DeadEventListener.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/EventBusSubscriberProcessor.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/EventBusSubscriberProcessor.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/EventSubscriber.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/EventSubscriber.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/AbstractDistributedEvent.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/AbstractDistributedEvent.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/CancelTargetAssignmentEvent.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/CancelTargetAssignmentEvent.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/CustomEvents.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/CustomEvents.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/DistributedEvent.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/DistributedEvent.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/DownloadProgressEvent.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/DownloadProgressEvent.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/EntityEvent.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/EntityEvent.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/Event.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/Event.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/NodeAware.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/NodeAware.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetDeletedEvent.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetDeletedEvent.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/GenericSpServerException.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/GenericSpServerException.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java
old mode 100755
new mode 100644
index c7996f0dd..91559cc88
--- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java
+++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java
@@ -12,7 +12,7 @@ package org.eclipse.hawkbit.exception;
*
*
*
- * Define the Error code for Error handling
+ * Define the Error code for Error handling
*
*/
@@ -69,8 +69,7 @@ public enum SpServerError {
*
*/
SP_REST_BODY_NOT_READABLE("hawkbit.server.error.rest.body.notReadable",
- "The given request body is not well formed"), SP_UI_SEARCH("hawkbit.server.error.ui.searchError",
- "blabla :-)"),
+ "The given request body is not well formed"),
/**
*
*/
@@ -113,7 +112,6 @@ public enum SpServerError {
/**
*
*/
-
SP_ARTIFACT_LOAD_FAILED("hawkbit.server.error.artifact.loadFailed",
"Load of artifact failed with internal server error."),
@@ -124,26 +122,34 @@ public enum SpServerError {
"Too many status entries have been inserted."),
/**
- *
- */
+ *
+ */
SP_ATTRIBUTES_TO_MANY_ENTRIES("hawkbit.server.error.target.attributes.tooManyEntries",
"Too many attribute entries have been inserted."),
/**
- *
- */
+ * error message, which describes that the action can not be canceled cause
+ * the action is inactive.
+ */
SP_ACTION_NOT_CANCELABLE("hawkbit.server.error.action.notcancelable",
- "Only active actions which are in status pending are canceable"),
+ "Only active actions which are in status pending are canceable."),
/**
- *
- */
+ * error message, which describes that the action can not be force quit
+ * cause the action is inactive.
+ */
+ SP_ACTION_NOT_FORCE_QUITABLE("hawkbit.server.error.action.notforcequitable",
+ "Only active actions which are in status pending can be force quit."),
+
+ /**
+ *
+ */
SP_DS_INCOMPLETE("hawkbit.server.error.distributionset.incomplete",
"Distribution set is assigned to a a target that is incomplete (i.e. mandatory modules are missing)"),
/**
- *
- */
+ *
+ */
SP_DS_TYPE_UNDEFINED("hawkbit.server.error.distributionset.type.undefined",
"Distribution set type is not yet defined. Modules cannot be added until definition."),
@@ -154,8 +160,8 @@ public enum SpServerError {
"Distribution set type does not contain the given module, i.e. is incompatible."),
/**
- *
- */
+ *
+ */
SP_REPO_TENANT_NOT_EXISTS("hawkbit.server.error.repo.tenantNotExists",
"The entity cannot be inserted due the tenant does not exists"),
@@ -181,10 +187,20 @@ public enum SpServerError {
this.message = message;
}
+ /**
+ * Gets the key of the error
+ *
+ * @return the key of the error
+ */
public String getKey() {
return key;
}
+ /**
+ * Gets the message of the error
+ *
+ * @return message of the error
+ */
public String getMessage() {
return message;
}
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerRtException.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerRtException.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionFields.java
old mode 100755
new mode 100644
index bc153d989..c2d8ec49d
--- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionFields.java
+++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionFields.java
@@ -15,7 +15,7 @@ package org.eclipse.hawkbit.repository;
*
*
*/
-public enum ActionFields implements FieldNameProvider, FieldValueConverter {
+public enum ActionFields implements FieldNameProvider,FieldValueConverter {
/**
* The status field.
@@ -51,7 +51,7 @@ public enum ActionFields implements FieldNameProvider, FieldValueConverter
* the return type of the runner
*/
+ @FunctionalInterface
interface TenantRunner {
/**
* Called to run specific code and a given tenant.
- *
+ *
* @return the return of the code block running under a certain tenant
*/
T run();
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/TenantConfigurationKey.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/TenantConfigurationKey.java
old mode 100755
new mode 100644
diff --git a/hawkbit-core/src/test/java/org/eclipse/hawkbit/eventbus/EventBusSubscriberProcessorTest.java b/hawkbit-core/src/test/java/org/eclipse/hawkbit/eventbus/EventBusSubscriberProcessorTest.java
old mode 100755
new mode 100644
diff --git a/hawkbit-dmf-amqp/pom.xml b/hawkbit-dmf-amqp/pom.xml
old mode 100755
new mode 100644
diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpConfiguration.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpConfiguration.java
old mode 100755
new mode 100644
index 30cec2f74..4be22c14f
--- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpConfiguration.java
+++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpConfiguration.java
@@ -47,7 +47,7 @@ public class AmqpConfiguration {
/**
* Method to set the Jackson2JsonMessageConverter.
- *
+ *
* @return the Jackson2JsonMessageConverter
*/
@Bean
@@ -59,7 +59,7 @@ public class AmqpConfiguration {
/**
* Create the sp receiver queue.
- *
+ *
* @return the receiver queue
*/
@Bean
@@ -69,7 +69,7 @@ public class AmqpConfiguration {
/**
* Create the dead letter fanout exchange.
- *
+ *
* @return the fanout exchange
*/
@Bean
@@ -79,7 +79,7 @@ public class AmqpConfiguration {
/**
* Create dead letter queue.
- *
+ *
* @return the queue
*/
@Bean
@@ -89,7 +89,7 @@ public class AmqpConfiguration {
/**
* Create the dead letter fanout exchange.
- *
+ *
* @return the fanout exchange
*/
@Bean
@@ -99,7 +99,7 @@ public class AmqpConfiguration {
/**
* Create the Binding deadLetterQueue to exchangeDeadLetter.
- *
+ *
* @return the binding
*/
@Bean
@@ -110,7 +110,7 @@ public class AmqpConfiguration {
/**
* Create the Binding {@link AmqpConfiguration#receiverQueueFromSp()} to
* {@link AmqpConfiguration#senderConnectorToSpExchange()}.
- *
+ *
* @return the binding and create the queue and exchange
*/
@Bean
@@ -120,7 +120,7 @@ public class AmqpConfiguration {
/**
* Create amqp handler service bean.
- *
+ *
* @return
*/
@Bean
@@ -130,7 +130,7 @@ public class AmqpConfiguration {
/**
* Returns the Listener factory.
- *
+ *
* @return the {@link SimpleMessageListenerContainer} that gets used receive
* AMQP messages
*/
@@ -143,7 +143,7 @@ public class AmqpConfiguration {
}
private Map getDeadLetterExchangeArgs() {
- final Map args = new HashMap();
+ final Map args = new HashMap<>();
args.put("x-dead-letter-exchange", amqpProperties.getDeadLetterExchange());
return args;
}
diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentfication.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentfication.java
old mode 100755
new mode 100644
index ee31470f6..dd36ef1fd
--- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentfication.java
+++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentfication.java
@@ -91,7 +91,7 @@ public class AmqpControllerAuthentfication {
/**
* Performs authentication with the secruity token.
- *
+ *
* @param secruityToken
* the authentication request object
* @return the authentfication object
@@ -110,7 +110,7 @@ public class AmqpControllerAuthentfication {
}
- private PreAuthenticatedAuthenticationToken createAuthentication(final PreAuthenficationFilter filter,
+ private static PreAuthenticatedAuthenticationToken createAuthentication(final PreAuthenficationFilter filter,
final TenantSecruityToken secruityToken) {
if (!filter.isEnable(secruityToken)) {
diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java
old mode 100755
new mode 100644
index 933124560..7469e6768
--- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java
+++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java
@@ -31,13 +31,14 @@ import org.eclipse.hawkbit.util.IpUtil;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.support.converter.AbstractJavaTypeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import com.google.common.eventbus.Subscribe;
/**
* {@link AmqpMessageDispatcherService} handles all outgoing AMQP messages.
- *
+ *
*
*
*/
@@ -56,7 +57,7 @@ public class AmqpMessageDispatcherService {
/**
* Method to send a message to a RabbitMQ Exchange after the Distribution
* set has been assign to a Target.
- *
+ *
* @param targetAssignDistributionSetEvent
* the object to be send.
*/
@@ -86,7 +87,7 @@ public class AmqpMessageDispatcherService {
/**
* Method to send a message to a RabbitMQ Exchange after the assignment of
* the Distribution set to a Target has been canceled.
- *
+ *
* @param cancelTargetAssignmentDistributionSetEvent
* the object to be send.
*/
@@ -104,13 +105,14 @@ public class AmqpMessageDispatcherService {
/**
* Send message to exchange.
- *
+ *
* @param exchange
* the exchange
* @param message
* the message
*/
public void sendMessage(final String exchange, final Message message) {
+ message.getMessageProperties().getHeaders().remove(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME);
rabbitTemplate.setExchange(exchange);
rabbitTemplate.send(message);
}
@@ -124,7 +126,7 @@ public class AmqpMessageDispatcherService {
return messageProperties;
}
- private MessageProperties createMessageProperties() {
+ private static MessageProperties createMessageProperties() {
final MessageProperties messageProperties = new MessageProperties();
messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON);
messageProperties.setHeader(MessageHeaderKey.CONTENT_TYPE, MessageProperties.CONTENT_TYPE_JSON);
diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java
old mode 100755
new mode 100644
index 33a08980b..640c0e270
--- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java
+++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java
@@ -71,9 +71,9 @@ import org.springframework.web.util.UriComponentsBuilder;
import com.google.common.eventbus.EventBus;
/**
- *
+ *
* {@link AmqpMessageHandlerService} handles all incoming AMQP messages.
- *
+ *
*
*
*
@@ -106,7 +106,7 @@ public class AmqpMessageHandlerService {
/**
* /** Method to handle all incoming amqp messages.
- *
+ *
* @param message
* incoming message
* @param type
@@ -199,7 +199,7 @@ public class AmqpMessageHandlerService {
return rabbitTemplate.getMessageConverter().toMessage(authentificationResponse, messageProperties);
}
- private Artifact convertDbArtifact(final DbArtifact dbArtifact) {
+ private static Artifact convertDbArtifact(final DbArtifact dbArtifact) {
final Artifact artifact = new Artifact();
artifact.setSize(dbArtifact.getSize());
final DbArtifactHash dbArtifactHash = dbArtifact.getHashes();
@@ -212,13 +212,13 @@ public class AmqpMessageHandlerService {
throw new IllegalArgumentException(error);
}
- private void setSecurityContext(final Authentication authentication) {
+ private static void setSecurityContext(final Authentication authentication) {
final SecurityContextImpl securityContextImpl = new SecurityContextImpl();
securityContextImpl.setAuthentication(authentication);
SecurityContextHolder.setContext(securityContextImpl);
}
- private void setTenantSecurityContext(final String tenantId) {
+ private static void setTenantSecurityContext(final String tenantId) {
final AnonymousAuthenticationToken authenticationToken = new AnonymousAuthenticationToken(
UUID.randomUUID().toString(), "AMQP-Controller",
Collections.singletonList(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS)));
@@ -237,7 +237,7 @@ public class AmqpMessageHandlerService {
/**
* Method to create a new target or to find the target if it already exists.
- *
+ *
* @param targetID
* the ID of the target/thing
* @param ip
@@ -274,7 +274,7 @@ public class AmqpMessageHandlerService {
/**
* Method to handle the different topics to an event.
- *
+ *
* @param message
* the incoming event message.
* @param topic
@@ -292,7 +292,7 @@ public class AmqpMessageHandlerService {
/**
* Method to update the action status of an action through the event.
- *
+ *
* @param actionUpdateStatus
* the object form the ampq message
*/
@@ -330,6 +330,9 @@ public class AmqpMessageHandlerService {
case RUNNING:
actionStatus.setStatus(Status.RUNNING);
break;
+ case CANCELED:
+ actionStatus.setStatus(Status.CANCELED);
+ break;
case FINISHED:
actionStatus.setStatus(Status.FINISHED);
break;
@@ -339,19 +342,43 @@ public class AmqpMessageHandlerService {
case WARNING:
actionStatus.setStatus(Status.WARNING);
break;
+ case CANCEL_REJECTED:
+ handleCancelRejected(message, action, actionStatus);
+ break;
default:
logAndThrowMessageError(message, "Status for action does not exisit.");
}
- final Action savedAction = controllerManagement.addUpdateActionStatus(actionStatus, action);
- if (Status.FINISHED == savedAction.getStatus()) {
+ Action addUpdateActionStatus;
+
+ if (!actionStatus.getStatus().equals(Status.CANCELED)) {
+ addUpdateActionStatus = controllerManagement.addUpdateActionStatus(actionStatus, action);
+ } else {
+ addUpdateActionStatus = controllerManagement.addCancelActionStatus(actionStatus, action);
+ }
+
+ if (!addUpdateActionStatus.isActive()) {
lookIfUpdateAvailable(action.getTarget());
}
}
+ private void handleCancelRejected(final Message message, final Action action, final ActionStatus actionStatus) {
+ if (action.isCancelingOrCanceled()) {
+
+ actionStatus.setStatus(Status.WARNING);
+
+ // cancel action rejected, write warning status message and fall
+ // back to running action status
+
+ } else {
+ logAndThrowMessageError(message,
+ "Cancel Recjected message is not allowed, if action is on state: " + action.getStatus());
+ }
+ }
+
/**
* Is needed to convert a incoming message to is originally object type.
- *
+ *
* @param message
* the message to convert.
* @param clazz
@@ -367,14 +394,15 @@ public class AmqpMessageHandlerService {
/**
* Is needed to verify if an incoming message has the content type json.
- *
+ *
* @param message
* the to verify
* @param contentType
* the content type
* @return true if the content type has json, false it not.
*/
- private void checkContentTypeJson(final Message message) {
+
+ private static void checkContentTypeJson(final Message message) {
final MessageProperties messageProperties = message.getMessageProperties();
if (messageProperties.getContentType() != null && messageProperties.getContentType().contains("json")) {
return;
diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java
old mode 100755
new mode 100644
diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/annotation/EnableAmqp.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/annotation/EnableAmqp.java
old mode 100755
new mode 100644
diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/util/ArtifactUrlHandler.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/util/ArtifactUrlHandler.java
old mode 100755
new mode 100644
index 488cfa2cb..f477da03a
--- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/util/ArtifactUrlHandler.java
+++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/util/ArtifactUrlHandler.java
@@ -14,15 +14,14 @@ import org.eclipse.hawkbit.repository.model.LocalArtifact;
/**
* Interface declaration of the {@link ArtifactUrlHandler} which generates the
* URLs to specific artifacts.
- *
- *
*
*/
+@FunctionalInterface
public interface ArtifactUrlHandler {
/**
* Returns a generated URL for a given artifact for a specific protocol.
- *
+ *
* @param controllerId
* the authentifacted controller id
* @param localArtifact
diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/util/ArtifactUrlHandlerProperties.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/util/ArtifactUrlHandlerProperties.java
old mode 100755
new mode 100644
diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/util/PropertyBasedArtifactUrlHandler.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/util/PropertyBasedArtifactUrlHandler.java
old mode 100755
new mode 100644
diff --git a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentficationTest.java b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentficationTest.java
old mode 100755
new mode 100644
diff --git a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java
old mode 100755
new mode 100644
index f9c6ff64b..778f196e9
--- a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java
+++ b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java
@@ -43,6 +43,7 @@ import org.mockito.Mockito;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.support.converter.AbstractJavaTypeMapper;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.test.context.ActiveProfiles;
@@ -154,15 +155,15 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
CONTROLLER_ID, 1l, IpUtil.createAmqpUri("mytest"));
amqpMessageDispatcherService
.targetCancelAssignmentToDistributionSet(cancelTargetAssignmentDistributionSetEvent);
- final Message sendMessage = createArgumentCapture(
- cancelTargetAssignmentDistributionSetEvent.getTargetAdress().getHost());
+ final Message sendMessage = createArgumentCapture(cancelTargetAssignmentDistributionSetEvent.getTargetAdress()
+ .getHost());
assertCancelMessage(sendMessage);
}
private void assertCancelMessage(final Message sendMessage) {
assertEventMessage(sendMessage);
- final Long actionId = (Long) messageConverter.fromMessage(sendMessage);
+ final Long actionId = convertMessage(sendMessage, Long.class);
assertEquals(actionId, Long.valueOf(1));
assertEquals(EventTopic.CANCEL_DOWNLOAD,
sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC));
@@ -171,8 +172,8 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
private DownloadAndUpdateRequest assertDownloadAndInstallMessage(final Message sendMessage) {
assertEventMessage(sendMessage);
- final DownloadAndUpdateRequest downloadAndUpdateRequest = (DownloadAndUpdateRequest) messageConverter
- .fromMessage(sendMessage);
+ final DownloadAndUpdateRequest downloadAndUpdateRequest = convertMessage(sendMessage,
+ DownloadAndUpdateRequest.class);
assertEquals(downloadAndUpdateRequest.getActionId(), Long.valueOf(1));
assertEquals(EventTopic.DOWNLOAD_AND_INSTALL,
sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC));
@@ -197,4 +198,11 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
return argumentCaptor.getValue();
}
+ @SuppressWarnings("unchecked")
+ private T convertMessage(final Message message, final Class clazz) {
+ message.getMessageProperties().getHeaders()
+ .put(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME, clazz.getTypeName());
+ return (T) rabbitTemplate.getMessageConverter().fromMessage(message);
+ }
+
}
diff --git a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java
old mode 100755
new mode 100644
diff --git a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/util/PropertyBasedArtifactUrlHandlerTest.java b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/util/PropertyBasedArtifactUrlHandlerTest.java
old mode 100755
new mode 100644
diff --git a/hawkbit-dmf-api/README.md b/hawkbit-dmf-api/README.md
old mode 100755
new mode 100644
diff --git a/hawkbit-dmf-api/pom.xml b/hawkbit-dmf-api/pom.xml
old mode 100755
new mode 100644
diff --git a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/AmqpSettings.java b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/AmqpSettings.java
old mode 100755
new mode 100644
diff --git a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/EventTopic.java b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/EventTopic.java
old mode 100755
new mode 100644
diff --git a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/MessageHeaderKey.java b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/MessageHeaderKey.java
old mode 100755
new mode 100644
diff --git a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/MessageType.java b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/MessageType.java
old mode 100755
new mode 100644
diff --git a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/ActionStatus.java b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/ActionStatus.java
old mode 100755
new mode 100644
index 883740354..12e80139a
--- a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/ActionStatus.java
+++ b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/ActionStatus.java
@@ -22,6 +22,6 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include;
@JsonIgnoreProperties(ignoreUnknown = true)
public enum ActionStatus {
- DOWNLOAD, RETRIEVED, RUNNING, FINISHED, ERROR, WARNING;
+ DOWNLOAD, RETRIEVED, RUNNING, FINISHED, ERROR, WARNING, CANCELED, CANCEL_REJECTED;
}
diff --git a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/ActionUpdateStatus.java b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/ActionUpdateStatus.java
old mode 100755
new mode 100644
diff --git a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/Artifact.java b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/Artifact.java
old mode 100755
new mode 100644
index c3f555c33..27da75fb0
--- a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/Artifact.java
+++ b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/Artifact.java
@@ -8,7 +8,7 @@
*/
package org.eclipse.hawkbit.dmf.json.model;
-import java.util.HashMap;
+import java.util.EnumMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@@ -18,7 +18,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
/**
* JSON representation of artifact.
- *
+ *
*
*
*/
@@ -28,11 +28,9 @@ public class Artifact {
/**
* Represented the supported protocols for artifact url's.
- *
- *
*
*/
- public static enum UrlProtocol {
+ public enum UrlProtocol {
COAP, HTTP, HTTPS
}
@@ -46,7 +44,7 @@ public class Artifact {
private Long size;
@JsonProperty
- private Map urls = new HashMap<>();
+ private Map urls = new EnumMap<>(UrlProtocol.class);
public Map getUrls() {
return urls;
diff --git a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/ArtifactHash.java b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/ArtifactHash.java
old mode 100755
new mode 100644
diff --git a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DownloadAndUpdateRequest.java b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DownloadAndUpdateRequest.java
old mode 100755
new mode 100644
index d31141879..4344c5416
--- a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DownloadAndUpdateRequest.java
+++ b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DownloadAndUpdateRequest.java
@@ -18,7 +18,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
/**
* JSON representation of download and update request.
- *
+ *
*
*
*
@@ -29,7 +29,7 @@ public class DownloadAndUpdateRequest {
@JsonProperty
private Long actionId;
@JsonProperty
- private final List softwareModules = new LinkedList();
+ private final List softwareModules = new LinkedList<>();
public Long getActionId() {
return actionId;
@@ -45,7 +45,7 @@ public class DownloadAndUpdateRequest {
/**
* Add a Software module.
- *
+ *
* @param createSoftwareModule
* the module
*/
diff --git a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DownloadResponse.java b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DownloadResponse.java
old mode 100755
new mode 100644
diff --git a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/SoftwareModule.java b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/SoftwareModule.java
old mode 100755
new mode 100644
index 2e553c051..193f33575
--- a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/SoftwareModule.java
+++ b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/SoftwareModule.java
@@ -19,7 +19,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
/**
* JSON representation of a software module.
- *
+ *
*
*
*
@@ -35,7 +35,7 @@ public class SoftwareModule {
@JsonProperty
private String moduleVersion;
@JsonProperty
- private List artifacts = new LinkedList();
+ private List artifacts = new LinkedList<>();
public String getModuleType() {
return moduleType;
diff --git a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/TenantSecruityToken.java b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/TenantSecruityToken.java
old mode 100755
new mode 100644
diff --git a/hawkbit-http-security/pom.xml b/hawkbit-http-security/pom.xml
old mode 100755
new mode 100644
diff --git a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/AbstractHttpControllerAuthenticationFilter.java b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/AbstractHttpControllerAuthenticationFilter.java
old mode 100755
new mode 100644
diff --git a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/ControllerTenantAwareAuthenticationDetailsSource.java b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/ControllerTenantAwareAuthenticationDetailsSource.java
old mode 100755
new mode 100644
diff --git a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticateSecurityTokenFilter.java b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticateSecurityTokenFilter.java
old mode 100755
new mode 100644
diff --git a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticatedGatewaySecurityTokenFilter.java b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticatedGatewaySecurityTokenFilter.java
old mode 100755
new mode 100644
diff --git a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticatedSecurityHeaderFilter.java b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticatedSecurityHeaderFilter.java
old mode 100755
new mode 100644
diff --git a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpDownloadAuthenticationFilter.java b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpDownloadAuthenticationFilter.java
old mode 100755
new mode 100644
diff --git a/hawkbit-http-security/src/test/java/org/eclipse/hawkbit/security/PreAuthTokenSourceTrustAuthenticationProviderTest.java b/hawkbit-http-security/src/test/java/org/eclipse/hawkbit/security/PreAuthTokenSourceTrustAuthenticationProviderTest.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/README.md b/hawkbit-repository/README.md
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/pom.xml b/hawkbit-repository/pom.xml
old mode 100755
new mode 100644
index 930d1bcc6..e5d7011ae
--- a/hawkbit-repository/pom.xml
+++ b/hawkbit-repository/pom.xml
@@ -70,7 +70,6 @@
com.google.guavaguava
- 18.0net._01001111
diff --git a/hawkbit-repository/src/fbExcludeFilter.xml b/hawkbit-repository/src/fbExcludeFilter.xml
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/Constants.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/Constants.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/MultiTenantJpaTransactionManager.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/MultiTenantJpaTransactionManager.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java
old mode 100755
new mode 100644
index d0450122c..a621e94fc
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java
@@ -11,7 +11,7 @@ package org.eclipse.hawkbit;
import java.util.HashMap;
import java.util.Map;
-import org.eclipse.hawkbit.aspects.SpExceptionMappingAspect;
+import org.eclipse.hawkbit.aspects.ExceptionMappingAspectHandler;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.model.helper.CacheManagerHolder;
import org.eclipse.hawkbit.repository.model.helper.PollConfigurationHelper;
@@ -123,11 +123,11 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
}
/**
- * @return {@link SpExceptionMappingAspect} aspect bean
+ * @return {@link ExceptionMappingAspectHandler} aspect bean
*/
@Bean
- public SpExceptionMappingAspect createRepositoryExceptionHandlerAdvice() {
- return new SpExceptionMappingAspect();
+ public ExceptionMappingAspectHandler createRepositoryExceptionHandlerAdvice() {
+ return new ExceptionMappingAspectHandler();
}
/*
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/aspects/ExceptionMappingAspectHandler.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/aspects/ExceptionMappingAspectHandler.java
new file mode 100644
index 000000000..bcb96f45d
--- /dev/null
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/aspects/ExceptionMappingAspectHandler.java
@@ -0,0 +1,179 @@
+/**
+ * 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.aspects;
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.transaction.TransactionManager;
+
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Aspect;
+import org.eclipse.hawkbit.exception.GenericSpServerException;
+import org.eclipse.hawkbit.repository.exception.ConcurrentModificationException;
+import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
+import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.Ordered;
+import org.springframework.dao.ConcurrencyFailureException;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
+import org.springframework.orm.jpa.JpaSystemException;
+import org.springframework.orm.jpa.JpaVendorAdapter;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.transaction.TransactionSystemException;
+
+/**
+ * {@link Aspect} catches persistence exceptions and wraps them to custom
+ * specific exceptions Additionally it checks and prevents access to certain
+ * packages. Logging aspect which logs the call stack
+ *
+ *
+ *
+ */
+@Aspect
+public class ExceptionMappingAspectHandler implements Ordered {
+ private static final Logger LOG = LoggerFactory.getLogger(ExceptionMappingAspectHandler.class);
+
+ private static final Map EXCEPTION_MAPPING = new HashMap<>();
+
+ /**
+ * this is required to enable a certain order of exception and to select the
+ * most specific mappable exception according to the type hierarchy of the
+ * exception.
+ */
+ private static final List> MAPPED_EXCEPTION_ORDER = new ArrayList<>();
+
+ @Autowired
+ private JpaVendorAdapter jpaVendorAdapter;
+
+ private final SQLStateSQLExceptionTranslator sqlStateExceptionTranslator = new SQLStateSQLExceptionTranslator();
+
+ static {
+ MAPPED_EXCEPTION_ORDER.add(DuplicateKeyException.class);
+ MAPPED_EXCEPTION_ORDER.add(DataIntegrityViolationException.class);
+ MAPPED_EXCEPTION_ORDER.add(ConcurrencyFailureException.class);
+ MAPPED_EXCEPTION_ORDER.add(AccessDeniedException.class);
+
+ EXCEPTION_MAPPING.put(DuplicateKeyException.class.getName(), EntityAlreadyExistsException.class.getName());
+ EXCEPTION_MAPPING.put(DataIntegrityViolationException.class.getName(),
+ EntityAlreadyExistsException.class.getName());
+
+ EXCEPTION_MAPPING.put(ConcurrencyFailureException.class.getName(),
+ ConcurrentModificationException.class.getName());
+ EXCEPTION_MAPPING.put(AccessDeniedException.class.getName(), InsufficientPermissionException.class.getName());
+ }
+
+ /**
+ * catch exceptions of the {@link TransactionManager} and wrap them to
+ * custom exceptions.
+ *
+ * @param ex
+ * the thrown and catched exception
+ * @throws Throwable
+ */
+ @AfterThrowing(pointcut = "( execution( * org.springframework.transaction..*.*(..)) "
+ + " || execution( * org.eclipse.hawkbit.repository.*.*(..)) "
+ + " || execution( * org.eclipse.hawkbit.controller.*.*(..)) "
+ + " || execution( * org.eclipse.hawkbit.rest.resource.*.*(..)) "
+ + " || execution( * org.eclipse.hawkbit.service.*.*(..)) )", throwing = "ex")
+ public void catchAndWrapJpaExceptionsService(final Exception ex) throws Throwable {
+ LOG.trace("exception occured", ex);
+ Exception translatedAccessException = translateEclipseLinkExceptionIfPossible(ex);
+
+ if (translatedAccessException == null && ex instanceof TransactionSystemException) {
+ final TransactionSystemException systemException = (TransactionSystemException) ex;
+ translatedAccessException = translateEclipseLinkExceptionIfPossible((Exception) systemException
+ .getOriginalException());
+ }
+
+ if (translatedAccessException == null) {
+ translatedAccessException = ex;
+ }
+
+ Exception mappingException = translatedAccessException;
+
+ LOG.trace("translated excpetion is", translatedAccessException);
+ for (final Class> mappedEx : MAPPED_EXCEPTION_ORDER) {
+
+ if (mappedEx.isAssignableFrom(translatedAccessException.getClass())) {
+ if (!EXCEPTION_MAPPING.containsKey(mappedEx.getName())) {
+ LOG.error("there is no mapping configured for exception class {}", mappedEx.getName());
+ mappingException = new GenericSpServerException(ex);
+ } else {
+ mappingException = (Exception) Class.forName(EXCEPTION_MAPPING.get(mappedEx.getName()))
+ .getConstructor(Throwable.class).newInstance(ex);
+ }
+ break;
+ }
+ }
+ LOG.trace("mapped exception {} to {}", translatedAccessException.getClass(), mappingException.getClass());
+ throw mappingException;
+ }
+
+ private DataAccessException translateEclipseLinkExceptionIfPossible(final Exception exception) {
+ final DataAccessException translatedAccessException = jpaVendorAdapter.getJpaDialect()
+ .translateExceptionIfPossible((RuntimeException) exception);
+ return translateSQLStateExceptionIfPossible(translatedAccessException);
+
+ }
+
+ /**
+ * There is no EclipseLinkExceptionTranslator. So we have to check and
+ * translate the exception by the sql error code. Luckily, there we can use
+ * {@link SQLStateSQLExceptionTranslator} if we can get a
+ * {@link SQLException}.
+ *
+ * @param accessException
+ * the base access exception from jpa
+ * @return the translated accessException
+ */
+ private DataAccessException translateSQLStateExceptionIfPossible(final DataAccessException accessException) {
+ if (!(accessException instanceof JpaSystemException)) {
+ return accessException;
+ }
+
+ final SQLException ex = findSqlException((JpaSystemException) accessException);
+
+ if (ex == null) {
+ return accessException;
+ }
+
+ return sqlStateExceptionTranslator.translate(null, null, ex);
+ }
+
+ private static SQLException findSqlException(final JpaSystemException jpaSystemException) {
+ Throwable exception = jpaSystemException.getCause();
+ while (exception != null) {
+ final Throwable cause = exception.getCause();
+ if (cause instanceof SQLException) {
+ return (SQLException) cause;
+ }
+ exception = cause;
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.core.Ordered#getOrder()
+ */
+ @Override
+ public int getOrder() {
+ return 1;
+ }
+}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/aspects/SpExceptionMappingAspect.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/aspects/SpExceptionMappingAspect.java
deleted file mode 100755
index 90fc95d8d..000000000
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/aspects/SpExceptionMappingAspect.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/**
- * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- */
-package org.eclipse.hawkbit.aspects;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.transaction.TransactionManager;
-
-import org.aspectj.lang.annotation.AfterThrowing;
-import org.aspectj.lang.annotation.Aspect;
-import org.eclipse.hawkbit.exception.GenericSpServerException;
-import org.eclipse.hawkbit.repository.exception.ConcurrentModificationException;
-import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
-import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.core.Ordered;
-import org.springframework.dao.ConcurrencyFailureException;
-import org.springframework.dao.DataIntegrityViolationException;
-import org.springframework.dao.DuplicateKeyException;
-import org.springframework.security.access.AccessDeniedException;
-
-/**
- * {@link Aspect} catches persistence exceptions and wraps them to custom
- * specific exceptions Additionally it checks and prevents access to certain
- * packages. Logging aspect which logs the call stack
- *
- *
- *
- */
-@Aspect
-public class SpExceptionMappingAspect implements Ordered {
- private static final Logger LOG = LoggerFactory.getLogger(SpExceptionMappingAspect.class);
-
- private static final Map EXCEPTION_MAPPING = new HashMap();
-
- /**
- * this is required to enable a certain order of exception and to select the
- * most specific mappable exception according to the type hierarchy of the
- * exception.
- */
- private static final List> MAPPED_EXCEPTION_ORDER = new ArrayList>();
-
- static {
- MAPPED_EXCEPTION_ORDER.add(DuplicateKeyException.class);
- MAPPED_EXCEPTION_ORDER.add(DataIntegrityViolationException.class);
- MAPPED_EXCEPTION_ORDER.add(ConcurrencyFailureException.class);
- MAPPED_EXCEPTION_ORDER.add(AccessDeniedException.class);
-
- EXCEPTION_MAPPING.put(DuplicateKeyException.class.getName(), EntityAlreadyExistsException.class.getName());
-
- EXCEPTION_MAPPING.put(ConcurrencyFailureException.class.getName(),
- ConcurrentModificationException.class.getName());
- EXCEPTION_MAPPING.put(AccessDeniedException.class.getName(), InsufficientPermissionException.class.getName());
- }
-
- /**
- * catch exceptions of the {@link TransactionManager} and wrap them to
- * custom exceptions.
- *
- * @param ex
- * the thrown and catched exception
- * @throws Throwable
- */
- @AfterThrowing(pointcut = "( execution( * org.springframework.transaction..*.*(..)) "
- + " || execution( * org.eclipse.hawkbit.repository.*.*(..)) "
- + " || execution( * org.eclipse.hawkbit.controller.*.*(..)) "
- + " || execution( * org.eclipse.hawkbit.service.*.*(..)) )", throwing = "ex")
- public void catchAndWrapJpaExceptionsService(final Exception ex) throws Throwable {
- final Class extends Exception> exClass = ex.getClass();
- Exception newEx = ex;
- LOG.trace("exception occured", ex);
- for (final Class> mappedEx : MAPPED_EXCEPTION_ORDER) {
-
- if (mappedEx.isAssignableFrom(exClass)) {
- if (!EXCEPTION_MAPPING.containsKey(mappedEx.getName())) {
- LOG.error("there is no mapping configured for exception class {}", mappedEx.getName());
- newEx = new GenericSpServerException(ex);
- } else {
- newEx = (Exception) Class.forName(EXCEPTION_MAPPING.get(mappedEx.getName()))
- .getConstructor(Throwable.class).newInstance(ex);
- }
- break;
- }
- }
- LOG.trace("mapped exception {} to {}", ex.getClass(), newEx.getClass());
- throw newEx;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.springframework.core.Ordered#getOrder()
- */
- @Override
- public int getOrder() {
- return 1;
- }
-}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/cache/CacheField.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/cache/CacheField.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/cache/CacheKeys.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/cache/CacheKeys.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/cache/CacheWriteNotify.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/cache/CacheWriteNotify.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/CacheFieldEntityListener.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/CacheFieldEntityListener.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/EntityChangeEventListener.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/EntityChangeEventListener.java
old mode 100755
new mode 100644
index a62d9265b..e1ff377e5
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/EntityChangeEventListener.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/EntityChangeEventListener.java
@@ -18,6 +18,7 @@ import org.aspectj.lang.annotation.Aspect;
import org.eclipse.hawkbit.eventbus.event.TargetCreatedEvent;
import org.eclipse.hawkbit.eventbus.event.TargetDeletedEvent;
import org.eclipse.hawkbit.eventbus.event.TargetInfoUpdateEvent;
+import org.eclipse.hawkbit.executor.AfterTransactionCommitExecutor;
import org.eclipse.hawkbit.repository.TargetRepository;
import org.eclipse.hawkbit.repository.model.BaseEntity;
import org.eclipse.hawkbit.repository.model.Target;
@@ -49,6 +50,9 @@ public class EntityChangeEventListener {
@Autowired
private EntityManager entityManager;
+ @Autowired
+ private AfterTransactionCommitExecutor afterCommit;
+
/**
* In case the a {@link Target} is created a corresponding
* {@link TargetInfo} is created as well. We need the {@link TargetInfo}
@@ -68,10 +72,6 @@ public class EntityChangeEventListener {
final Object result = joinpoint.proceed();
if (result instanceof TargetInfo) {
if (isNew) {
- // we need to flush here because seems like eclipselink
- // implementation setting the ID of the target no immediately
- // otherwise.
- entityManager.flush();
notifyTargetCreated(entityManager.merge(entityManager.merge(((TargetInfo) result).getTarget())));
} else {
notifyTargetInfoChanged((TargetInfo) result);
@@ -129,15 +129,16 @@ public class EntityChangeEventListener {
}
private void notifyTargetCreated(final Target t) {
- eventBus.post(new TargetCreatedEvent(t));
+ afterCommit.afterCommit(() -> eventBus.post(new TargetCreatedEvent(t)));
+
}
private void notifyTargetInfoChanged(final TargetInfo targetInfo) {
- eventBus.post(new TargetInfoUpdateEvent(targetInfo));
+ afterCommit.afterCommit(() -> eventBus.post(new TargetInfoUpdateEvent(targetInfo)));
}
private void notifyTargetDeleted(final String tenant, final Long targetId) {
- eventBus.post(new TargetDeletedEvent(tenant, targetId));
+ afterCommit.afterCommit(() -> eventBus.post(new TargetDeletedEvent(tenant, targetId)));
}
private boolean isTargetInfoNew(final Object targetInfo) {
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/AbstractBaseEntityEvent.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/AbstractBaseEntityEvent.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/AbstractEntityBulkEvent.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/AbstractEntityBulkEvent.java
new file mode 100644
index 000000000..0a0ce88ce
--- /dev/null
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/AbstractEntityBulkEvent.java
@@ -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
+ */
+package org.eclipse.hawkbit.eventbus.event;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.hawkbit.repository.model.BaseEntity;
+
+/**
+ *
+ * A abstract typesafe bulkevent which contains all changed base entities.
+ *
+ * @param
+ */
+public abstract class AbstractEntityBulkEvent implements EntityBulkEvent {
+
+ private static final long serialVersionUID = 1L;
+
+ private List entities;
+
+ private String tenant;
+
+ /**
+ * Constructor.
+ *
+ * @param tenant
+ * the tenant
+ * @param entities
+ * the changed entities
+ */
+ public AbstractEntityBulkEvent(final String tenant, final List entities) {
+ this.entities = entities;
+ this.tenant = tenant;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param tenant
+ * the tenant
+ * @param entitiy
+ * the changed entity
+ */
+ public AbstractEntityBulkEvent(final String tenant, final E entitiy) {
+ this(tenant, Arrays.asList(entitiy));
+ }
+
+ @Override
+ public List getEntities() {
+ return entities;
+ }
+
+ @Override
+ public long getRevision() {
+ return -1;
+ }
+
+ @Override
+ public String getTenant() {
+ return tenant;
+ }
+
+}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/DistributionSetTagAssigmentResultEvent.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/DistributionSetTagAssigmentResultEvent.java
new file mode 100644
index 000000000..9a8a485b4
--- /dev/null
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/DistributionSetTagAssigmentResultEvent.java
@@ -0,0 +1,34 @@
+/**
+ * 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 org.eclipse.hawkbit.repository.model.DistributionSetTagAssigmentResult;
+
+/**
+ * A event for assignment target tag.
+ */
+public class DistributionSetTagAssigmentResultEvent {
+
+ private final DistributionSetTagAssigmentResult assigmentResult;
+
+ /**
+ * Constructor.
+ *
+ * @param assigmentResult
+ * the assignment result-
+ */
+ public DistributionSetTagAssigmentResultEvent(final DistributionSetTagAssigmentResult assigmentResult) {
+ this.assigmentResult = assigmentResult;
+ }
+
+ public DistributionSetTagAssigmentResult getAssigmentResult() {
+ return assigmentResult;
+ }
+
+}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/DistributionSetTagCreatedBulkEvent.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/DistributionSetTagCreatedBulkEvent.java
new file mode 100644
index 000000000..fb7c4a862
--- /dev/null
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/DistributionSetTagCreatedBulkEvent.java
@@ -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.eventbus.event;
+
+import java.util.List;
+
+import org.eclipse.hawkbit.repository.model.DistributionSetTag;
+
+/**
+ * * A bulk event which contains one or many new ds tag after creating.
+ */
+public class DistributionSetTagCreatedBulkEvent extends AbstractEntityBulkEvent {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor.
+ *
+ * @param tenant
+ * the tenant
+ * @param entities
+ * the new ds tags
+ */
+ public DistributionSetTagCreatedBulkEvent(final String tenant, final List entities) {
+ super(tenant, entities);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param tenant
+ * the tenant.
+ * @param entity
+ * the new ds tag
+ */
+ public DistributionSetTagCreatedBulkEvent(final String tenant, final DistributionSetTag entity) {
+ super(tenant, entity);
+ }
+
+}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/DistributionSetTagDeletedEvent.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/DistributionSetTagDeletedEvent.java
new file mode 100644
index 000000000..b909390d1
--- /dev/null
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/DistributionSetTagDeletedEvent.java
@@ -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.eventbus.event;
+
+import org.eclipse.hawkbit.repository.model.DistributionSetTag;
+
+/**
+ * Defines the {@link AbstractBaseEntityEvent} of update a
+ * {@link DistributionSetTag}.
+ *
+ */
+public class DistributionSetTagDeletedEvent extends AbstractBaseEntityEvent {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor.
+ *
+ * @param tag
+ * the tag which is deleted
+ */
+ public DistributionSetTagDeletedEvent(final DistributionSetTag tag) {
+ super(tag);
+ }
+}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/DistributionSetTagUpdateEvent.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/DistributionSetTagUpdateEvent.java
new file mode 100644
index 000000000..2825322f9
--- /dev/null
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/DistributionSetTagUpdateEvent.java
@@ -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.eventbus.event;
+
+import org.eclipse.hawkbit.repository.model.DistributionSetTag;
+
+/**
+ * Defines the {@link AbstractBaseEntityEvent} for update a
+ * {@link DistributionSetTag}.
+ *
+ */
+public class DistributionSetTagUpdateEvent extends AbstractBaseEntityEvent {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor.
+ *
+ * @param tag
+ * the tag which is updated
+ */
+ public DistributionSetTagUpdateEvent(final DistributionSetTag tag) {
+ super(tag);
+ }
+}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/EntityBulkEvent.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/EntityBulkEvent.java
new file mode 100644
index 000000000..2004d3017
--- /dev/null
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/EntityBulkEvent.java
@@ -0,0 +1,34 @@
+/**
+ * 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;
+import java.util.List;
+
+import org.eclipse.hawkbit.repository.model.BaseEntity;
+
+/**
+ * An event interface which declares event types that an entities has been
+ * changed.
+ *
+ * @param
+ * the entity type
+ */
+public interface EntityBulkEvent extends Serializable, Event {
+
+ /**
+ * A typesafe way to retrieve the the entities from the event, which might
+ * be loaded lazy in case the event has been distributed from another node.
+ *
+ * @return the entities 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
+ */
+ List getEntities();
+}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetAssignDistributionSetEvent.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetAssignDistributionSetEvent.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetCreatedEvent.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetCreatedEvent.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetInfoUpdateEvent.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetInfoUpdateEvent.java
old mode 100755
new mode 100644
index 1119026bd..563bb4bdc
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetInfoUpdateEvent.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetInfoUpdateEvent.java
@@ -11,9 +11,7 @@ package org.eclipse.hawkbit.eventbus.event;
import org.eclipse.hawkbit.repository.model.TargetInfo;
/**
- *
- *
- *
+ * Event for update the targets info.
*/
public class TargetInfoUpdateEvent implements EntityEvent {
@@ -24,6 +22,8 @@ public class TargetInfoUpdateEvent implements EntityEvent {
private String nodeId;
/**
+ * Constructor.
+ *
* @param targetInfo
* the target info entity
*/
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetTagAssigmentResultEvent.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetTagAssigmentResultEvent.java
new file mode 100644
index 000000000..405595de0
--- /dev/null
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetTagAssigmentResultEvent.java
@@ -0,0 +1,34 @@
+/**
+ * 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 org.eclipse.hawkbit.repository.model.TargetTagAssigmentResult;
+
+/**
+ * A event for assignment target tag.
+ */
+public class TargetTagAssigmentResultEvent {
+
+ private final TargetTagAssigmentResult assigmentResult;
+
+ /**
+ * Constructor.
+ *
+ * @param assigmentResult
+ * the assignment result-
+ */
+ public TargetTagAssigmentResultEvent(final TargetTagAssigmentResult assigmentResult) {
+ this.assigmentResult = assigmentResult;
+ }
+
+ public TargetTagAssigmentResult getAssigmentResult() {
+ return assigmentResult;
+ }
+
+}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetTagCreatedBulkEvent.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetTagCreatedBulkEvent.java
new file mode 100644
index 000000000..c66a5150e
--- /dev/null
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetTagCreatedBulkEvent.java
@@ -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.eventbus.event;
+
+import java.util.List;
+
+import org.eclipse.hawkbit.repository.model.TargetTag;
+
+/**
+ * A bulk event which contains one or many new target tags after creating.
+ */
+public class TargetTagCreatedBulkEvent extends AbstractEntityBulkEvent {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor.
+ *
+ * @param tenant
+ * the tenant
+ * @param entities
+ * the new targets
+ */
+ public TargetTagCreatedBulkEvent(final String tenant, final List entities) {
+ super(tenant, entities);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param tenant
+ * the tenant
+ * @param entity
+ * one new target
+ */
+ public TargetTagCreatedBulkEvent(final String tenant, final TargetTag entity) {
+ super(tenant, entity);
+ }
+
+}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetTagDeletedEvent.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetTagDeletedEvent.java
new file mode 100644
index 000000000..040fbc19a
--- /dev/null
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetTagDeletedEvent.java
@@ -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.eventbus.event;
+
+import org.eclipse.hawkbit.repository.model.TargetTag;
+
+/**
+ * Defines the {@link AbstractBaseEntityEvent} of update a {@link TargetTag}.
+ *
+ */
+public class TargetTagDeletedEvent extends AbstractBaseEntityEvent {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor.
+ *
+ * @param tag
+ * the tag which is deleted
+ */
+ public TargetTagDeletedEvent(final TargetTag tag) {
+ super(tag);
+ }
+}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetTagUpdateEvent.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetTagUpdateEvent.java
new file mode 100644
index 000000000..4562063aa
--- /dev/null
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetTagUpdateEvent.java
@@ -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.eventbus.event;
+
+import org.eclipse.hawkbit.repository.model.TargetTag;
+
+/**
+ * Defines the {@link AbstractBaseEntityEvent} for update a {@link TargetTag}.
+ *
+ */
+public class TargetTagUpdateEvent extends AbstractBaseEntityEvent {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor.
+ *
+ * @param tag
+ * the tag which is updated
+ */
+ public TargetTagUpdateEvent(final TargetTag tag) {
+ super(tag);
+ }
+}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/executor/AfterTransactionCommitDefaultServiceExecutor.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/executor/AfterTransactionCommitDefaultServiceExecutor.java
new file mode 100644
index 000000000..9b66178ba
--- /dev/null
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/executor/AfterTransactionCommitDefaultServiceExecutor.java
@@ -0,0 +1,69 @@
+/**
+ * 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.executor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.support.TransactionSynchronizationAdapter;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+/**
+ *
+ * A Service which calls register runnable. This runnables will executed after a
+ * successful spring transaction commit.The class is thread safe.
+ */
+@Service
+public class AfterTransactionCommitDefaultServiceExecutor extends TransactionSynchronizationAdapter implements
+ AfterTransactionCommitExecutor {
+ private static final Logger LOGGER = LoggerFactory.getLogger(AfterTransactionCommitDefaultServiceExecutor.class);
+ private static final ThreadLocal> THREAD_LOCAL_RUNNABLES = new ThreadLocal<>();
+
+ @Override
+ public void afterCommit() {
+ final List afterCommitRunnables = THREAD_LOCAL_RUNNABLES.get();
+ LOGGER.debug("Transaction successfully committed, executing {} runnables", afterCommitRunnables.size());
+ for (final Runnable afterCommitRunnable : afterCommitRunnables) {
+ LOGGER.debug("Executing runnable {}", afterCommitRunnable);
+ try {
+ afterCommitRunnable.run();
+ } catch (final RuntimeException e) {
+ LOGGER.error("Failed to execute runnable " + afterCommitRunnable, e);
+ }
+ }
+ }
+
+ @Override
+ public void afterCommit(final Runnable runnable) {
+ LOGGER.debug("Submitting new runnable {} to run after transaction commit", runnable);
+ if (TransactionSynchronizationManager.isSynchronizationActive()) {
+ List localRunnables = THREAD_LOCAL_RUNNABLES.get();
+ if (localRunnables == null) {
+ localRunnables = new ArrayList<>();
+ THREAD_LOCAL_RUNNABLES.set(localRunnables);
+ TransactionSynchronizationManager.registerSynchronization(this);
+ }
+ localRunnables.add(runnable);
+ return;
+ }
+ LOGGER.info("Transaction synchronization is NOT ACTIVE/ INACTIVE. Executing right now runnable {}", runnable);
+ runnable.run();
+ }
+
+ @Override
+ public void afterCompletion(final int status) {
+ final String transactionStatus = status == STATUS_COMMITTED ? "COMMITTED" : "ROLLEDBACK";
+ LOGGER.debug("Transaction completed after commit with status {}", transactionStatus);
+ THREAD_LOCAL_RUNNABLES.remove();
+ }
+
+}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/executor/AfterTransactionCommitExecutor.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/executor/AfterTransactionCommitExecutor.java
new file mode 100644
index 000000000..ab5c67bab
--- /dev/null
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/executor/AfterTransactionCommitExecutor.java
@@ -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.executor;
+
+/**
+ *
+ * A interface to register a runnable, which will be executed after a successful
+ * spring transaction.
+ *
+ */
+@FunctionalInterface
+public interface AfterTransactionCommitExecutor {
+
+ /**
+ * Register a runnable which will be executed after a successful spring
+ * transaction.
+ *
+ * @param runnable
+ * the after commit runnable
+ */
+ void afterCommit(Runnable runnable);
+}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/report/model/AbstractReportSeries.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/report/model/AbstractReportSeries.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/report/model/DataReportSeries.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/report/model/DataReportSeries.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/report/model/DataReportSeriesItem.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/report/model/DataReportSeriesItem.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/report/model/InnerOuterDataReportSeries.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/report/model/InnerOuterDataReportSeries.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/report/model/ListReportSeries.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/report/model/ListReportSeries.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/report/model/SeriesTime.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/report/model/SeriesTime.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/report/model/SystemUsageReport.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/report/model/SystemUsageReport.java
new file mode 100644
index 000000000..45cc60cba
--- /dev/null
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/report/model/SystemUsageReport.java
@@ -0,0 +1,95 @@
+/**
+ * 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.report.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Bean for holding the system usage stats.
+ *
+ */
+public class SystemUsageReport {
+ private final long overallTargets;
+ private final long overallArtifacts;
+ private final long overallArtifactVolumeInBytes;
+ private final long overallActions;
+
+ private final List tenants = new ArrayList<>();
+
+ /**
+ * Constructor.
+ *
+ * @param overallTargets
+ * of the system
+ * @param overallArtifacts
+ * of the system
+ * @param overallActions
+ * of the system
+ * @param overallArtifactVolumeInBytes
+ * of the system
+ */
+ public SystemUsageReport(final long overallTargets, final long overallArtifacts, final long overallActions,
+ final long overallArtifactVolumeInBytes) {
+ super();
+ this.overallTargets = overallTargets;
+ this.overallArtifacts = overallArtifacts;
+ this.overallActions = overallActions;
+
+ this.overallArtifactVolumeInBytes = overallArtifactVolumeInBytes;
+ }
+
+ /**
+ * @return overallTargets in the system
+ */
+ public long getOverallTargets() {
+ return overallTargets;
+ }
+
+ /**
+ * @return overallArtifacts in the system
+ */
+ public long getOverallArtifacts() {
+ return overallArtifacts;
+ }
+
+ /**
+ * @return overallArtifactVolumeInBytes of the system
+ */
+ public long getOverallArtifactVolumeInBytes() {
+ return overallArtifactVolumeInBytes;
+ }
+
+ /**
+ * @param tenantUsage
+ * of one tenant
+ * @return updated bean
+ */
+ public SystemUsageReport addTenantData(final TenantUsage tenantUsage) {
+ tenants.add(tenantUsage);
+ return this;
+ }
+
+ /**
+ * @return actions of system
+ */
+ public long getOverallActions() {
+ return overallActions;
+ }
+
+ /**
+ * @return tenant data
+ */
+ public List getTenants() {
+ return ImmutableList.copyOf(tenants);
+ }
+
+}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/report/model/TenantUsage.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/report/model/TenantUsage.java
new file mode 100644
index 000000000..d0ee7102c
--- /dev/null
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/report/model/TenantUsage.java
@@ -0,0 +1,161 @@
+/**
+ * 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.report.model;
+
+/**
+ * System usage stats element for a tenant.
+ *
+ */
+public class TenantUsage {
+
+ private final String tenantName;
+ private long targets;
+ private long artifacts;
+ private long actions;
+ private long overallArtifactVolumeInBytes;
+
+ /**
+ * Constructor.
+ *
+ * @param tenantName
+ */
+ public TenantUsage(final String tenantName) {
+ super();
+ this.tenantName = tenantName;
+ }
+
+ /**
+ * @return name of the tenant
+ */
+ public String getTenantName() {
+ return tenantName;
+ }
+
+ /**
+ * @return number of targets of the tenant
+ */
+ public long getTargets() {
+ return targets;
+ }
+
+ /**
+ * @param targets
+ * of the tenant
+ * @return updated tenant stats element
+ */
+ public TenantUsage setTargets(final long targets) {
+ this.targets = targets;
+ return this;
+ }
+
+ /**
+ * @return number of undeleted artifacts of the tenant
+ */
+ public long getArtifacts() {
+ return artifacts;
+ }
+
+ /**
+ * @param artifacts
+ * of tenant
+ * @return updated tenant stats element
+ */
+ public TenantUsage setArtifacts(final long artifacts) {
+ this.artifacts = artifacts;
+ return this;
+ }
+
+ /**
+ * @return current overallArtifactVolumeInBytes
+ */
+ public long getOverallArtifactVolumeInBytes() {
+ return overallArtifactVolumeInBytes;
+ }
+
+ /**
+ * @param overallArtifactVolumeInBytes
+ * of the tenant in bytes
+ * @return updated tenant stats element
+ */
+ public TenantUsage setOverallArtifactVolumeInBytes(final long overallArtifactVolumeInBytes) {
+ this.overallArtifactVolumeInBytes = overallArtifactVolumeInBytes;
+ return this;
+ }
+
+ /**
+ * @return number of actions of tenant
+ */
+ public long getActions() {
+ return actions;
+ }
+
+ /**
+ * @param actions
+ * of the tenant
+ * @return updated tenant stats element
+ */
+ public TenantUsage setActions(final long actions) {
+ this.actions = actions;
+ return this;
+ }
+
+ @Override
+ public int hashCode() { // NOSONAR - as this is generated code
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (actions ^ (actions >>> 32));
+ result = prime * result + (int) (artifacts ^ (artifacts >>> 32));
+ result = prime * result + (int) (overallArtifactVolumeInBytes ^ (overallArtifactVolumeInBytes >>> 32));
+ result = prime * result + (int) (targets ^ (targets >>> 32));
+ result = prime * result + ((tenantName == null) ? 0 : tenantName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) { // NOSONAR - as this is generated
+ // code
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final TenantUsage other = (TenantUsage) obj;
+ if (actions != other.actions) {
+ return false;
+ }
+ if (artifacts != other.artifacts) {
+ return false;
+ }
+ if (overallArtifactVolumeInBytes != other.overallArtifactVolumeInBytes) {
+ return false;
+ }
+ if (targets != other.targets) {
+ return false;
+ }
+ if (tenantName == null) {
+ if (other.tenantName != null) {
+ return false;
+ }
+ } else if (!tenantName.equals(other.tenantName)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "SystemUsage [tenantName=" + tenantName + ", targets=" + targets + ", artifacts=" + artifacts
+ + ", actions=" + actions + ", overallArtifactVolumeInBytes=" + overallArtifactVolumeInBytes + "]";
+ }
+
+}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ActionRepository.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ActionRepository.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ActionStatusRepository.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ActionStatusRepository.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/BaseEntityRepository.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/BaseEntityRepository.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java
old mode 100755
new mode 100644
index 55ed458ec..844bbd097
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java
@@ -11,7 +11,6 @@ package org.eclipse.hawkbit.repository;
import java.net.URI;
import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
@@ -135,8 +134,8 @@ public class ControllerManagement implements EnvironmentAware {
final List action = actionRepository.findActionByTargetAndSoftwareModule(targetId, module);
if (action.isEmpty() || action.get(0).isCancelingOrCanceled()) {
- throw new EntityNotFoundException("No assigment found for module " + module.getId() + " to target "
- + targetId);
+ throw new EntityNotFoundException(
+ "No assigment found for module " + module.getId() + " to target " + targetId);
}
return action.get(0);
@@ -270,22 +269,20 @@ public class ControllerManagement implements EnvironmentAware {
}
/**
- * Reports an {@link ActionStatus} for a {@link CancelAction}.
- *
- * @param actionStatusMessages
+ * Adds an {@link ActionStatus} for a {@link UpdateAction} and cancels the
+ * {@link UpdateAction} if necessary.
+ *
+ * @param actionStatus
* to be updated
- * @param target2
- *
- * @throws EntityAlreadyExistsException
- * if a given entity already exists
- * @throws ToManyStatusEntriesException
- * if more than the allowed number of status entries are
- * inserted
+ * @param action
+ * the status is for
+ * @return the persisted {@link Action}
+ *
*/
@Modifying
@Transactional
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
- public void addCancelActionStatus(@NotNull final ActionStatus actionStatus, final Action action) {
+ public Action addCancelActionStatus(@NotNull final ActionStatus actionStatus, final Action action) {
checkForToManyStatusEntries(action);
action.setStatus(actionStatus.getStatus());
@@ -298,12 +295,9 @@ public class ControllerManagement implements EnvironmentAware {
case CANCELED:
case FINISHED:
// in case of successful cancelation we also report the success at
- // the canceled action
- // itself.
+ // the canceled action itself.
actionStatus.addMessage("Cancelation completion is finished sucessfully.");
- // set action inactive
- action.setActive(false);
- successCancellation(action);
+ deploymentManagement.successCancellation(action);
break;
case RETRIEVED:
actionStatus.addMessage("Cancelation request retrieved");
@@ -312,30 +306,18 @@ public class ControllerManagement implements EnvironmentAware {
}
actionRepository.save(action);
actionStatusRepository.save(actionStatus);
- }
- private void successCancellation(final Action action) {
- final Target target = action.getTarget();
- final List nextActiveActions = actionRepository.findByTargetAndActiveOrderByIdAsc(target, true)
- .stream().filter(a -> !a.getId().equals(action.getId())).collect(Collectors.toList());
-
- if (nextActiveActions.isEmpty()) {
- target.setAssignedDistributionSet(target.getTargetInfo().getInstalledDistributionSet());
- deploymentManagement.updateTargetInfo(target, TargetUpdateStatus.IN_SYNC, false);
- } else {
- target.setAssignedDistributionSet(nextActiveActions.get(0).getDistributionSet());
- }
- targetManagement.updateTarget(target);
+ return action;
}
/**
- * Reports an {@link ActionStatus} for a {@link UpdateAction}.
+ * Updates an {@link ActionStatus} for a {@link UpdateAction}.
*
* @param actionStatus
* to be updated
* @param action
* the update is for
- * @return the persisted {@link ActionStatus}
+ * @return the persisted {@link Action}
*
* @throws EntityAlreadyExistsException
* if a given entity already exists
@@ -420,8 +402,8 @@ public class ControllerManagement implements EnvironmentAware {
final TargetInfo targetInfo = target.getTargetInfo();
final DistributionSet ds = entityManager.merge(action.getDistributionSet());
targetInfo.setInstalledDistributionSet(ds);
- if (target.getAssignedDistributionSet() != null && targetInfo.getInstalledDistributionSet() != null
- && target.getAssignedDistributionSet().getId().equals(targetInfo.getInstalledDistributionSet().getId())) {
+ if (target.getAssignedDistributionSet() != null && targetInfo.getInstalledDistributionSet() != null && target
+ .getAssignedDistributionSet().getId().equals(targetInfo.getInstalledDistributionSet().getId())) {
targetInfo.setUpdateStatus(TargetUpdateStatus.IN_SYNC);
targetInfo.setInstallationDate(System.currentTimeMillis());
} else {
@@ -461,8 +443,7 @@ public class ControllerManagement implements EnvironmentAware {
target.getTargetInfo().getControllerAttributes().putAll(data);
if (target.getTargetInfo().getControllerAttributes().size() > maxAttributes) {
- LOG_DOS.info(
- "Target tries to insert more than the allowed number of entries ({}). DOS attack anticipated!",
+ LOG_DOS.info("Target tries to insert more than the allowed number of entries ({}). DOS attack anticipated!",
maxAttributes);
throw new ToManyAttributeEntriesException(String.valueOf(maxAttributes));
}
@@ -474,7 +455,7 @@ public class ControllerManagement implements EnvironmentAware {
/*
* (non-Javadoc)
- *
+ *
* @see org.springframework.context.EnvironmentAware#setEnvironment(org.
* springframework.core.env. Environment)
*/
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java
old mode 100755
new mode 100644
index adfb3beb2..0288c83a5
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java
@@ -28,10 +28,14 @@ import javax.persistence.criteria.Root;
import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.Constants;
+import org.eclipse.hawkbit.eventbus.event.CancelTargetAssignmentEvent;
+import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent;
+import org.eclipse.hawkbit.eventbus.event.TargetInfoUpdateEvent;
+import org.eclipse.hawkbit.executor.AfterTransactionCommitExecutor;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
-import org.eclipse.hawkbit.repository.event.DeploymentManagementEvents;
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
+import org.eclipse.hawkbit.repository.exception.ForceQuitActionNotAllowedException;
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
@@ -65,6 +69,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import com.google.common.collect.Lists;
+import com.google.common.eventbus.EventBus;
/**
* Business service facade for managing all deployment related data and actions.
@@ -105,11 +110,14 @@ public class DeploymentManagement {
private AuditorAware auditorProvider;
@Autowired
- private DeploymentManagementEvents deploymentManagementEvents;
+ private EventBus eventBus;
+
+ @Autowired
+ private AfterTransactionCommitExecutor afterCommit;
/**
* method assigns the {@link DistributionSet} to all {@link Target}s.
- *
+ *
* @param pset
* {@link DistributionSet} which is assigned to the
* {@link Target}s
@@ -139,7 +147,7 @@ public class DeploymentManagement {
/**
* method assigns the {@link DistributionSet} to all {@link Target}s by
* their IDs.
- *
+ *
* @param dsID
* {@link DistributionSet} which is assigned to the
* {@link Target}s
@@ -168,7 +176,7 @@ public class DeploymentManagement {
/**
* method assigns the {@link DistributionSet} to all {@link Target}s by
* their IDs with a specific {@link ActionType} and {@code forcetime}.
- *
+ *
* @param dsID
* the ID of the distribution set to assign
* @param actionType
@@ -190,14 +198,16 @@ public class DeploymentManagement {
@CacheEvict(value = { "distributionUsageAssigned" }, allEntries = true)
public DistributionSetAssignmentResult assignDistributionSet(@NotNull final Long dsID, final ActionType actionType,
final long forcedTimestamp, @NotEmpty final String... targetIDs) {
- return assignDistributionSet(dsID, Arrays.stream(targetIDs)
- .map(t -> new TargetWithActionType(t, actionType, forcedTimestamp)).collect(Collectors.toList()));
+ return assignDistributionSet(
+ dsID,
+ Arrays.stream(targetIDs).map(t -> new TargetWithActionType(t, actionType, forcedTimestamp))
+ .collect(Collectors.toList()));
}
/**
* method assigns the {@link DistributionSet} to all {@link Target}s by
* their IDs with a specific {@link ActionType} and {@code forcetime}.
- *
+ *
* @param dsID
* the ID of the distribution set to assign
* @param targets
@@ -216,8 +226,8 @@ public class DeploymentManagement {
final List targets) {
final DistributionSet set = distributoinSetRepository.findOne(dsID);
if (set == null) {
- throw new EntityNotFoundException(
- String.format("no %s with id %d found", DistributionSet.class.getSimpleName(), dsID));
+ throw new EntityNotFoundException(String.format("no %s with id %d found",
+ DistributionSet.class.getSimpleName(), dsID));
}
return assignDistributionSetToTargets(set, targets);
@@ -226,7 +236,7 @@ public class DeploymentManagement {
/**
* method assigns the {@link DistributionSet} to all {@link Target}s by
* their IDs with a specific {@link ActionType} and {@code forcetime}.
- *
+ *
* @param dsID
* the ID of the distribution set to assign
* @param targetsWithActionType
@@ -241,8 +251,8 @@ public class DeploymentManagement {
final List targetsWithActionType) {
if (!set.isComplete()) {
- throw new IncompleteDistributionSetException(
- "Distribution set of type " + set.getType().getKey() + " is incomplete: " + set.getId());
+ throw new IncompleteDistributionSetException("Distribution set of type " + set.getType().getKey()
+ + " is incomplete: " + set.getId());
}
final List controllerIDs = targetsWithActionType.stream().map(TargetWithActionType::getTargetId)
@@ -250,8 +260,8 @@ public class DeploymentManagement {
LOG.debug("assignDistribution({}) to {} targets", set, controllerIDs.size());
- final Map targetsWithActionMap = targetsWithActionType.stream()
- .collect(Collectors.toMap(TargetWithActionType::getTargetId, Function.identity()));
+ final Map targetsWithActionMap = targetsWithActionType.stream().collect(
+ Collectors.toMap(TargetWithActionType::getTargetId, Function.identity()));
// split tIDs length into max entries in-statement because many database
// have constraint of
@@ -261,10 +271,12 @@ public class DeploymentManagement {
// we take the target only into account if the requested operation is no
// duplicate of a
// previous one
- final List targets = Lists.partition(controllerIDs, Constants.MAX_ENTRIES_IN_STATEMENT).stream()
- .map(ids -> targetRepository
- .findAll(TargetSpecifications.hasControllerIdAndAssignedDistributionSetIdNot(ids, set.getId())))
- .flatMap(t -> t.stream()).collect(Collectors.toList());
+ final List targets = Lists
+ .partition(controllerIDs, Constants.MAX_ENTRIES_IN_STATEMENT)
+ .stream()
+ .map(ids -> targetRepository.findAll(TargetSpecifications
+ .hasControllerIdAndAssignedDistributionSetIdNot(ids, set.getId()))).flatMap(t -> t.stream())
+ .collect(Collectors.toList());
if (targets.isEmpty()) {
// detaching as it is not necessary to persist the set itself
@@ -327,8 +339,8 @@ public class DeploymentManagement {
});
// select updated targets in order to return them
- final DistributionSetAssignmentResult result = new DistributionSetAssignmentResult(
- targets.stream().map(target -> target.getControllerId()).collect(Collectors.toList()), targets.size(),
+ final DistributionSetAssignmentResult result = new DistributionSetAssignmentResult(targets.stream()
+ .map(target -> target.getControllerId()).collect(Collectors.toList()), targets.size(),
controllerIDs.size() - targets.size(), Lists.newArrayList(targetIdsToActions.values()),
targetManagement);
@@ -340,16 +352,40 @@ public class DeploymentManagement {
entityManager.detach(set);
// send distribution set assignment event
- targets.stream().filter(t -> !!!targetIdsCancellList.contains(t.getId()))
- .forEach(t -> deploymentManagementEvents.assignDistributionSet(t,
- targetIdsToActions.get(t.getControllerId()).getId(), softwareModules));
+
+ targets.stream()
+ .filter(t -> !!!targetIdsCancellList.contains(t.getId()))
+ .forEach(
+ t -> assignDistributionSetEvent(t, targetIdsToActions.get(t.getControllerId()).getId(),
+ softwareModules));
return result;
}
+ /**
+ * Sends the {@link TargetAssignDistributionSetEvent} for a specific target
+ * to the {@link EventBus}.
+ *
+ * @param target
+ * the Target which has been assigned to a distribution set
+ * @param actionId
+ * the action id of the assignment
+ * @param softwareModules
+ * the software modules which have been assigned
+ */
+ private void assignDistributionSetEvent(final Target target, final Long actionId,
+ final List softwareModules) {
+ target.getTargetInfo().setUpdateStatus(TargetUpdateStatus.PENDING);
+ afterCommit.afterCommit(() -> {
+ eventBus.post(new TargetInfoUpdateEvent(target.getTargetInfo()));
+ eventBus.post(new TargetAssignDistributionSetEvent(target.getControllerId(), actionId, softwareModules,
+ target.getTargetInfo().getAddress()));
+ });
+ }
+
/**
* Removes {@link UpdateAction}s that are no longer necessary and sends
- * cancelations to the controller.
+ * cancellations to the controller.
*
* @param myTarget
* to override {@link UpdateAction}s
@@ -360,18 +396,20 @@ public class DeploymentManagement {
// Figure out if there are potential target/action combinations that
// need to be considered
- // for cancelation
+ // for cancellation
final List activeActions = actionRepository
.findByActiveAndTargetIdInAndActionStatusNotEqualToAndDistributionSetRequiredMigrationStep(targetsIds,
Action.Status.CANCELING);
activeActions.forEach(action -> {
action.setStatus(Status.CANCELING);
// document that the status has been retrieved
- actionStatusRepository.save(new ActionStatus(action, Status.CANCELING, System.currentTimeMillis(),
- "manual cancelation requested"));
- deploymentManagementEvents.cancalAssignDistributionSet(action.getTarget(), action.getId());
- cancelledTargetIds.add(action.getTarget().getId());
- });
+ actionStatusRepository.save(new ActionStatus(action, Status.CANCELING, System.currentTimeMillis(),
+ "manual cancelation requested"));
+
+ cancelAssignDistributionSetEvent(action.getTarget(), action.getId());
+
+ cancelledTargetIds.add(action.getTarget().getId());
+ });
actionRepository.save(activeActions);
return cancelledTargetIds;
@@ -379,8 +417,9 @@ public class DeploymentManagement {
private DistributionSetAssignmentResult assignDistributionSetByTargetId(@NotNull final DistributionSet set,
@NotEmpty final List tIDs, final ActionType actionType, final long forcedTime) {
- return assignDistributionSetToTargets(set, tIDs.stream()
- .map(t -> new TargetWithActionType(t, actionType, forcedTime)).collect(Collectors.toList()));
+ return assignDistributionSetToTargets(set,
+ tIDs.stream().map(t -> new TargetWithActionType(t, actionType, forcedTime))
+ .collect(Collectors.toList()));
}
/**
@@ -442,19 +481,77 @@ public class DeploymentManagement {
// document that the status has been retrieved
actionStatusRepository.save(new ActionStatus(myAction, Status.CANCELING, System.currentTimeMillis(),
"manual cancelation requested"));
+ final Action saveAction = actionRepository.save(myAction);
- deploymentManagementEvents.cancalAssignDistributionSet(target, myAction.getId());
+ cancelAssignDistributionSetEvent(target, myAction.getId());
- return actionRepository.save(myAction);
+ return saveAction;
} else {
- throw new CancelActionNotAllowedException(
- "Action [id: " + action.getId() + "] is not active and cannot be canceled");
+ throw new CancelActionNotAllowedException("Action [id: " + action.getId()
+ + "] is not active and cannot be canceled");
}
}
/**
- * Get the {@link Action} entity for given actionId.
+ * Sends the {@link CancelTargetAssignmentEvent} for a specific target to
+ * the {@link EventBus}.
*
+ * @param target
+ * the Target which has been assigned to a distribution set
+ * @param actionId
+ * the action id of the assignment
+ */
+ private void cancelAssignDistributionSetEvent(final Target target, final Long actionId) {
+ afterCommit.afterCommit(() -> eventBus.post(new CancelTargetAssignmentEvent(target.getControllerId(), actionId,
+ target.getTargetInfo().getAddress())));
+ }
+
+ /**
+ * Force cancels given {@link Action} for given {@link Target}. Force
+ * canceling means that the action is marked as canceled on the SP server
+ * and a cancel request is sent to the target. But however it's not tracked,
+ * if the targets handles the cancel request or not.
+ *
+ * @param action
+ * to be canceled
+ * @param target
+ * for which the action needs cancellation
+ *
+ * @return generated {@link CancelAction} or null if not in
+ * {@link Target#getActiveActions()}.
+ * @throws CancelActionNotAllowedException
+ * in case the given action is not active
+ */
+ @Modifying
+ @Transactional
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
+ public Action forceQuitAction(@NotNull final Action action, @NotNull final Target target) {
+ final Action mergedAction = entityManager.merge(action);
+
+ if (!mergedAction.isCancelingOrCanceled()) {
+ throw new ForceQuitActionNotAllowedException("Action [id: " + action.getId()
+ + "] is not canceled yet and cannot be force quit");
+ }
+
+ if (!mergedAction.isActive()) {
+ throw new ForceQuitActionNotAllowedException("Action [id: " + action.getId()
+ + "] is not active and cannot be force quit");
+ }
+
+ LOG.warn("action ({}) was still activ and has been force quite.", action);
+
+ // document that the status has been retrieved
+ actionStatusRepository.save(new ActionStatus(mergedAction, Status.CANCELED, System.currentTimeMillis(),
+ "A force quit has been performed."));
+
+ successCancellation(mergedAction);
+
+ return actionRepository.save(mergedAction);
+ }
+
+ /**
+ * Get the {@link Action} entity for given actionId.
+ *
* @param actionId
* to be id of the action
* @return the corresponding {@link Action}
@@ -467,7 +564,7 @@ public class DeploymentManagement {
/**
* Get the {@link Action} entity for given actionId with all lazy
* attributes.
- *
+ *
* @param actionId
* to be id of the action
* @return the corresponding {@link Action}
@@ -493,7 +590,7 @@ public class DeploymentManagement {
/**
* Retrieves all {@link Action}s of a specific target ordered by action ID.
- *
+ *
* @param target
* the target associated with the actions
* @return a list of actions associated with the given target ordered by
@@ -506,7 +603,7 @@ public class DeploymentManagement {
/**
* Retrieves all {@link Action}s of a specific target ordered by action ID.
- *
+ *
* @param target
* the target associated with the actions
* @return a list of actions associated with the given target ordered by
@@ -536,7 +633,7 @@ public class DeploymentManagement {
/**
* Retrieves all {@link Action}s assigned to a specific {@link Target} and a
* given specification.
- *
+ *
* @param specifiction
* the specification to narrow down the search
* @param target
@@ -553,17 +650,21 @@ public class DeploymentManagement {
return actionRepository.findAll(new Specification() {
@Override
- public Predicate toPredicate(final Root root, final CriteriaQuery> query,
- final CriteriaBuilder cb) {
+ public Predicate toPredicate(final Root root, final CriteriaQuery> query, final CriteriaBuilder cb) {
return cb.and(specifiction.toPredicate(root, query, cb), cb.equal(root.get(Action_.target), target));
}
}, pageable);
}
/**
- * @param foundTarget
+ * Retrieves all {@link Action}s which are referring the given
+ * {@link Target}.
+ *
* @param pageable
- * @return
+ * page parameters
+ * @param foundTarget
+ * the target to find assigned actions
+ * @return the found {@link Action}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
public Slice findActionsByTarget(final Target foundTarget, final Pageable pageable) {
@@ -573,7 +674,7 @@ public class DeploymentManagement {
/**
* Retrieves all active {@link Action}s of a specific target ordered by
* action ID.
- *
+ *
* @param pageable
* the pagination parameter
* @param target
@@ -588,7 +689,7 @@ public class DeploymentManagement {
/**
* Retrieves all active {@link Action}s of a specific target ordered by
* action ID.
- *
+ *
* @param target
* the target associated with the actions
* @return a list of actions associated with the given target
@@ -601,7 +702,7 @@ public class DeploymentManagement {
/**
* Retrieves all inactive {@link Action}s of a specific target ordered by
* action ID.
- *
+ *
* @param target
* the target associated with the actions
* @return a list of actions associated with the given target
@@ -614,7 +715,7 @@ public class DeploymentManagement {
/**
* Retrieves all inactive {@link Action}s of a specific target ordered by
* action ID.
- *
+ *
* @param pageable
* the pagination parameter
* @param target
@@ -628,7 +729,7 @@ public class DeploymentManagement {
/**
* counts all actions associated to a specific target.
- *
+ *
* @param target
* the target associated to the actions to count
* @return the count value of found actions associated to the target
@@ -640,7 +741,7 @@ public class DeploymentManagement {
/**
* counts all actions associated to a specific target.
- *
+ *
* @param spec
* the specification to filter the count result
* @param target
@@ -651,8 +752,7 @@ public class DeploymentManagement {
public Long countActionsByTarget(@NotNull final Specification spec, @NotNull final Target target) {
return actionRepository.count(new Specification() {
@Override
- public Predicate toPredicate(final Root root, final CriteriaQuery> query,
- final CriteriaBuilder cb) {
+ public Predicate toPredicate(final Root root, final CriteriaQuery> query, final CriteriaBuilder cb) {
return cb.and(spec.toPredicate(root, query, cb), cb.equal(root.get(Action_.target), target));
}
});
@@ -683,7 +783,7 @@ public class DeploymentManagement {
/**
* retrieves all the {@link ActionStatus} entries of the given
* {@link Action} and {@link Target} in the order latest first.
- *
+ *
* @param pageReq
* pagination parameter
* @param action
@@ -703,4 +803,30 @@ public class DeploymentManagement {
}
}
+ /**
+ * This method is called, when cancellation has been successful. It sets the
+ * action to canceled, resets the meta data of the target and in case there
+ * is a new action this action is triggered.
+ *
+ * @param action
+ * the action which is set to canceled
+ */
+ void successCancellation(final Action action) {
+
+ // set action inactive
+ action.setActive(false);
+ action.setStatus(Status.CANCELED);
+
+ final Target target = action.getTarget();
+ final List nextActiveActions = actionRepository.findByTargetAndActiveOrderByIdAsc(target, true)
+ .stream().filter(a -> !a.getId().equals(action.getId())).collect(Collectors.toList());
+
+ if (nextActiveActions.isEmpty()) {
+ target.setAssignedDistributionSet(target.getTargetInfo().getInstalledDistributionSet());
+ updateTargetInfo(target, TargetUpdateStatus.IN_SYNC, false);
+ } else {
+ target.setAssignedDistributionSet(nextActiveActions.get(0).getDistributionSet());
+ }
+ targetManagement.updateTarget(target);
+ }
}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetAssignmentResult.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetAssignmentResult.java
old mode 100755
new mode 100644
index d80667024..ac562131d
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetAssignmentResult.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetAssignmentResult.java
@@ -11,6 +11,7 @@ package org.eclipse.hawkbit.repository;
import java.util.List;
import org.eclipse.hawkbit.repository.model.Action;
+import org.eclipse.hawkbit.repository.model.AssignmentResult;
import org.eclipse.hawkbit.repository.model.Target;
/**
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetFilter.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetFilter.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java
old mode 100755
new mode 100644
index e962978a4..d4b7ac55e
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java
@@ -11,7 +11,9 @@ package org.eclipse.hawkbit.repository;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
@@ -26,6 +28,8 @@ import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.validation.constraints.NotNull;
+import org.eclipse.hawkbit.eventbus.event.DistributionSetTagAssigmentResultEvent;
+import org.eclipse.hawkbit.executor.AfterTransactionCommitExecutor;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.DistributionSetFilter.DistributionSetFilterBuilder;
import org.eclipse.hawkbit.repository.exception.DistributionSetCreationFailedMissingMandatoryModuleException;
@@ -38,6 +42,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata_;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
+import org.eclipse.hawkbit.repository.model.DistributionSetTagAssigmentResult;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.DistributionSetTypeElement;
import org.eclipse.hawkbit.repository.model.DistributionSet_;
@@ -62,6 +67,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import com.google.common.base.Strings;
+import com.google.common.eventbus.EventBus;
/**
* Business facade for managing the {@link DistributionSet}s.
@@ -96,6 +102,12 @@ public class DistributionSetManagement {
@Autowired
private ActionRepository actionRepository;
+ @Autowired
+ private EventBus eventBus;
+
+ @Autowired
+ private AfterTransactionCommitExecutor afterCommit;
+
/**
* Find {@link DistributionSet} based on given ID including (lazy loaded)
* details, e.g. {@link DistributionSet#getAgentHub()}.
@@ -183,13 +195,16 @@ public class DistributionSetManagement {
allDSs.add(set);
}
}
- result = new DistributionSetTagAssigmentResult(dsIds.size() - allDSs.size(), 0, allDSs.size(), null,
- distributionSetRepository.save(allDSs));
+ result = new DistributionSetTagAssigmentResult(dsIds.size() - allDSs.size(), 0, allDSs.size(),
+ Collections.emptyList(), distributionSetRepository.save(allDSs), myTag);
} else {
result = new DistributionSetTagAssigmentResult(dsIds.size() - allDSs.size(), allDSs.size(), 0,
- distributionSetRepository.save(allDSs), null);
+ distributionSetRepository.save(allDSs), Collections.emptyList(), myTag);
}
+ final DistributionSetTagAssigmentResult resultAssignment = result;
+ afterCommit.afterCommit(() -> eventBus.post(new DistributionSetTagAssigmentResultEvent(resultAssignment)));
+
// no reason to persist the tag
entityManager.detach(myTag);
return result;
@@ -204,8 +219,7 @@ public class DistributionSetManagement {
* @return the found {@link DistributionSet}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
- public List findDistributionSetListWithDetails(
- @NotEmpty final Collection distributionIdSet) {
+ public List findDistributionSetListWithDetails(@NotEmpty final Collection distributionIdSet) {
return distributionSetRepository.findAll(DistributionSetSpecification.byIds(distributionIdSet));
}
@@ -383,8 +397,7 @@ public class DistributionSetManagement {
@Modifying
@Transactional
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
- public DistributionSet unassignSoftwareModule(@NotNull final DistributionSet ds,
- final SoftwareModule softwareModule) {
+ public DistributionSet unassignSoftwareModule(@NotNull final DistributionSet ds, final SoftwareModule softwareModule) {
final Set softwareModules = new HashSet();
softwareModules.add(softwareModule);
ds.removeModule(softwareModule);
@@ -416,9 +429,9 @@ public class DistributionSetManagement {
// throw exception if user tries to update a DS type that is already in
// use
if (!persisted.areModuleEntriesIdentical(dsType) && distributionSetRepository.countByType(persisted) > 0) {
- throw new EntityReadOnlyException(
- String.format("distribution set type %s set is already assigned to targets and cannot be changed",
- dsType.getName()));
+ throw new EntityReadOnlyException(String.format(
+ "distribution set type %s set is already assigned to targets and cannot be changed",
+ dsType.getName()));
}
return distributionSetTypeRepository.save(dsType);
@@ -584,16 +597,14 @@ public class DistributionSetManagement {
final DistributionSetFilter filterWithInstalledTargets = distributionSetFilterBuilder
.setInstalledTargetId(assignedOrInstalled).setAssignedTargetId(null).build();
- final DistributionSet installedDS = findDistributionSetsByFiltersAndInstalledOrAssignedTarget(
- filterWithInstalledTargets);
+ final DistributionSet installedDS = findDistributionSetsByFiltersAndInstalledOrAssignedTarget(filterWithInstalledTargets);
final DistributionSetFilter filterWithAssignedTargets = distributionSetFilterBuilder.setInstalledTargetId(null)
.setAssignedTargetId(assignedOrInstalled).build();
- final DistributionSet assignedDS = findDistributionSetsByFiltersAndInstalledOrAssignedTarget(
- filterWithAssignedTargets);
+ final DistributionSet assignedDS = findDistributionSetsByFiltersAndInstalledOrAssignedTarget(filterWithAssignedTargets);
- final DistributionSetFilter dsFilterWithNoTargetLinked = distributionSetFilterBuilder.setInstalledTargetId(null)
- .setAssignedTargetId(null).build();
+ final DistributionSetFilter dsFilterWithNoTargetLinked = distributionSetFilterBuilder
+ .setInstalledTargetId(null).setAssignedTargetId(null).build();
// first fine the distribution sets filtered by the given filter
// parameters
final Page findDistributionSetsByFilters = findDistributionSetsByFilters(pageable,
@@ -643,8 +654,8 @@ public class DistributionSetManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
public DistributionSet findDistributionSetByNameAndVersion(@NotEmpty final String distributionName,
@NotEmpty final String version) {
- final Specification spec = DistributionSetSpecification
- .equalsNameAndVersionIgnoreCase(distributionName, version);
+ final Specification spec = DistributionSetSpecification.equalsNameAndVersionIgnoreCase(
+ distributionName, version);
return distributionSetRepository.findOne(spec);
}
@@ -998,17 +1009,17 @@ public class DistributionSetManagement {
final Set softwareModules) {
if (!new HashSet(distributionSet.getModules()).equals(softwareModules)
&& actionRepository.countByDistributionSet(distributionSet) > 0) {
- throw new EntityLockedException(
- String.format("distribution set %s:%s is already assigned to targets and cannot be changed",
- distributionSet.getName(), distributionSet.getVersion()));
+ throw new EntityLockedException(String.format(
+ "distribution set %s:%s is already assigned to targets and cannot be changed",
+ distributionSet.getName(), distributionSet.getVersion()));
}
}
private void checkDistributionSetSoftwareModulesIsAllowedToModify(final DistributionSet distributionSet) {
if (actionRepository.countByDistributionSet(distributionSet) > 0) {
- throw new EntityLockedException(
- String.format("distribution set %s:%s is already assigned to targets and cannot be changed",
- distributionSet.getName(), distributionSet.getVersion()));
+ throw new EntityLockedException(String.format(
+ "distribution set %s:%s is already assigned to targets and cannot be changed",
+ distributionSet.getName(), distributionSet.getVersion()));
}
}
@@ -1057,8 +1068,8 @@ public class DistributionSetManagement {
private void checkAndThrowAlreadyIfDistributionSetMetadataExists(final DsMetadataCompositeKey metadataId) {
if (distributionSetMetadataRepository.exists(metadataId)) {
- throw new EntityAlreadyExistsException(
- "Metadata entry with key '" + metadataId.getKey() + "' already exists");
+ throw new EntityAlreadyExistsException("Metadata entry with key '" + metadataId.getKey()
+ + "' already exists");
}
}
@@ -1066,4 +1077,74 @@ public class DistributionSetManagement {
throw new EntityAlreadyExistsException("Metadata entry with key '" + metadataKey + "' already exists");
}
+ /**
+ * Assign a {@link DistributionSetTag} assignment to given
+ * {@link DistributionSet}s.
+ *
+ * @param dsIds
+ * to assign for
+ * @param tag
+ * to assign
+ * @return list of assigned ds
+ */
+ @Modifying
+ @Transactional
+ @NotNull
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
+ public List assignTag(@NotEmpty final Collection dsIds, @NotNull final DistributionSetTag tag) {
+ final List allDs = findDistributionSetListWithDetails(dsIds);
+
+ allDs.forEach(ds -> ds.getTags().add(tag));
+ final List save = distributionSetRepository.save(allDs);
+
+ afterCommit.afterCommit(() -> {
+
+ final DistributionSetTagAssigmentResult result = new DistributionSetTagAssigmentResult(0, save.size(), 0,
+ save, Collections.emptyList(), tag);
+ eventBus.post(new DistributionSetTagAssigmentResultEvent(result));
+ });
+
+ return save;
+ }
+
+ /**
+ * Unassign all {@link DistributionSet} from a given
+ * {@link DistributionSetTag} .
+ *
+ * @param tag
+ * to unassign all ds
+ * @return list of unassigned ds
+ */
+ @Modifying
+ @Transactional
+ @NotNull
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
+ public List unAssignAllDistributionSetsByTag(@NotNull final DistributionSetTag tag) {
+ return unAssignTag(tag.getAssignedToDistributionSet(), tag);
+ }
+
+ /**
+ * Unassign a {@link DistributionSetTag} assignment to given
+ * {@link DistributionSet}.
+ *
+ * @param dsId
+ * to unassign for
+ * @param distributionSetTag
+ * to unassign
+ * @return the unassigned ds or if no ds is unassigned
+ */
+ @Modifying
+ @Transactional
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
+ public DistributionSet unAssignTag(@NotNull final Long dsId, @NotNull final DistributionSetTag distributionSetTag) {
+ final List allDs = findDistributionSetListWithDetails(Arrays.asList(dsId));
+ final List unAssignTag = unAssignTag(allDs, distributionSetTag);
+ return unAssignTag.isEmpty() ? null : unAssignTag.get(0);
+ }
+
+ private List unAssignTag(final Collection distributionSets,
+ final DistributionSetTag tag) {
+ distributionSets.forEach(ds -> ds.getTags().remove(tag));
+ return distributionSetRepository.save(distributionSets);
+ }
}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetMetadataRepository.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetMetadataRepository.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetRepository.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetRepository.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTagRepository.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTagRepository.java
old mode 100755
new mode 100644
index 39770dee0..e09db5cb2
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTagRepository.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTagRepository.java
@@ -13,6 +13,7 @@ import java.util.List;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.TargetTag;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.transaction.annotation.Transactional;
@@ -23,7 +24,8 @@ import org.springframework.transaction.annotation.Transactional;
*
*/
@Transactional(readOnly = true)
-public interface DistributionSetTagRepository extends BaseEntityRepository {
+public interface DistributionSetTagRepository extends BaseEntityRepository,
+ JpaSpecificationExecutor {
/**
* deletes the {@link DistributionSet} with the given name.
*
@@ -51,4 +53,7 @@ public interface DistributionSetTagRepository extends BaseEntityRepository findAll();
+
+ @Override
+ List save(Iterable entities);
}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTypeRepository.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTypeRepository.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/EclipseLinkTargetInfoRepository.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/EclipseLinkTargetInfoRepository.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ExternalArtifactProviderRepository.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ExternalArtifactProviderRepository.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ExternalArtifactRepository.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ExternalArtifactRepository.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/LocalArtifactRepository.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/LocalArtifactRepository.java
old mode 100755
new mode 100644
index 763b6e5a2..5bbac1dd1
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/LocalArtifactRepository.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/LocalArtifactRepository.java
@@ -9,20 +9,40 @@
package org.eclipse.hawkbit.repository;
import java.util.List;
+import java.util.Optional;
import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
/**
* {@link LocalArtifact} repository.
*
- *
- *
*/
@Transactional(readOnly = true)
public interface LocalArtifactRepository extends BaseEntityRepository {
+
+ /**
+ * Counts artifacts size where the related software module is not
+ * deleted/archived.
+ *
+ * @return sum of artifacts size in bytes
+ */
+ @Query("SELECT SUM(la.size) FROM LocalArtifact la WHERE la.softwareModule.deleted = 0")
+ Optional getSumOfUndeletedArtifactSize();
+
+ /**
+ * Counts artifacts where the related software module is deleted/archived.
+ *
+ * @param deleted
+ * to true for counting the deleted artifacts
+ *
+ * @return number of artifacts
+ */
+ Long countBySoftwareModuleDeleted(boolean deleted);
+
/**
* Searches for a {@link LocalArtifact} based on given gridFsFileName.
*
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/NoCountPagingRepository.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/NoCountPagingRepository.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ReportManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ReportManagement.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/SoftwareManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/SoftwareManagement.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleMetadataRepository.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleMetadataRepository.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleRepository.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleRepository.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleTypeRepository.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleTypeRepository.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java
old mode 100755
new mode 100644
index 4ba82401d..64865ac65
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java
@@ -9,6 +9,7 @@
package org.eclipse.hawkbit.repository;
import java.lang.reflect.Method;
+import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;
@@ -17,13 +18,13 @@ import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.cache.TenancyCacheManager;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
+import org.eclipse.hawkbit.report.model.SystemUsageReport;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.TenantConfiguration;
import org.eclipse.hawkbit.repository.model.TenantMetaData;
import org.eclipse.hawkbit.tenancy.TenantAware;
-import org.eclipse.hawkbit.tenancy.TenantAware.TenantRunner;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.springframework.beans.factory.annotation.Autowired;
@@ -48,9 +49,6 @@ import org.springframework.validation.annotation.Validated;
/**
* Central system management operations of the SP server.
*
- *
- *
- *
*/
@Transactional(readOnly = true)
@Validated
@@ -101,6 +99,9 @@ public class SystemManagement implements EnvironmentAware {
@Autowired
private TenantAware tenantAware;
+ @Autowired
+ private TenantStatsManagement systemStatsManagement;
+
@Autowired
private TenancyCacheManager cacheManager;
@@ -110,12 +111,61 @@ public class SystemManagement implements EnvironmentAware {
private Environment environment;
+ /**
+ * Calculated system usage statistics, both overall for the entire system
+ * and per tenant;
+ *
+ * @return SystemUsageReport of the current system
+ */
+ @NotNull
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_SYSTEM_ADMIN)
+ public SystemUsageReport getSystemUsageStatistics() {
+
+ BigDecimal sumOfArtifacts = (BigDecimal) entityManager
+ .createNativeQuery(
+ "select SUM(file_size) from sp_artifact a INNER JOIN sp_base_software_module sm ON a.software_module = sm.id WHERE sm.deleted = 0")
+ .getSingleResult();
+
+ if (sumOfArtifacts == null) {
+ sumOfArtifacts = new BigDecimal(0);
+ }
+
+ // we use native queries to punch through the tenant boundaries. This
+ // has to be used with care!
+ final Long targets = (Long) entityManager.createNativeQuery("SELECT COUNT(id) FROM sp_target")
+ .getSingleResult();
+
+ final Long artifacts = (Long) entityManager
+ .createNativeQuery(
+ "SELECT COUNT(a.id) FROM sp_artifact a INNER JOIN sp_base_software_module sm ON a.software_module = sm.id WHERE sm.deleted = 0")
+ .getSingleResult();
+
+ final Long actions = (Long) entityManager.createNativeQuery("SELECT COUNT(id) FROM sp_action")
+ .getSingleResult();
+
+ final SystemUsageReport result = new SystemUsageReport(targets, artifacts, actions,
+ sumOfArtifacts.setScale(0, BigDecimal.ROUND_HALF_UP).longValue());
+
+ usageStatsPerTenant(result);
+
+ return result;
+ }
+
+ private void usageStatsPerTenant(final SystemUsageReport report) {
+ final List tenants = findTenants();
+
+ tenants.forEach(tenant -> tenantAware.runAsTenant(tenant, () -> {
+ report.addTenantData(systemStatsManagement.getStatsOfTenant(tenant));
+ return null;
+ }));
+ }
+
/**
* Registers the key generator for the {@link #currentTenant()} method
* because this key generator is aware of the {@link #createInitialTenant}
* thread local in case we are currently creating a tenant and insert the
* default distribution set types.
- *
+ *
* @return the {@link CurrentTenantKeyGenerator}
*/
@Bean
@@ -127,8 +177,8 @@ public class SystemManagement implements EnvironmentAware {
* Returns {@link TenantMetaData} of given and current tenant.
*
* DISCLAIMER: this variant is used during initial login (where the tenant
- * is not yet in teh session). Please user {@link #getTenantMetadata()} for
- * reluar requests.
+ * is not yet in the session). Please user {@link #getTenantMetadata()} for
+ * regular requests.
*
* @param tenant
* @return
@@ -179,25 +229,22 @@ public class SystemManagement implements EnvironmentAware {
public void deleteTenant(@NotNull final String tenant) {
cacheManager.evictCaches(tenant);
cacheManager.getCache("currentTenant").evict(currentTenantKeyGenerator().generate(null, null));
- tenantAware.runAsTenant(tenant, new TenantRunner() {
- @Override
- public Void run() {
- entityManager.setProperty(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, tenant.toUpperCase());
- tenantMetaDataRepository.deleteByTenantIgnoreCase(tenant);
- tenantConfigurationRepository.deleteByTenantIgnoreCase(tenant);
- targetRepository.deleteByTenantIgnoreCase(tenant);
- artifactRepository.deleteByTenantIgnoreCase(tenant);
- externalArtifactRepository.deleteByTenantIgnoreCase(tenant);
- externalArtifactProviderRepository.deleteByTenantIgnoreCase(tenant);
- targetTagRepository.deleteByTenantIgnoreCase(tenant);
- actionRepository.deleteByTenantIgnoreCase(tenant);
- distributionSetTagRepository.deleteByTenantIgnoreCase(tenant);
- distributionSetRepository.deleteByTenantIgnoreCase(tenant);
- distributionSetTypeRepository.deleteByTenantIgnoreCase(tenant);
- softwareModuleRepository.deleteByTenantIgnoreCase(tenant);
- softwareModuleTypeRepository.deleteByTenantIgnoreCase(tenant);
- return null;
- }
+ tenantAware.runAsTenant(tenant, () -> {
+ entityManager.setProperty(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, tenant.toUpperCase());
+ tenantMetaDataRepository.deleteByTenantIgnoreCase(tenant);
+ tenantConfigurationRepository.deleteByTenantIgnoreCase(tenant);
+ targetRepository.deleteByTenantIgnoreCase(tenant);
+ artifactRepository.deleteByTenantIgnoreCase(tenant);
+ externalArtifactRepository.deleteByTenantIgnoreCase(tenant);
+ externalArtifactProviderRepository.deleteByTenantIgnoreCase(tenant);
+ targetTagRepository.deleteByTenantIgnoreCase(tenant);
+ actionRepository.deleteByTenantIgnoreCase(tenant);
+ distributionSetTagRepository.deleteByTenantIgnoreCase(tenant);
+ distributionSetRepository.deleteByTenantIgnoreCase(tenant);
+ distributionSetTypeRepository.deleteByTenantIgnoreCase(tenant);
+ softwareModuleRepository.deleteByTenantIgnoreCase(tenant);
+ softwareModuleTypeRepository.deleteByTenantIgnoreCase(tenant);
+ return null;
});
}
@@ -218,7 +265,7 @@ public class SystemManagement implements EnvironmentAware {
/**
* Checks if a specific tenant exists. The tenant will not be created lazy.
- *
+ *
* @param tenant
* the tenant to check
* @return {@code true} in case the tenant exits or {@code false} if not
@@ -268,7 +315,7 @@ public class SystemManagement implements EnvironmentAware {
* Retrieves a configuration value from the e.g. tenant overwritten
* configuration values or in case the tenant does not a have a specific
* configuration the global default value hold in the {@link Environment}.
- *
+ *
* @param configurationKey
* the key of the configuration
* @param propertyType
@@ -298,7 +345,7 @@ public class SystemManagement implements EnvironmentAware {
/**
* Adds or updates a specific configuration for a specific tenant.
- *
+ *
* @param tenantConf
* the tenant configuration object which contains the key and
* value of the specific configuration to update
@@ -319,7 +366,7 @@ public class SystemManagement implements EnvironmentAware {
/**
* Deletes a specific configuration for the current tenant.
- *
+ *
* @param configurationKey
* the configuration key to be deleted
*/
@@ -337,7 +384,7 @@ public class SystemManagement implements EnvironmentAware {
/*
* (non-Javadoc)
- *
+ *
* @see org.springframework.context.EnvironmentAware#setEnvironment(org.
* springframework.core.env. Environment)
*/
@@ -379,7 +426,7 @@ public class SystemManagement implements EnvironmentAware {
* {@link TenantAware}, but in case we are in a tenant creation with its
* default types we need to use the tenant the current tenant which is
* currently created and not the one currently in the {@link TenantAware}.
- *
+ *
*
*
*/
@@ -387,7 +434,7 @@ public class SystemManagement implements EnvironmentAware {
/*
* (non-Javadoc)
- *
+ *
* @see
* org.springframework.cache.interceptor.KeyGenerator#generate(java.lang
* .Object, java.lang.reflect.Method, java.lang.Object[])
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/TagManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/TagManagement.java
old mode 100755
new mode 100644
index 541c9c9cf..d0cfea0a3
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/TagManagement.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/TagManagement.java
@@ -15,6 +15,13 @@ import java.util.List;
import javax.validation.constraints.NotNull;
+import org.eclipse.hawkbit.eventbus.event.DistributionSetTagCreatedBulkEvent;
+import org.eclipse.hawkbit.eventbus.event.DistributionSetTagDeletedEvent;
+import org.eclipse.hawkbit.eventbus.event.DistributionSetTagUpdateEvent;
+import org.eclipse.hawkbit.eventbus.event.TargetTagCreatedBulkEvent;
+import org.eclipse.hawkbit.eventbus.event.TargetTagDeletedEvent;
+import org.eclipse.hawkbit.eventbus.event.TargetTagUpdateEvent;
+import org.eclipse.hawkbit.executor.AfterTransactionCommitExecutor;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.model.DistributionSet;
@@ -22,16 +29,20 @@ import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.Tag;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetTag;
+import org.eclipse.hawkbit.tenancy.TenantAware;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
+import com.google.common.eventbus.EventBus;
+
/**
*
* Mangement service class for {@link Tag}s.
@@ -58,6 +69,15 @@ public class TagManagement {
@Autowired
private DistributionSetRepository distributionSetRepository;
+ @Autowired
+ private EventBus eventBus;
+
+ @Autowired
+ private TenantAware tenantAware;
+
+ @Autowired
+ private AfterTransactionCommitExecutor afterCommit;
+
/**
* Find {@link TargetTag} based on given Name.
*
@@ -94,7 +114,12 @@ public class TagManagement {
throw new EntityAlreadyExistsException();
}
- return targetTagRepository.save(targetTag);
+ final TargetTag save = targetTagRepository.save(targetTag);
+
+ afterCommit
+ .afterCommit(() -> eventBus.post(new TargetTagCreatedBulkEvent(tenantAware.getCurrentTenant(), save)));
+
+ return save;
}
/**
@@ -117,8 +142,10 @@ public class TagManagement {
throw new EntityAlreadyExistsException();
}
});
-
- return targetTagRepository.save(targetTags);
+ final List save = targetTagRepository.save(targetTags);
+ afterCommit
+ .afterCommit(() -> eventBus.post(new TargetTagCreatedBulkEvent(tenantAware.getCurrentTenant(), save)));
+ return save;
}
/**
@@ -144,6 +171,9 @@ public class TagManagement {
// finally delete the tag itself
targetTagRepository.deleteByName(targetTagName);
+
+ afterCommit.afterCommit(() -> eventBus.post(new TargetTagDeletedEvent(tag)));
+
}
/**
@@ -157,6 +187,31 @@ public class TagManagement {
return targetTagRepository.findAll();
}
+ /**
+ * Retrieves all target tags based on the given specification.
+ *
+ * @param spec
+ * the specification for the query
+ * @param pageable
+ * pagination parameter
+ * @return the found {@link Target}s, never {@code null}
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
+ public Page findAllTargetTags(@NotNull final Specification spec,
+ @NotNull final Pageable pageable) {
+ return targetTagRepository.findAll(spec, pageable);
+ }
+
+ /**
+ * count {@link TargetTag}s.
+ *
+ * @return size of {@link TargetTag}s
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
+ public long countTargetTags() {
+ return targetTagRepository.count();
+ }
+
/**
* updates the {@link TargetTag}.
*
@@ -171,7 +226,9 @@ public class TagManagement {
public TargetTag updateTargetTag(@NotNull final TargetTag targetTag) {
checkNotNull(targetTag.getName());
checkNotNull(targetTag.getId());
- return targetTagRepository.save(targetTag);
+ final TargetTag save = targetTagRepository.save(targetTag);
+ afterCommit.afterCommit(() -> eventBus.post(new TargetTagUpdateEvent(save)));
+ return save;
}
/**
@@ -208,7 +265,11 @@ public class TagManagement {
throw new EntityAlreadyExistsException();
}
- return distributionSetTagRepository.save(distributionSetTag);
+ final DistributionSetTag save = distributionSetTagRepository.save(distributionSetTag);
+
+ afterCommit.afterCommit(() -> eventBus.post(new DistributionSetTagCreatedBulkEvent(tenantAware
+ .getCurrentTenant(), save)));
+ return save;
}
/**
@@ -223,15 +284,18 @@ public class TagManagement {
@Modifying
@Transactional
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY)
- public Iterable createDistributionSetTags(
+ public List createDistributionSetTags(
@NotNull final Iterable distributionSetTags) {
for (final DistributionSetTag dsTag : distributionSetTags) {
if (dsTag.getId() != null) {
throw new EntityAlreadyExistsException();
}
}
+ final List save = distributionSetTagRepository.save(distributionSetTags);
+ afterCommit.afterCommit(() -> eventBus.post(new DistributionSetTagCreatedBulkEvent(tenantAware
+ .getCurrentTenant(), save)));
- return distributionSetTagRepository.save(distributionSetTags);
+ return save;
}
/**
@@ -257,6 +321,8 @@ public class TagManagement {
distributionSetRepository.save(changed);
distributionSetTagRepository.deleteByName(tagName);
+
+ afterCommit.afterCommit(() -> eventBus.post(new DistributionSetTagDeletedEvent(tag)));
}
/**
@@ -275,7 +341,10 @@ public class TagManagement {
public DistributionSetTag updateDistributionSetTag(@NotNull final DistributionSetTag distributionSetTag) {
checkNotNull(distributionSetTag.getName());
checkNotNull(distributionSetTag.getId());
- return distributionSetTagRepository.save(distributionSetTag);
+ final DistributionSetTag save = distributionSetTagRepository.save(distributionSetTag);
+ afterCommit.afterCommit(() -> eventBus.post(new DistributionSetTagUpdateEvent(save)));
+
+ return save;
}
/**
@@ -284,7 +353,7 @@ public class TagManagement {
* @return all {@link DistributionTag}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
- public List findDistributionSetTagsAll() {
+ public List findAllDistributionSetTags() {
return distributionSetTagRepository.findAll();
}
@@ -328,16 +397,31 @@ public class TagManagement {
}
/**
- * returns all {@link TargetTag}s.
+ * returns all {@link DistributionSetTag}s.
*
* @param pageReq
* page parameter
- * @return all {@link TargetTag}s
+ * @return all {@link DistributionSetTag}s
*/
@NotNull
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
- public Page findDistributionSetTagsAll(@NotNull final Pageable pageReq) {
+ public Page findAllDistributionSetTags(@NotNull final Pageable pageReq) {
return distributionSetTagRepository.findAll(pageReq);
}
+ /**
+ * Retrieves all DistributionSet tags based on the given specification.
+ *
+ * @param spec
+ * the specification for the query
+ * @param pageable
+ * pagination parameter
+ * @return the found {@link DistributionSetTag}s, never {@code null}
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
+ public Page findAllDistributionSetTags(@NotNull final Specification spec,
+ @NotNull final Pageable pageable) {
+ return distributionSetTagRepository.findAll(spec, pageable);
+ }
+
}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/TargetFilterQueryManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/TargetFilterQueryManagement.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/TargetFilterQueryRepository.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/TargetFilterQueryRepository.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/TargetInfoRepository.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/TargetInfoRepository.java
old mode 100755
new mode 100644
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java
old mode 100755
new mode 100644
index c0a635442..f0047f6dd
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java
@@ -10,7 +10,9 @@ package org.eclipse.hawkbit.repository;
import java.net.URI;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@@ -28,6 +30,8 @@ import javax.persistence.criteria.Root;
import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.Constants;
+import org.eclipse.hawkbit.eventbus.event.TargetTagAssigmentResultEvent;
+import org.eclipse.hawkbit.executor.AfterTransactionCommitExecutor;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.model.DistributionSet;
@@ -39,6 +43,7 @@ import org.eclipse.hawkbit.repository.model.TargetIdName;
import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.eclipse.hawkbit.repository.model.TargetInfo_;
import org.eclipse.hawkbit.repository.model.TargetTag;
+import org.eclipse.hawkbit.repository.model.TargetTagAssigmentResult;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.model.Target_;
import org.eclipse.hawkbit.repository.rsql.RSQLUtility;
@@ -86,9 +91,6 @@ public class TargetManagement {
@Autowired
private TargetTagRepository targetTagRepository;
- @Autowired
- private TargetFilterQueryRepository targetFilterQueryRepository;
-
@Autowired
private TargetInfoRepository targetInfoRepository;
@@ -98,6 +100,9 @@ public class TargetManagement {
@Autowired
private EventBus eventBus;
+ @Autowired
+ private AfterTransactionCommitExecutor afterCommit;
+
/**
* Find {@link Target} based on given ID returns found Target without
* details, i.e. NO {@link Target#getTags()} and
@@ -179,14 +184,11 @@ public class TargetManagement {
// workarround - no join fetch allowed that is why we need specification
// instead of query for
// count() of Pageable
- final Specification spec = new Specification() {
- @Override
- public Predicate toPredicate(final Root root, final CriteriaQuery> query, final CriteriaBuilder cb) {
- if (!query.getResultType().isAssignableFrom(Long.class)) {
- root.fetch(Target_.targetInfo);
- }
- return cb.conjunction();
+ final Specification spec = (root, query, cb) -> {
+ if (!query.getResultType().isAssignableFrom(Long.class)) {
+ root.fetch(Target_.targetInfo);
}
+ return cb.conjunction();
};
return criteriaNoCountDao.findAll(spec, pageable, Target.class);
}
@@ -223,7 +225,7 @@ public class TargetManagement {
/**
* Retrieves all targets based on the given specification.
- *
+ *
* @param spec
* the specification for the query
* @param pageable
@@ -256,7 +258,7 @@ public class TargetManagement {
/**
* updates the {@link Target}.
- *
+ *
* @param target
* to be updated
* @return the updated {@link Target}
@@ -274,7 +276,7 @@ public class TargetManagement {
/**
* updates multiple {@link Target}s.
- *
+ *
* @param targets
* to be updated
* @return the updated {@link Target}s
@@ -291,7 +293,7 @@ public class TargetManagement {
/**
* Deletes all targets with the given IDs.
- *
+ *
* @param targetIDs
* the technical IDs of the targets to be deleted
*/
@@ -336,7 +338,7 @@ public class TargetManagement {
* details, i.e. NO {@link Target#getTags()} and
* {@link Target#getActiveActions()} possible including the filtering based
* on the given {@code spec}.
- *
+ *
* @param distributionSetID
* the ID of the {@link DistributionSet}
* @param spec
@@ -349,14 +351,9 @@ public class TargetManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET)
public Page findTargetByAssignedDistributionSet(@NotNull final Long distributionSetID,
final Specification spec, @NotNull final Pageable pageReq) {
- return targetRepository.findAll(new Specification() {
- @Override
- public Predicate toPredicate(final Root root, final CriteriaQuery> query, final CriteriaBuilder cb) {
- return cb
- .and(TargetSpecifications.hasAssignedDistributionSet(distributionSetID).toPredicate(root,
- query, cb), spec.toPredicate(root, query, cb));
- }
- }, pageReq);
+ return targetRepository.findAll((Specification) (root, query, cb) -> cb.and(
+ TargetSpecifications.hasAssignedDistributionSet(distributionSetID).toPredicate(root, query, cb),
+ spec.toPredicate(root, query, cb)), pageReq);
}
/**
@@ -393,14 +390,9 @@ public class TargetManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET)
public Page findTargetByInstalledDistributionSet(final Long distributionSetId,
final Specification spec, final Pageable pageable) {
- return targetRepository.findAll(new Specification() {
- @Override
- public Predicate toPredicate(final Root root, final CriteriaQuery> query, final CriteriaBuilder cb) {
- return cb.and(
- TargetSpecifications.hasInstalledDistributionSet(distributionSetId)
- .toPredicate(root, query, cb), spec.toPredicate(root, query, cb));
- }
- }, pageable);
+ return targetRepository.findAll((Specification) (root, query, cb) -> cb.and(
+ TargetSpecifications.hasInstalledDistributionSet(distributionSetId).toPredicate(root, query, cb),
+ spec.toPredicate(root, query, cb)), pageable);
}
/**
@@ -487,16 +479,16 @@ public class TargetManagement {
return countByCriteriaAPI(specList);
}
- private List> buildSpecificationList(final Collection status,
+ private static List> buildSpecificationList(final Collection status,
final String searchText, final Long installedOrAssignedDistributionSetId,
final Boolean selectTargetWithNoTag, final boolean fetch, final String... tagNames) {
- final List> specList = new ArrayList>();
+ final List> specList = new ArrayList<>();
if (status != null && !status.isEmpty()) {
specList.add(TargetSpecifications.hasTargetUpdateStatus(status, fetch));
}
if (installedOrAssignedDistributionSetId != null) {
- specList.add(TargetSpecifications
- .hasInstalledOrAssignedDistributionSet(installedOrAssignedDistributionSetId));
+ specList.add(
+ TargetSpecifications.hasInstalledOrAssignedDistributionSet(installedOrAssignedDistributionSetId));
}
if (!Strings.isNullOrEmpty(searchText)) {
specList.add(TargetSpecifications.likeNameOrDescriptionOrIp(searchText));
@@ -509,7 +501,7 @@ public class TargetManagement {
/**
* executes findAll with the given {@link Target} {@link Specification}s.
- *
+ *
* @param pageable
* paging parameter
* @param specList
@@ -538,7 +530,7 @@ public class TargetManagement {
}
- private Specifications creatingTargetSpecifications(final List> specList) {
+ private static Specifications creatingTargetSpecifications(final List> specList) {
Specifications specs = null;
if (!specList.isEmpty()) {
specs = Specifications.where(specList.get(0));
@@ -568,8 +560,8 @@ public class TargetManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
public TargetTagAssigmentResult toggleTagAssignment(@NotEmpty final List targets,
@NotNull final TargetTag tag) {
- return toggleTagAssignment(targets.stream().map(target -> target.getControllerId())
- .collect(Collectors.toList()), tag.getName());
+ return toggleTagAssignment(
+ targets.stream().map(target -> target.getControllerId()).collect(Collectors.toList()), tag.getName());
}
/**
@@ -592,25 +584,107 @@ public class TargetManagement {
@NotNull final String tagName) {
final TargetTag tag = targetTagRepository.findByNameEquals(tagName);
final List alreadyAssignedTargets = targetRepository.findByTagNameAndControllerIdIn(tagName, targetIds);
- final List allTargets = targetRepository.findAll(TargetSpecifications
- .byControllerIdWithStatusAndTagsInJoin(targetIds));
+ final List allTargets = targetRepository
+ .findAll(TargetSpecifications.byControllerIdWithStatusAndTagsInJoin(targetIds));
// all are already assigned -> unassign
if (alreadyAssignedTargets.size() == allTargets.size()) {
alreadyAssignedTargets.forEach(target -> target.getTags().remove(tag));
- return new TargetTagAssigmentResult(0, 0, alreadyAssignedTargets.size(), null, alreadyAssignedTargets);
+ final TargetTagAssigmentResult result = new TargetTagAssigmentResult(0, 0, alreadyAssignedTargets.size(),
+ Collections.emptyList(), alreadyAssignedTargets, tag);
+
+ afterCommit.afterCommit(() -> eventBus.post(new TargetTagAssigmentResultEvent(result)));
+ return result;
}
allTargets.removeAll(alreadyAssignedTargets);
// some or none are assigned -> assign
allTargets.forEach(target -> target.getTags().add(tag));
final TargetTagAssigmentResult result = new TargetTagAssigmentResult(alreadyAssignedTargets.size(),
- allTargets.size(), 0, targetRepository.save(allTargets), null);
+ allTargets.size(), 0, targetRepository.save(allTargets), Collections.emptyList(), tag);
+
+ afterCommit.afterCommit(() -> eventBus.post(new TargetTagAssigmentResultEvent(result)));
+
// no reason to persist the tag
entityManager.detach(tag);
return result;
}
+ /**
+ * Assign a {@link TargetTag} assignment to given {@link Target}s.
+ *
+ * @param targetIds
+ * to assign for
+ * @param tagName
+ * to assign
+ * @return list of assigned targets
+ */
+ @Modifying
+ @Transactional
+ @NotNull
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
+ public List assignTag(@NotEmpty final Collection targetIds, @NotNull final TargetTag tag) {
+ final List allTargets = targetRepository.findAll(TargetSpecifications
+ .byControllerIdWithStatusAndTagsInJoin(targetIds));
+
+ allTargets.forEach(target -> target.getTags().add(tag));
+ final List save = targetRepository.save(allTargets);
+
+ afterCommit.afterCommit(() -> {
+ final TargetTagAssigmentResult assigmentResult = new TargetTagAssigmentResult(0, save.size(), 0, save,
+ Collections.emptyList(), tag);
+ eventBus.post(new TargetTagAssigmentResultEvent(assigmentResult));
+ });
+
+ return save;
+ }
+
+ private List unAssignTag(@NotEmpty final Collection targets, @NotNull final TargetTag tag) {
+ targets.forEach(target -> target.getTags().remove(tag));
+
+ final List save = targetRepository.save(targets);
+ afterCommit.afterCommit(() -> {
+ final TargetTagAssigmentResult assigmentResult = new TargetTagAssigmentResult(0, 0, save.size(),
+ Collections.emptyList(), save, tag);
+ eventBus.post(new TargetTagAssigmentResultEvent(assigmentResult));
+ });
+ return save;
+ }
+
+ /**
+ * Unassign all {@link Target} from a given {@link TargetTag} .
+ *
+ * @param tag
+ * to unassign all targets
+ * @return list of unassigned targets
+ */
+ @Modifying
+ @Transactional
+ @NotNull
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
+ public List unAssignAllTargetsByTag(@NotNull final TargetTag tag) {
+ return unAssignTag(tag.getAssignedToTargets(), tag);
+ }
+
+ /**
+ * Unassign a {@link TargetTag} assignment to given {@link Target}.
+ *
+ * @param controllerID
+ * to unassign for
+ * @param targetTag
+ * to unassign
+ * @return the unassigned target or if no target is unassigned
+ */
+ @Modifying
+ @Transactional
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
+ public Target unAssignTag(@NotNull final String controllerID, @NotNull final TargetTag targetTag) {
+ final List allTargets = targetRepository.findAll(TargetSpecifications
+ .byControllerIdWithStatusAndTagsInJoin(Arrays.asList(controllerID)));
+ final List unAssignTag = unAssignTag(allTargets, targetTag);
+ return unAssignTag.isEmpty() ? null : unAssignTag.get(0);
+ }
+
/**
* method retrieves all {@link Target}s from the repo in the following
* order:
@@ -624,7 +698,7 @@ public class TargetManagement {
*
* 3) {@link Target}s which have no connection to the given
* {@link DistributionSet}.
- *
+ *
* @param pageable
* the page request to page the result set
* @param orderByDistributionId
@@ -667,19 +741,20 @@ public class TargetManagement {
// select case expression to retrieve the case value as a column to be
// able to order based on
// this column, installed first,...
- final Expression