Merge branch 'master' into feature_boot_13_sec_41
Conflicts: hawkbit-artifact-repository-mongo/src/test/java/org/eclipse/hawkbit/artifact/FreePortFileWriter.java hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/FreePortFileWriter.java Signed-off-by: Kai Zimmermann <kai.zimmermann@bosch-si.com>
This commit is contained in:
@@ -9,16 +9,16 @@
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-repository</artifactId>
|
||||
<version>0.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>hawkbit-repository-api</artifactId>
|
||||
<name>hawkBit :: Repository API</name>
|
||||
|
||||
<dependencies>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-repository</artifactId>
|
||||
<version>0.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>hawkbit-repository-api</artifactId>
|
||||
<name>hawkBit :: Repository API</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-security-core</artifactId>
|
||||
@@ -36,14 +36,33 @@
|
||||
<groupId>cz.jirutka.rsql</groupId>
|
||||
<artifactId>rsql-parser</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.hateoas</groupId>
|
||||
<artifactId>spring-hateoas</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<!-- Optional -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- TEST -->
|
||||
<dependency>
|
||||
<groupId>ru.yandex.qatools.allure</groupId>
|
||||
<artifactId>allure-junit-adaptor</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easytesting</groupId>
|
||||
<artifactId>fest-assert-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easytesting</groupId>
|
||||
<artifactId>fest-assert</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -183,6 +183,8 @@ public interface ControllerManagement {
|
||||
* @return the security context of the target, in case no target exists for
|
||||
* the given controllerId {@code null} is returned
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER + SpringEvalExpressions.HAS_AUTH_OR
|
||||
+ SpringEvalExpressions.HAS_AUTH_READ_TARGET_SEC_TOKEN)
|
||||
String getSecurityTokenByControllerId(@NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldExc
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetFilter;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetFilter.DistributionSetFilterBuilder;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult;
|
||||
@@ -32,7 +33,6 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.model.Tag;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetFilter.DistributionSetFilterBuilder;
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -44,9 +44,6 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
||||
*/
|
||||
public interface DistributionSetManagement {
|
||||
|
||||
// TODO rename/document the whole with details thing (document what the
|
||||
// details are and maybe find a better name, e.g. with dependencies?)
|
||||
|
||||
/**
|
||||
* Assigns {@link SoftwareModule} to existing {@link DistributionSet}.
|
||||
*
|
||||
@@ -284,6 +281,16 @@ public interface DistributionSetManagement {
|
||||
Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(@NotNull Long distributionSetId,
|
||||
@NotNull Pageable pageable);
|
||||
|
||||
/**
|
||||
* Finds all meta data by the given distribution set id.
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the distribution set id to retrieve the meta data from
|
||||
* @return list of distributionSetMetadata for a given distribution set Id.
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
List<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(@NotNull Long distributionSetId);
|
||||
|
||||
/**
|
||||
* finds all meta data by the given distribution set id.
|
||||
*
|
||||
@@ -320,7 +327,6 @@ public interface DistributionSetManagement {
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
List<DistributionSet> findDistributionSetsAll(Collection<Long> dist);
|
||||
|
||||
// TODO discuss: use enum instead of the true,false,null switch ?
|
||||
/**
|
||||
* finds all {@link DistributionSet}s.
|
||||
*
|
||||
|
||||
@@ -340,6 +340,7 @@ public interface SoftwareManagement {
|
||||
* to search for
|
||||
* @return {@link List} of found {@link SoftwareModule}s
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
List<SoftwareModule> findSoftwareModulesById(@NotEmpty Collection<Long> ids);
|
||||
|
||||
/**
|
||||
@@ -482,5 +483,23 @@ public interface SoftwareManagement {
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
|
||||
SoftwareModuleType updateSoftwareModuleType(@NotNull SoftwareModuleType sm);
|
||||
|
||||
/**
|
||||
* Finds all meta data by the given software module id.
|
||||
*
|
||||
* @param softwareModuleId
|
||||
* the software module id to retrieve the meta data from
|
||||
|
||||
*
|
||||
* @throws RSQLParameterUnsupportedFieldException
|
||||
* if a field in the RSQL string is used but not provided by the
|
||||
* given {@code fieldNameProvider}
|
||||
* @throws RSQLParameterSyntaxException
|
||||
* if the RSQL syntax is wrong
|
||||
* @return result of all meta data entries for a given software
|
||||
* module id.
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
List<SoftwareModuleMetadata> findSoftwareModuleMetadataBySoftwareModuleId(Long softwareModuleId);
|
||||
|
||||
}
|
||||
|
||||
@@ -61,6 +61,9 @@ public interface SystemManagement {
|
||||
/**
|
||||
* @return {@link TenantMetaData} of {@link TenantAware#getCurrentTenant()}
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
|
||||
+ SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR
|
||||
+ SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
|
||||
TenantMetaData getTenantMetadata();
|
||||
|
||||
/**
|
||||
@@ -77,6 +80,7 @@ public interface SystemManagement {
|
||||
* to retrieve data for
|
||||
* @return {@link TenantMetaData} of given tenant
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.IS_SYSTEM_CODE)
|
||||
TenantMetaData getTenantMetadata(@NotNull String tenant);
|
||||
|
||||
/**
|
||||
@@ -86,6 +90,7 @@ public interface SystemManagement {
|
||||
* to update
|
||||
* @return updated {@link TenantMetaData} entity
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
|
||||
TenantMetaData updateTenantMetadata(@NotNull TenantMetaData metaData);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.repository.eventbus.event;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
|
||||
/**
|
||||
* Defines the {@link AbstractBaseEntityEvent} of creating a new {@link DistributionSet}.
|
||||
*
|
||||
*/
|
||||
public class DistributionCreatedEvent extends AbstractBaseEntityEvent<DistributionSet> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* @param distributionSet
|
||||
* the distributionSet which has been created
|
||||
*/
|
||||
public DistributionCreatedEvent(final DistributionSet distributionSet) {
|
||||
super(distributionSet);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.eventbus.event;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.event.AbstractDistributedEvent;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
|
||||
/**
|
||||
* Defines the {@link AbstractDistributedEvent} for deletion of
|
||||
* {@link DistributionSet}.
|
||||
*/
|
||||
public class DistributionDeletedEvent extends AbstractDistributedEvent {
|
||||
private static final long serialVersionUID = -3308850381757843098L;
|
||||
private final Long distributionId;
|
||||
|
||||
/**
|
||||
* @param tenant
|
||||
* the tenant for this event
|
||||
* @param distributionId
|
||||
* the ID of the distribution set which has been deleted
|
||||
*/
|
||||
public DistributionDeletedEvent(final String tenant, final Long distributionId) {
|
||||
super(-1, tenant);
|
||||
this.distributionId = distributionId;
|
||||
}
|
||||
|
||||
public Long getDistributionSetId() {
|
||||
return distributionId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.eventbus.event;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
|
||||
/**
|
||||
* Defines the {@link AbstractBaseEntityEvent} for update a {@link DistributionSet}.
|
||||
*
|
||||
*/
|
||||
public class DistributionSetUpdateEvent extends AbstractBaseEntityEvent<DistributionSet> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param ds Distribution Set
|
||||
*/
|
||||
public DistributionSetUpdateEvent(final DistributionSet ds) {
|
||||
super(ds);
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.eventbus.event;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.event.AbstractEvent;
|
||||
import org.eclipse.hawkbit.eventbus.event.DefaultEvent;
|
||||
|
||||
/**
|
||||
* Event declaration for the UI to notify the UI that a rollout has been
|
||||
@@ -17,7 +17,7 @@ import org.eclipse.hawkbit.eventbus.event.AbstractEvent;
|
||||
* @author Michael Hirsch
|
||||
*
|
||||
*/
|
||||
public class RolloutChangeEvent extends AbstractEvent {
|
||||
public class RolloutChangeEvent extends DefaultEvent {
|
||||
|
||||
private final Long rolloutId;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.eventbus.event;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.event.AbstractEvent;
|
||||
import org.eclipse.hawkbit.eventbus.event.DefaultEvent;
|
||||
|
||||
/**
|
||||
* Event declaration for the UI to notify the UI that a rollout has been
|
||||
@@ -17,7 +17,7 @@ import org.eclipse.hawkbit.eventbus.event.AbstractEvent;
|
||||
* @author Michael Hirsch
|
||||
*
|
||||
*/
|
||||
public class RolloutGroupChangeEvent extends AbstractEvent {
|
||||
public class RolloutGroupChangeEvent extends DefaultEvent {
|
||||
|
||||
private final Long rolloutId;
|
||||
private final Long rolloutGroupId;
|
||||
|
||||
@@ -11,14 +11,14 @@ package org.eclipse.hawkbit.repository.eventbus.event;
|
||||
import java.net.URI;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.event.AbstractEvent;
|
||||
import org.eclipse.hawkbit.eventbus.event.DefaultEvent;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
|
||||
/**
|
||||
* Event that gets sent when a distribution set gets assigned to a target.
|
||||
*
|
||||
*/
|
||||
public class TargetAssignDistributionSetEvent extends AbstractEvent {
|
||||
public class TargetAssignDistributionSetEvent extends DefaultEvent {
|
||||
|
||||
private final Collection<SoftwareModule> softwareModules;
|
||||
private final String controllerId;
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* 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.repository.eventbus.event;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.event.AbstractDistributedEvent;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
|
||||
/**
|
||||
*
|
||||
* Defines the {@link AbstractBaseEntityEvent} of deleting a {@link Target}.
|
||||
*/
|
||||
public class TargetDeletedEvent extends AbstractDistributedEvent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final long targetId;
|
||||
|
||||
/**
|
||||
* @param tenant
|
||||
* the tenant for this event
|
||||
* @param targetId
|
||||
* the ID of the target which has been deleted
|
||||
*/
|
||||
public TargetDeletedEvent(final String tenant, final long targetId) {
|
||||
super(-1, tenant);
|
||||
this.targetId = targetId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the targetId
|
||||
*/
|
||||
public long getTargetId() {
|
||||
return targetId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.repository.eventbus.event;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
|
||||
/**
|
||||
* Defines the {@link AbstractBaseEntityEvent} of updating a {@link Target}.
|
||||
*
|
||||
*/
|
||||
public class TargetUpdatedEvent extends AbstractBaseEntityEvent<Target> {
|
||||
|
||||
private static final long serialVersionUID = 5665118668865832477L;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param baseEntity
|
||||
* Target entity
|
||||
*/
|
||||
public TargetUpdatedEvent(final Target baseEntity) {
|
||||
super(baseEntity);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* Thrown if artifact deletion failed.
|
||||
@@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class ArtifactDeleteFailedException extends SpServerRtException {
|
||||
public final class ArtifactDeleteFailedException extends AbstractServerRtException {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class ArtifactUploadFailedException extends SpServerRtException {
|
||||
public final class ArtifactUploadFailedException extends AbstractServerRtException {
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* Thrown if cancelation of actions is performened where the action is not
|
||||
@@ -19,7 +19,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class CancelActionNotAllowedException extends SpServerRtException {
|
||||
public final class CancelActionNotAllowedException extends AbstractServerRtException {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* {@link ConcurrentModificationException} is thrown when a given entity in's
|
||||
@@ -19,7 +19,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ConcurrentModificationException extends SpServerRtException {
|
||||
public class ConcurrentModificationException extends AbstractServerRtException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_CONCURRENT_MODIFICATION;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* Thrown if DS creation failed.
|
||||
@@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class DistributionSetCreationFailedMissingMandatoryModuleException extends SpServerRtException {
|
||||
public final class DistributionSetCreationFailedMissingMandatoryModuleException extends AbstractServerRtException {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class DistributionSetTypeUndefinedException extends SpServerRtException {
|
||||
public class DistributionSetTypeUndefinedException extends AbstractServerRtException {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* the {@link EntityAlreadyExistsException} is thrown when a entity is tried to
|
||||
@@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class EntityAlreadyExistsException extends SpServerRtException {
|
||||
public class EntityAlreadyExistsException extends AbstractServerRtException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_ENTITY_ALRREADY_EXISTS;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* The {@link EntityLockedException} is thrown when an entity has been locked by
|
||||
@@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class EntityLockedException extends SpServerRtException {
|
||||
public class EntityLockedException extends AbstractServerRtException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final SpServerError THIS_ERROR = SpServerError.SP_ENTITY_LOCKED;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* the {@link EntityNotFoundException} is thrown when a entity is tried find but
|
||||
@@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class EntityNotFoundException extends SpServerRtException {
|
||||
public class EntityNotFoundException extends AbstractServerRtException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_ENTITY_NOT_EXISTS;
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* the {@link EntityReadOnlyException} is thrown when a entity is in read only
|
||||
* mode and a user tries to change it.
|
||||
*/
|
||||
public class EntityReadOnlyException extends SpServerRtException {
|
||||
public class EntityReadOnlyException extends AbstractServerRtException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_ENTITY_READ_ONLY;
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* Thrown when force quitting an actions is not allowed. e.g. the action is not
|
||||
* active or it is not canceled before.
|
||||
*
|
||||
*/
|
||||
public final class ForceQuitActionNotAllowedException extends SpServerRtException {
|
||||
public final class ForceQuitActionNotAllowedException extends AbstractServerRtException {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class GridFSDBFileNotFoundException extends SpServerRtException {
|
||||
public final class GridFSDBFileNotFoundException extends AbstractServerRtException {
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* Thrown if a distribution set is assigned to a a target that is incomplete
|
||||
@@ -19,7 +19,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class IncompleteDistributionSetException extends SpServerRtException {
|
||||
public final class IncompleteDistributionSetException extends AbstractServerRtException {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* Exception which is thrown in case the current security context object does
|
||||
@@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class InsufficientPermissionException extends SpServerRtException {
|
||||
public class InsufficientPermissionException extends AbstractServerRtException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* Thrown if MD5 checksum check fails.
|
||||
@@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class InvalidMD5HashException extends SpServerRtException {
|
||||
public class InvalidMD5HashException extends AbstractServerRtException {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* Thrown if SHA1 checksum check fails.
|
||||
@@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class InvalidSHA1HashException extends SpServerRtException {
|
||||
public class InvalidSHA1HashException extends AbstractServerRtException {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* Exception which is thrown when trying to set an invalid target address.
|
||||
*/
|
||||
public class InvalidTargetAddressException extends SpServerRtException {
|
||||
public class InvalidTargetAddressException extends AbstractServerRtException {
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* Thrown if a multi part exception occurred.
|
||||
*
|
||||
*/
|
||||
public final class MultiPartFileUploadException extends SpServerRtException {
|
||||
public final class MultiPartFileUploadException extends AbstractServerRtException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* Exception used by the REST API in case of RSQL search filter query.
|
||||
@@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class RSQLParameterSyntaxException extends SpServerRtException {
|
||||
public class RSQLParameterSyntaxException extends AbstractServerRtException {
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* Exception used by the REST API in case of invalid field name in the rsql
|
||||
@@ -19,7 +19,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class RSQLParameterUnsupportedFieldException extends SpServerRtException {
|
||||
public class RSQLParameterUnsupportedFieldException extends AbstractServerRtException {
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* the {@link RolloutIllegalStateException} is thrown when a rollout is changing
|
||||
@@ -17,7 +17,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
* rollout, or trying to resume a already finished rollout.
|
||||
*
|
||||
*/
|
||||
public class RolloutIllegalStateException extends SpServerRtException {
|
||||
public class RolloutIllegalStateException extends AbstractServerRtException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final SpServerError THIS_ERROR = SpServerError.SP_ROLLOUT_ILLEGAL_STATE;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* the {@link TenantNotExistException} is thrown when e.g. a controller tries to
|
||||
@@ -20,7 +20,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class TenantNotExistException extends SpServerRtException {
|
||||
public class TenantNotExistException extends AbstractServerRtException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_TENANT_NOT_EXISTS;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* Thrown if too many status entries have been inserted.
|
||||
@@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class ToManyAttributeEntriesException extends SpServerRtException {
|
||||
public final class ToManyAttributeEntriesException extends AbstractServerRtException {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
|
||||
/**
|
||||
* Thrown if too many status entries have been inserted.
|
||||
@@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class ToManyStatusEntriesException extends SpServerRtException {
|
||||
public final class ToManyStatusEntriesException extends AbstractServerRtException {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.exception.SpServerRtException;
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
@@ -23,7 +23,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class UnsupportedSoftwareModuleForThisDistributionSetException extends SpServerRtException {
|
||||
public class UnsupportedSoftwareModuleForThisDistributionSetException extends AbstractServerRtException {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* 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.repository.model;
|
||||
|
||||
/**
|
||||
* Interface for the entity interceptor lifecycle.
|
||||
*/
|
||||
public interface EntityInterceptor {
|
||||
|
||||
/**
|
||||
* Callback for the {@link @PrePersist} lifecycle event.
|
||||
*
|
||||
* @param entity
|
||||
* the model entity
|
||||
*/
|
||||
default void prePersist(final Object entity) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback for the {@link @PostPersist} lifecycle event.
|
||||
*
|
||||
* @param entity
|
||||
* the model entity
|
||||
*/
|
||||
default void postPersist(final Object entity) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback for the {@link @PostRemove} lifecycle event.
|
||||
*
|
||||
* @param entity
|
||||
* the model entity
|
||||
*/
|
||||
default void postRemove(final Object entity) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback for the {@link @PreRemove} lifecycle event.
|
||||
*
|
||||
* @param entity
|
||||
* the model entity
|
||||
*/
|
||||
default void preRemove(final Object entity) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback for the {@link @PostLoad} lifecycle event.
|
||||
*
|
||||
* @param entity
|
||||
* the model entity
|
||||
*/
|
||||
default void postLoad(final Object entity) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback for the {@link @PreUpdate} lifecycle event.
|
||||
*
|
||||
* @param entity
|
||||
* the model entity
|
||||
*/
|
||||
default void preUpdate(final Object entity) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback for the {@link @PostUpdate} lifecycle event.
|
||||
*
|
||||
* @param entity
|
||||
* the model entity
|
||||
*/
|
||||
default void postUpdate(final Object entity) {
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* 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.repository;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
import com.google.common.reflect.ClassPath;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Unit Tests - Repository")
|
||||
@Stories("Security Test")
|
||||
public class RepositoryManagementMethodPreAuthorizeAnnotatedTest {
|
||||
|
||||
private static final Set<Method> METHOD_SECURITY_EXCLUSION = new HashSet<>();
|
||||
|
||||
static {
|
||||
METHOD_SECURITY_EXCLUSION.add(getMethod(SystemManagement.class, "currentTenant"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that repository methods are @PreAuthorize annotated")
|
||||
public void repositoryManagementMethodsArePreAuthorizedAnnotated()
|
||||
throws ClassNotFoundException, URISyntaxException, IOException {
|
||||
final List<Class<?>> findInterfacesInPackage = findInterfacesInPackage(getClass().getPackage(),
|
||||
Pattern.compile(".*Management"));
|
||||
|
||||
assertThat(findInterfacesInPackage).isNotEmpty();
|
||||
for (final Class<?> interfaceToCheck : findInterfacesInPackage) {
|
||||
assertDeclaredMethodsContainsPreAuthorizeAnnotaions(interfaceToCheck);
|
||||
}
|
||||
|
||||
// all exclusion should be used, otherwise the method exlusion should be
|
||||
// cleaned up again
|
||||
assertThat(METHOD_SECURITY_EXCLUSION).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* asserts that the given methods are annotated with the
|
||||
* {@link PreAuthorize} annotation for security. Inherited methods are not
|
||||
* checked. The following methods are excluded due inherited from
|
||||
* {@link Object}, like equals() or toString().
|
||||
*
|
||||
* @param clazz
|
||||
* the class to retrieve the public declared methods
|
||||
*/
|
||||
private static void assertDeclaredMethodsContainsPreAuthorizeAnnotaions(final Class<?> clazz) {
|
||||
final Method[] declaredMethods = clazz.getDeclaredMethods();
|
||||
for (final Method method : declaredMethods) {
|
||||
final boolean methodExcluded = METHOD_SECURITY_EXCLUSION.contains(method);
|
||||
if (methodExcluded || method.isSynthetic() || Modifier.isPublic(method.getModifiers())) {
|
||||
// skip method because it should be excluded
|
||||
METHOD_SECURITY_EXCLUSION.remove(method);
|
||||
continue;
|
||||
}
|
||||
final PreAuthorize annotation = method.getAnnotation(PreAuthorize.class);
|
||||
assertThat(annotation).as("The public method " + method.getName() + " in class " + clazz.getName()
|
||||
+ " is not annoated with @PreAuthorize, security leak?").isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
private List<Class<?>> findInterfacesInPackage(final Package p, final Pattern includeFilter)
|
||||
throws URISyntaxException, IOException, ClassNotFoundException {
|
||||
return ClassPath.from(Thread.currentThread().getContextClassLoader()).getTopLevelClasses(p.getName()).stream()
|
||||
.filter(clazzInfo -> includeFilter.matcher(clazzInfo.getSimpleName()).matches())
|
||||
.map(clazzInfo -> clazzInfo.load()).filter(clazz -> clazz.isInterface()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static Method getMethod(final Class<?> clazz, final String methodName, final Class<?>... parameterTypes) {
|
||||
try {
|
||||
return clazz.getMethod(methodName, parameterTypes);
|
||||
} catch (NoSuchMethodException | SecurityException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,7 @@ import org.eclipse.hawkbit.repository.jpa.aspects.ExceptionMappingAspectHandler;
|
||||
import org.eclipse.hawkbit.repository.jpa.configuration.MultiTenantJpaTransactionManager;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.CacheManagerHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityInterceptorHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemManagementHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
|
||||
@@ -144,6 +145,14 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
return SecurityTokenGeneratorHolder.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the singleton instance of the {@link EntityInterceptorHolder}
|
||||
*/
|
||||
@Bean
|
||||
public EntityInterceptorHolder entityInterceptorHolder() {
|
||||
return EntityInterceptorHolder.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the singleton instance of the {@link CacheManagerHolder}
|
||||
*/
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.eclipse.hawkbit.repository.DistributionSetMetadataFields;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetTypeFields;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.repository.TagManagement;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetTagAssigmentResultEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityLockedException;
|
||||
@@ -54,6 +55,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
@@ -102,6 +104,9 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
@Autowired
|
||||
private AfterTransactionCommitExecutor afterCommit;
|
||||
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
|
||||
@Override
|
||||
public DistributionSet findDistributionSetByIdWithDetails(final Long distid) {
|
||||
return distributionSetRepository.findOne(DistributionSetSpecification.byId(distid));
|
||||
@@ -193,6 +198,9 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
// handle the empty list
|
||||
distributionSetRepository.deleteByIdIn(toHardDelete);
|
||||
}
|
||||
|
||||
Arrays.stream(distributionSetIDs)
|
||||
.forEach(dsId -> eventBus.post(new DistributionDeletedEvent(tenantAware.getCurrentTenant(), dsId)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -475,11 +483,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
if (distributionSetMetadataRepository.exists(metadata.getId())) {
|
||||
throwMetadataKeyAlreadyExists(metadata.getId().getKey());
|
||||
}
|
||||
// merge base distribution set so optLockRevision gets updated and audit
|
||||
// log written because
|
||||
// modifying metadata is modifying the base distribution set itself for
|
||||
// auditing purposes.
|
||||
entityManager.merge((JpaDistributionSet) metadata.getDistributionSet()).setLastModifiedAt(0L);
|
||||
|
||||
touch(metadata.getDistributionSet());
|
||||
return distributionSetMetadataRepository.save(metadata);
|
||||
}
|
||||
|
||||
@@ -494,7 +499,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
for (final JpaDistributionSetMetadata distributionSetMetadata : metadata) {
|
||||
checkAndThrowAlreadyIfDistributionSetMetadataExists(distributionSetMetadata.getId());
|
||||
}
|
||||
metadata.forEach(m -> entityManager.merge((JpaDistributionSet) m.getDistributionSet()).setLastModifiedAt(0L));
|
||||
metadata.forEach(m -> touch(m.getDistributionSet()));
|
||||
|
||||
return new ArrayList<>(
|
||||
(Collection<? extends DistributionSetMetadata>) distributionSetMetadataRepository.save(metadata));
|
||||
@@ -510,7 +515,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
findOne(metadata.getDistributionSet(), metadata.getKey());
|
||||
// touch it to update the lock revision because we are modifying the
|
||||
// DS indirectly
|
||||
entityManager.merge((JpaDistributionSet) metadata.getDistributionSet()).setLastModifiedAt(0L);
|
||||
touch(metadata.getDistributionSet());;
|
||||
return distributionSetMetadataRepository.save(metadata);
|
||||
}
|
||||
|
||||
@@ -518,13 +523,26 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
|
||||
@Modifying
|
||||
public void deleteDistributionSetMetadata(final DistributionSet distributionSet, final String key) {
|
||||
touch(distributionSet);
|
||||
distributionSetMetadataRepository.delete(new DsMetadataCompositeKey(distributionSet, key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the latest distribution set based on ds ID after the metadata changes for that distribution set.
|
||||
* @param distributionSet Distribution set
|
||||
*/
|
||||
private void touch(final DistributionSet distributionSet) {
|
||||
final DistributionSet latestDistributionSet = findDistributionSetById(distributionSet.getId());
|
||||
// merge base distribution set so optLockRevision gets updated and audit
|
||||
// log written because
|
||||
// modifying metadata is modifying the base distribution set itself for
|
||||
// auditing purposes.
|
||||
entityManager.merge((JpaDistributionSet) latestDistributionSet).setLastModifiedAt(0L);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(final Long distributionSetId,
|
||||
final Pageable pageable) {
|
||||
|
||||
return convertMdPage(distributionSetMetadataRepository
|
||||
.findAll((Specification<JpaDistributionSetMetadata>) (root, query, cb) -> cb.equal(
|
||||
root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id),
|
||||
@@ -532,6 +550,14 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(final Long distributionSetId) {
|
||||
return new ArrayList<DistributionSetMetadata>(distributionSetMetadataRepository
|
||||
.findAll((Specification<JpaDistributionSetMetadata>) (root, query, cb) -> cb.equal(
|
||||
root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id),
|
||||
distributionSetId)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(final Long distributionSetId,
|
||||
final String rsqlParam, final Pageable pageable) {
|
||||
|
||||
@@ -621,6 +621,16 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
||||
pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SoftwareModuleMetadata> findSoftwareModuleMetadataBySoftwareModuleId(final Long softwareModuleId) {
|
||||
return new ArrayList<>(
|
||||
softwareModuleMetadataRepository
|
||||
.findAll((Specification<JpaSoftwareModuleMetadata>) (root, query,
|
||||
cb) -> cb.and(cb.equal(
|
||||
root.get(JpaSoftwareModuleMetadata_.softwareModule).get(JpaSoftwareModule_.id),
|
||||
softwareModuleId))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoftwareModuleMetadata findSoftwareModuleMetadata(final SoftwareModule softwareModule, final String key) {
|
||||
return findSoftwareModuleMetadata(new SwMetadataCompositeKey(softwareModule, key));
|
||||
|
||||
@@ -29,6 +29,7 @@ import javax.persistence.criteria.Root;
|
||||
|
||||
import org.eclipse.hawkbit.repository.TargetFields;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetTagAssigmentResultEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||
@@ -48,6 +49,7 @@ import org.eclipse.hawkbit.repository.model.TargetIdName;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.data.domain.Page;
|
||||
@@ -94,6 +96,9 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
@Autowired
|
||||
private EventBus eventBus;
|
||||
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
|
||||
@Autowired
|
||||
private AfterTransactionCommitExecutor afterCommit;
|
||||
|
||||
@@ -206,6 +211,8 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
targetInfoRepository.deleteByTargetIdIn(targetsForCurrentTenant);
|
||||
targetRepository.deleteByIdIn(targetsForCurrentTenant);
|
||||
}
|
||||
targetsForCurrentTenant
|
||||
.forEach(targetId -> eventBus.post(new TargetDeletedEvent(tenantAware.getCurrentTenant(), targetId)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,154 +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.repository.jpa.eventbus;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.eclipse.hawkbit.eventbus.event.TargetDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetInfoUpdateEvent;
|
||||
import org.eclipse.hawkbit.repository.jpa.TargetRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetInfo;
|
||||
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* An aspect implementation which wraps the necessary repository services for
|
||||
* saving {@link TenantAwareBaseEntity}s to publish create or update events.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
@Aspect
|
||||
public class EntityChangeEventListener {
|
||||
|
||||
@Autowired
|
||||
private EventBus eventBus;
|
||||
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
|
||||
@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}
|
||||
* information in the target created event. So we are listening to the
|
||||
* {@link TargetInfo} creation to indicate if an Target has been created.
|
||||
*
|
||||
* @param joinpoint
|
||||
* the aspect join point
|
||||
* @return the object of the {@link ProceedingJoinPoint#proceed()}
|
||||
* @throws Throwable
|
||||
* in case exception happens in the
|
||||
* {@link ProceedingJoinPoint#proceed()}
|
||||
*/
|
||||
@Around("execution(* org.eclipse.hawkbit.repository.jpa.TargetInfoRepository.save(..))")
|
||||
// Exception squid:S00112 - Is aspectJ proxy
|
||||
@SuppressWarnings({ "squid:S00112" })
|
||||
public Object targetCreated(final ProceedingJoinPoint joinpoint) throws Throwable {
|
||||
final boolean isNew = isTargetInfoNew(joinpoint.getArgs()[0]);
|
||||
final Object result = joinpoint.proceed();
|
||||
if (result instanceof TargetInfo) {
|
||||
if (isNew) {
|
||||
notifyTargetCreated(entityManager.merge(entityManager.merge(((TargetInfo) result).getTarget())));
|
||||
} else {
|
||||
notifyTargetInfoChanged((TargetInfo) result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy method around the delete method of the {@link TargetRepository} to
|
||||
* notify the {@link TargetDeletedEvent} in case targets has been deleted.
|
||||
*
|
||||
* @param joinpoint
|
||||
* the aspect join point
|
||||
* @return the object of the {@link ProceedingJoinPoint#proceed()}
|
||||
* @throws Throwable
|
||||
* in case exception happens in the
|
||||
* {@link ProceedingJoinPoint#proceed()}
|
||||
*/
|
||||
@Around("execution(* org.eclipse.hawkbit.repository.jpa.TargetRepository.deleteByIdIn(..))")
|
||||
// Exception squid:S00112 - Is aspectJ proxy
|
||||
@SuppressWarnings({ "squid:S00112" })
|
||||
public Object targetDeletedById(final ProceedingJoinPoint joinpoint) throws Throwable {
|
||||
final String currentTenant = tenantAware.getCurrentTenant();
|
||||
final Object result = joinpoint.proceed();
|
||||
final Collection<Long> targetIds = (Collection<Long>) joinpoint.getArgs()[0];
|
||||
targetIds.forEach(targetId -> notifyTargetDeleted(currentTenant, targetId));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy method around the delete method of the {@link TargetRepository} to
|
||||
* notify the {@link TargetDeletedEvent} in case targets has been deleted.
|
||||
*
|
||||
* @param joinpoint
|
||||
* the aspect join point
|
||||
* @return the object of the {@link ProceedingJoinPoint#proceed()}
|
||||
* @throws Throwable
|
||||
* in case exception happens in the
|
||||
* {@link ProceedingJoinPoint#proceed()}
|
||||
*/
|
||||
@Around("execution(* org.eclipse.hawkbit.repository.jpa.TargetRepository.delete(..))")
|
||||
// Exception squid:S00112 - Is aspectJ proxy
|
||||
@SuppressWarnings({ "squid:S00112", "unchecked" })
|
||||
public Object targetDeleted(final ProceedingJoinPoint joinpoint) throws Throwable {
|
||||
final String currentTenant = tenantAware.getCurrentTenant();
|
||||
final Object result = joinpoint.proceed();
|
||||
final Object param = joinpoint.getArgs()[0];
|
||||
// delete by id
|
||||
if (param instanceof Long) {
|
||||
notifyTargetDeleted(currentTenant, (Long) param);
|
||||
} else if (param instanceof Target) {
|
||||
notifyTargetDeleted(currentTenant, ((Target) param).getId());
|
||||
} else if (param instanceof Iterable) {
|
||||
((Iterable<Target>) param).forEach(target -> notifyTargetDeleted(currentTenant, target.getId()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void notifyTargetCreated(final Target t) {
|
||||
afterCommit.afterCommit(() -> eventBus.post(new TargetCreatedEvent(t)));
|
||||
|
||||
}
|
||||
|
||||
private void notifyTargetInfoChanged(final TargetInfo targetInfo) {
|
||||
afterCommit.afterCommit(() -> eventBus.post(new TargetInfoUpdateEvent(targetInfo)));
|
||||
}
|
||||
|
||||
private void notifyTargetDeleted(final String tenant, final Long targetId) {
|
||||
afterCommit.afterCommit(() -> eventBus.post(new TargetDeletedEvent(tenant, targetId)));
|
||||
}
|
||||
|
||||
private static boolean isTargetInfoNew(final Object targetInfo) {
|
||||
return ((JpaTargetInfo) targetInfo).isNew();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,7 +31,8 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
*/
|
||||
@MappedSuperclass
|
||||
@Access(AccessType.FIELD)
|
||||
@EntityListeners({ AuditingEntityListener.class, CacheFieldEntityListener.class, EntityPropertyChangeListener.class })
|
||||
@EntityListeners({ AuditingEntityListener.class, CacheFieldEntityListener.class, EntityPropertyChangeListener.class,
|
||||
EntityInterceptorListener.class })
|
||||
public abstract class AbstractJpaBaseEntity implements BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@@ -178,4 +179,5 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* 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.repository.jpa.model;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.persistence.PostLoad;
|
||||
import javax.persistence.PostPersist;
|
||||
import javax.persistence.PostRemove;
|
||||
import javax.persistence.PostUpdate;
|
||||
import javax.persistence.PrePersist;
|
||||
import javax.persistence.PreRemove;
|
||||
import javax.persistence.PreUpdate;
|
||||
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityInterceptorHolder;
|
||||
import org.eclipse.hawkbit.repository.model.EntityInterceptor;
|
||||
|
||||
/**
|
||||
* Entity listener which calls the callback's of all registered entity
|
||||
* interceptors.
|
||||
*/
|
||||
public class EntityInterceptorListener {
|
||||
|
||||
/**
|
||||
* Callback for lifecyle event <i>pre persist</i>.
|
||||
*
|
||||
* @param entity
|
||||
* the JPA entity which this listener is associated with
|
||||
*/
|
||||
@PrePersist
|
||||
public void prePersist(final Object entity) {
|
||||
notifyAll(interceptor -> interceptor.prePersist(entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for lifecyle event <i>post persist</i>.
|
||||
*
|
||||
* @param entity
|
||||
* the JPA entity which this listener is associated with
|
||||
*/
|
||||
@PostPersist
|
||||
public void postPersist(final Object entity) {
|
||||
notifyAll(interceptor -> interceptor.postPersist(entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for lifecyle event <i>post remove</i>.
|
||||
*
|
||||
* @param entity
|
||||
* the JPA entity which this listener is associated with
|
||||
*/
|
||||
@PostRemove
|
||||
public void postRemove(final Object entity) {
|
||||
notifyAll(interceptor -> interceptor.postRemove(entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for lifecyle event <i>pre remove</i>.
|
||||
*
|
||||
* @param entity
|
||||
* the JPA entity which this listener is associated with
|
||||
*/
|
||||
@PreRemove
|
||||
public void preRemove(final Object entity) {
|
||||
notifyAll(interceptor -> interceptor.preRemove(entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for lifecyle event <i>post load</i>.
|
||||
*
|
||||
* @param entity
|
||||
* the JPA entity which this listener is associated with
|
||||
*/
|
||||
@PostLoad
|
||||
public void postLoad(final Object entity) {
|
||||
notifyAll(interceptor -> interceptor.postLoad(entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for lifecyle event <i>pre update</i>.
|
||||
*
|
||||
* @param entity
|
||||
* the JPA entity which this listener is associated with
|
||||
*/
|
||||
@PreUpdate
|
||||
public void preUpdate(final Object entity) {
|
||||
notifyAll(interceptor -> interceptor.preUpdate(entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for lifecyle event <i>post update</i>.
|
||||
*
|
||||
* @param entity
|
||||
* the JPA entity which this listener is associated with
|
||||
*/
|
||||
@PostUpdate
|
||||
public void postUpdate(final Object entity) {
|
||||
notifyAll(interceptor -> interceptor.postUpdate(entity));
|
||||
}
|
||||
|
||||
private static void notifyAll(final Consumer<? super EntityInterceptor> action) {
|
||||
EntityInterceptorHolder.getInstance().getEntityInterceptors().forEach(action);
|
||||
}
|
||||
}
|
||||
@@ -8,79 +8,47 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.model;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.ActionCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.ActionPropertyChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.RolloutGroupPropertyChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.RolloutPropertyChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
|
||||
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
|
||||
import org.eclipse.persistence.queries.UpdateObjectQuery;
|
||||
import org.eclipse.persistence.sessions.changesets.DirectToFieldChangeRecord;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* Listens to change in property values of an entity.
|
||||
* Listens to change in property values of an entity and calls the corresponding
|
||||
* {@link EventAwareEntity}.
|
||||
*
|
||||
*/
|
||||
public class EntityPropertyChangeListener extends DescriptorEventAdapter {
|
||||
|
||||
@Override
|
||||
public void postInsert(final DescriptorEvent event) {
|
||||
if (event.getObject().getClass().equals(Action.class)) {
|
||||
final Action action = (Action) event.getObject();
|
||||
if (action.getRollout() != null) {
|
||||
final EventBus eventBus = getEventBus();
|
||||
final AfterTransactionCommitExecutor afterCommit = getAfterTransactionCommmitExecutor();
|
||||
afterCommit.afterCommit(() -> eventBus.post(new ActionCreatedEvent(action)));
|
||||
}
|
||||
final Object object = event.getObject();
|
||||
if (isEventAwareEntity(object)) {
|
||||
doNotifiy(() -> ((EventAwareEntity) object).fireCreateEvent(event));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postUpdate(final DescriptorEvent event) {
|
||||
if (event.getObject().getClass().equals(JpaAction.class)) {
|
||||
getAfterTransactionCommmitExecutor().afterCommit(() -> getEventBus().post(
|
||||
new ActionPropertyChangeEvent((Action) event.getObject(), getChangeSet(Action.class, event))));
|
||||
} else if (event.getObject().getClass().equals(JpaRollout.class)) {
|
||||
getAfterTransactionCommmitExecutor().afterCommit(() -> getEventBus().post(
|
||||
new RolloutPropertyChangeEvent((Rollout) event.getObject(), getChangeSet(Rollout.class, event))));
|
||||
} else if (event.getObject().getClass().equals(JpaRolloutGroup.class)) {
|
||||
getAfterTransactionCommmitExecutor().afterCommit(
|
||||
() -> getEventBus().post(new RolloutGroupPropertyChangeEvent((RolloutGroup) event.getObject(),
|
||||
getChangeSet(RolloutGroup.class, event))));
|
||||
final Object object = event.getObject();
|
||||
if (isEventAwareEntity(object)) {
|
||||
doNotifiy(() -> ((EventAwareEntity) object).fireUpdateEvent(event));
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends TenantAwareBaseEntity> Map<String, AbstractPropertyChangeEvent<T>.Values> getChangeSet(
|
||||
final Class<T> clazz, final DescriptorEvent event) {
|
||||
final T rolloutGroup = clazz.cast(event.getObject());
|
||||
final ObjectChangeSet changeSet = ((UpdateObjectQuery) event.getQuery()).getObjectChangeSet();
|
||||
return changeSet.getChanges().stream().filter(record -> record instanceof DirectToFieldChangeRecord)
|
||||
.map(record -> (DirectToFieldChangeRecord) record)
|
||||
.collect(Collectors.toMap(record -> record.getAttribute(),
|
||||
record -> new AbstractPropertyChangeEvent<T>(rolloutGroup, null).new Values(
|
||||
record.getOldValue(), record.getNewValue())));
|
||||
@Override
|
||||
public void postDelete(final DescriptorEvent event) {
|
||||
final Object object = event.getObject();
|
||||
if (isEventAwareEntity(object)) {
|
||||
doNotifiy(() -> ((EventAwareEntity) object).fireDeleteEvent(event));
|
||||
}
|
||||
}
|
||||
|
||||
private AfterTransactionCommitExecutor getAfterTransactionCommmitExecutor() {
|
||||
return AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit();
|
||||
private boolean isEventAwareEntity(final Object object) {
|
||||
return object instanceof EventAwareEntity;
|
||||
}
|
||||
|
||||
private EventBus getEventBus() {
|
||||
return EventBusHolder.getInstance().getEventBus();
|
||||
private void doNotifiy(final Runnable runnable) {
|
||||
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(runnable);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.model;
|
||||
|
||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||
|
||||
/**
|
||||
* Interfaces which can be implemented by entities to be called when the entity
|
||||
* should fire an event because the entity has been created, updated or deleted.
|
||||
*/
|
||||
public interface EventAwareEntity {
|
||||
|
||||
/**
|
||||
* Fired for the Entity creation.
|
||||
*
|
||||
* @param descriptorEvent
|
||||
*/
|
||||
void fireCreateEvent(DescriptorEvent descriptorEvent);
|
||||
|
||||
/**
|
||||
* Fired for the Entity updation.
|
||||
*
|
||||
* @param descriptorEvent
|
||||
*/
|
||||
void fireUpdateEvent(DescriptorEvent descriptorEvent);
|
||||
|
||||
/**
|
||||
* Fired for the Entity deletion.
|
||||
*
|
||||
* @param descriptorEvent
|
||||
*/
|
||||
void fireDeleteEvent(DescriptorEvent descriptorEvent);
|
||||
}
|
||||
@@ -28,6 +28,10 @@ import javax.persistence.NamedSubgraph;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.ActionCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.ActionPropertyChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
@@ -35,6 +39,7 @@ import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||
|
||||
/**
|
||||
* JPA implementation of {@link Action}.
|
||||
@@ -49,7 +54,7 @@ import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||
// sub entities
|
||||
@SuppressWarnings("squid:S2160")
|
||||
public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Action {
|
||||
public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Action, EventAwareEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@@ -171,4 +176,20 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio
|
||||
return "Action [distributionSet=" + distributionSet + ", getId()=" + getId() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new ActionCreatedEvent(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new ActionPropertyChangeEvent(this,
|
||||
EntityPropertyChangeHelper.getChangeSet(Action.class, descriptorEvent)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireDeleteEvent(final DescriptorEvent descriptorEvent) {
|
||||
// there is no action deletion
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -33,8 +34,14 @@ import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetUpdateEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.DistributionSetTypeUndefinedException;
|
||||
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
@@ -45,6 +52,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetInfo;
|
||||
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||
|
||||
/**
|
||||
* Jpa implementation of {@link DistributionSet}.
|
||||
@@ -61,9 +69,13 @@ import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||
// sub entities
|
||||
@SuppressWarnings("squid:S2160")
|
||||
public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implements DistributionSet {
|
||||
public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implements DistributionSet, EventAwareEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String COMPLETE_PROPERTY = "complete";
|
||||
|
||||
private static final String DELETED_PROPERTY = "deleted";
|
||||
|
||||
@Column(name = "required_migration_step")
|
||||
private boolean requiredMigrationStep;
|
||||
|
||||
@@ -279,4 +291,30 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
return complete;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new DistributionCreatedEvent(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||
|
||||
final Map<String, AbstractPropertyChangeEvent<JpaDistributionSet>.Values> changeSet = EntityPropertyChangeHelper
|
||||
.getChangeSet(JpaDistributionSet.class, descriptorEvent);
|
||||
EventBusHolder.getInstance().getEventBus().post(new DistributionSetUpdateEvent(this));
|
||||
|
||||
if (changeSet.containsKey(DELETED_PROPERTY)) {
|
||||
final Boolean newDeleted = (Boolean) changeSet.get(DELETED_PROPERTY).getNewValue();
|
||||
if (newDeleted) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new DistributionDeletedEvent(getTenant(), getId()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireDeleteEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new DistributionDeletedEvent(getTenant(), getId()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,13 +25,17 @@ import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.RolloutPropertyChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.jpa.cache.CacheField;
|
||||
import org.eclipse.hawkbit.repository.jpa.cache.CacheKeys;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||
|
||||
/**
|
||||
* JPA implementation of a {@link Rollout}.
|
||||
@@ -44,7 +48,7 @@ import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||
// sub entities
|
||||
@SuppressWarnings("squid:S2160")
|
||||
public class JpaRollout extends AbstractJpaNamedEntity implements Rollout {
|
||||
public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, EventAwareEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@@ -197,4 +201,21 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout {
|
||||
+ ", getName()=" + getName() + ", getId()=" + getId() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||
// there is no rollout creation event
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new RolloutPropertyChangeEvent(this,
|
||||
EntityPropertyChangeHelper.getChangeSet(Rollout.class, descriptorEvent)));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireDeleteEvent(final DescriptorEvent descriptorEvent) {
|
||||
// there is no rollout deletion event
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,9 +25,13 @@ import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.RolloutGroupPropertyChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||
|
||||
/**
|
||||
* JPA entity definition of persisting a group of an rollout.
|
||||
@@ -40,7 +44,7 @@ import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||
// sub entities
|
||||
@SuppressWarnings("squid:S2160")
|
||||
public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGroup {
|
||||
public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGroup, EventAwareEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@@ -236,4 +240,19 @@ public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGr
|
||||
+ ", getId()=" + getId() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||
// there is no RolloutGroup created event
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new RolloutGroupPropertyChangeEvent(this,
|
||||
EntityPropertyChangeHelper.getChangeSet(RolloutGroup.class, descriptorEvent)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireDeleteEvent(final DescriptorEvent descriptorEvent) {
|
||||
// there is no RolloutGroup deleted event
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,10 @@ import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityChecker;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
|
||||
@@ -45,6 +49,7 @@ import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetInfo;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||
import org.springframework.data.domain.Persistable;
|
||||
|
||||
/**
|
||||
@@ -64,7 +69,7 @@ import org.springframework.data.domain.Persistable;
|
||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||
// sub entities
|
||||
@SuppressWarnings("squid:S2160")
|
||||
public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Long>, Target {
|
||||
public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Long>, Target, EventAwareEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Column(name = "controller_id", length = 64)
|
||||
@@ -222,6 +227,7 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Lon
|
||||
* @param securityToken
|
||||
* the securityToken to set
|
||||
*/
|
||||
@Override
|
||||
public void setSecurityToken(final String securityToken) {
|
||||
this.securityToken = securityToken;
|
||||
}
|
||||
@@ -231,4 +237,18 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Lon
|
||||
return "Target [controllerId=" + controllerId + ", getId()=" + getId() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new TargetCreatedEvent(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new TargetUpdatedEvent(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireDeleteEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new TargetDeletedEvent(getTenant(), getId()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import javax.persistence.Column;
|
||||
import javax.persistence.ConstraintMode;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EntityListeners;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.FetchType;
|
||||
@@ -37,7 +38,9 @@ import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetInfoUpdateEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
@@ -48,6 +51,7 @@ import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
||||
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.domain.Persistable;
|
||||
@@ -64,7 +68,8 @@ import org.springframework.data.domain.Persistable;
|
||||
@Table(name = "sp_target_info", indexes = {
|
||||
@Index(name = "sp_idx_target_info_02", columnList = "target_id,update_status") })
|
||||
@Entity
|
||||
public class JpaTargetInfo implements Persistable<Long>, TargetInfo {
|
||||
@EntityListeners(EntityPropertyChangeListener.class)
|
||||
public class JpaTargetInfo implements Persistable<Long>, TargetInfo, EventAwareEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TargetInfo.class);
|
||||
@@ -321,4 +326,19 @@ public class JpaTargetInfo implements Persistable<Long>, TargetInfo {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||
// there is no target info created event
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new TargetInfoUpdateEvent(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireDeleteEvent(final DescriptorEvent descriptorEvent) {
|
||||
// there is no target info deleted event
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.model.helper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.EntityInterceptor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* A singleton bean which holds the {@link EntityInterceptor} to have all
|
||||
* interceptors in spring beans.
|
||||
*
|
||||
*/
|
||||
public final class EntityInterceptorHolder {
|
||||
|
||||
private static final EntityInterceptorHolder SINGLETON = new EntityInterceptorHolder();
|
||||
|
||||
@Autowired(required = false)
|
||||
private final List<EntityInterceptor> entityInterceptors = new ArrayList<>();
|
||||
|
||||
private EntityInterceptorHolder() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the entity intreceptor holder singleton instance
|
||||
*/
|
||||
public static EntityInterceptorHolder getInstance() {
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
public List<EntityInterceptor> getEntityInterceptors() {
|
||||
return entityInterceptors;
|
||||
}
|
||||
}
|
||||
@@ -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.repository.jpa.model.helper;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
|
||||
import org.eclipse.persistence.queries.UpdateObjectQuery;
|
||||
import org.eclipse.persistence.sessions.changesets.DirectToFieldChangeRecord;
|
||||
|
||||
/**
|
||||
* Helper class to get the change set for the property changes in the Entity.
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public class EntityPropertyChangeHelper<T extends TenantAwareBaseEntity> {
|
||||
|
||||
/**
|
||||
* To get the map of entity property change set
|
||||
*
|
||||
* @param clazz
|
||||
* @param event
|
||||
* @return the map of the changeSet
|
||||
*/
|
||||
public static <T extends TenantAwareBaseEntity> Map<String, AbstractPropertyChangeEvent<T>.Values> getChangeSet(
|
||||
final Class<T> clazz, final DescriptorEvent event) {
|
||||
final T rolloutGroup = clazz.cast(event.getObject());
|
||||
final ObjectChangeSet changeSet = ((UpdateObjectQuery) event.getQuery()).getObjectChangeSet();
|
||||
return changeSet.getChanges().stream().filter(record -> record instanceof DirectToFieldChangeRecord)
|
||||
.map(record -> (DirectToFieldChangeRecord) record)
|
||||
.collect(Collectors.toMap(record -> record.getAttribute(),
|
||||
record -> new AbstractPropertyChangeEvent<T>(rolloutGroup, null).new Values(
|
||||
record.getOldValue(), record.getNewValue())));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
public class MethodSecurityUtil {
|
||||
|
||||
private static final Set<String> METHOD_SECURITY_EXCLUSION = new HashSet<>();
|
||||
|
||||
static {
|
||||
METHOD_SECURITY_EXCLUSION.add("equals");
|
||||
METHOD_SECURITY_EXCLUSION.add("toString");
|
||||
METHOD_SECURITY_EXCLUSION.add("hashCode");
|
||||
METHOD_SECURITY_EXCLUSION.add("clone");
|
||||
METHOD_SECURITY_EXCLUSION.add("setEnvironment");
|
||||
// this method shouldn't be public on the DeploymentManagemeht but it is
|
||||
METHOD_SECURITY_EXCLUSION.add("setOverrideObsoleteUpdateActions");
|
||||
METHOD_SECURITY_EXCLUSION.add("isOverrideObsoleteUpdateActions");
|
||||
// this method must be public accessible without security because it's
|
||||
// necessary to acccess
|
||||
// the security-token of a target without being authenticated because
|
||||
// the security-token is
|
||||
// the authentication process
|
||||
// ControllerManagement#getSecurityTokenByControllerId()
|
||||
METHOD_SECURITY_EXCLUSION.add("getSecurityTokenByControllerId");
|
||||
}
|
||||
|
||||
/**
|
||||
* asserts that the given methods are annotated with the
|
||||
* {@link PreAuthorize} annotation for security. Inherited methods are not
|
||||
* checked. The following methods are excluded due inherited from
|
||||
* {@link Object}, like equals() or toString().
|
||||
*
|
||||
* @param clazz
|
||||
* the class to retrieve the public declared methods
|
||||
*/
|
||||
public static void assertDeclaredMethodsContainsPreAuthorizeAnnotaions(final Class<?> clazz) {
|
||||
final Method[] declaredMethods = clazz.getDeclaredMethods();
|
||||
for (final Method method : declaredMethods) {
|
||||
if (!METHOD_SECURITY_EXCLUSION.contains(method.getName()) && !method.isSynthetic()
|
||||
&& Modifier.isPublic(method.getModifiers())) {
|
||||
final PreAuthorize annotation = method.getAnnotation(PreAuthorize.class);
|
||||
assertThat(annotation).as(
|
||||
"The public method " + method.getName() + " is not annoated with @PreAuthorize, security leak?")
|
||||
.isNotNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,13 +34,13 @@ import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupErrorAction
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupErrorCondition;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupStatus;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition;
|
||||
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroupConditions;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Description;
|
||||
@@ -56,9 +56,6 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
/**
|
||||
* Junit tests for RolloutManagment.
|
||||
*
|
||||
* @author Michael Hirsch
|
||||
*
|
||||
*/
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("Rollout Management")
|
||||
|
||||
@@ -14,10 +14,10 @@ import java.io.ByteArrayInputStream;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TenantMetaData;
|
||||
import org.eclipse.hawkbit.repository.report.model.TenantUsage;
|
||||
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
|
||||
import org.junit.Test;
|
||||
@@ -30,15 +30,6 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
||||
@Stories("System Management")
|
||||
public class SystemManagementTest extends AbstractJpaIntegrationTestWithMongoDB {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that you can create a tenant without setting the necessary security context which holds a current tenant")
|
||||
public void createInitialTenantWithoutSecurityContext() {
|
||||
securityRule.clear();
|
||||
final String tenantToBeCreated = "newTenantToCreate";
|
||||
final TenantMetaData tenantMetadata = systemManagement.getTenantMetadata(tenantToBeCreated);
|
||||
assertThat(tenantMetadata).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that findTenants returns all tenants and not only restricted to the tenant which currently is logged in")
|
||||
public void findTenantsReturnsAllTenantsNotOnlyWhichLoggedIn() throws Exception {
|
||||
@@ -109,26 +100,27 @@ public class SystemManagementTest extends AbstractJpaIntegrationTestWithMongoDB
|
||||
|
||||
for (int i = 0; i < tenants; i++) {
|
||||
final String tenantname = "tenant" + i;
|
||||
securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("bumlux", tenantname), () -> {
|
||||
systemManagement.getTenantMetadata(tenantname);
|
||||
if (artifactSize > 0) {
|
||||
createTestArtifact(random);
|
||||
createDeletedTestArtifact(random);
|
||||
}
|
||||
if (targets > 0) {
|
||||
final List<Target> createdTargets = createTestTargets(targets);
|
||||
if (updates > 0) {
|
||||
for (int x = 0; x < updates; x++) {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("to be deployed" + x,
|
||||
true);
|
||||
|
||||
deploymentManagement.assignDistributionSet(ds, createdTargets);
|
||||
securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("bumlux", tenantname, true, true,
|
||||
SpringEvalExpressions.SYSTEM_ROLE), () -> {
|
||||
systemManagement.getTenantMetadata(tenantname);
|
||||
if (artifactSize > 0) {
|
||||
createTestArtifact(random);
|
||||
createDeletedTestArtifact(random);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (targets > 0) {
|
||||
final List<Target> createdTargets = createTestTargets(targets);
|
||||
if (updates > 0) {
|
||||
for (int x = 0; x < updates; x++) {
|
||||
final DistributionSet ds = testdataFactory
|
||||
.createDistributionSet("to be deployed" + x, true);
|
||||
|
||||
return null;
|
||||
});
|
||||
deploymentManagement.assignDistributionSet(ds, createdTargets);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
return random;
|
||||
|
||||
@@ -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.repository.jpa.eventbus;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.event.Event;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetInfoUpdateEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.fest.assertions.api.Assertions;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("Entity Events")
|
||||
public class RepositoryEntityEventTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private EventBus eventBus;
|
||||
|
||||
private final MyEventListener eventListener = new MyEventListener();
|
||||
|
||||
@Before
|
||||
public void beforeTest() {
|
||||
eventListener.queue.clear();
|
||||
eventBus.register(eventListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that the target created event is published when a target has been created")
|
||||
public void targetCreatedEventIsPublished() throws InterruptedException {
|
||||
final Target createdTarget = targetManagement.createTarget(entityFactory.generateTarget("12345"));
|
||||
|
||||
final TargetCreatedEvent targetCreatedEvent = eventListener.waitForEvent(TargetCreatedEvent.class, 1,
|
||||
TimeUnit.SECONDS);
|
||||
assertThat(targetCreatedEvent).isNotNull();
|
||||
assertThat(targetCreatedEvent.getEntity().getId()).isEqualTo(createdTarget.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that the target update event is published when a target has been updated")
|
||||
public void targetUpdateEventIsPublished() throws InterruptedException {
|
||||
final Target createdTarget = targetManagement.createTarget(entityFactory.generateTarget("12345"));
|
||||
createdTarget.setName("updateName");
|
||||
targetManagement.updateTarget(createdTarget);
|
||||
|
||||
final TargetUpdatedEvent targetUpdatedEvent = eventListener.waitForEvent(TargetUpdatedEvent.class, 1,
|
||||
TimeUnit.SECONDS);
|
||||
assertThat(targetUpdatedEvent).isNotNull();
|
||||
assertThat(targetUpdatedEvent.getEntity().getId()).isEqualTo(createdTarget.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that the target info update event is published when a target info has been updated")
|
||||
public void targetInfoUpdateEventIsPublished() throws InterruptedException {
|
||||
final Target createdTarget = targetManagement.createTarget(entityFactory.generateTarget("12345"));
|
||||
controllerManagament.updateTargetStatus(createdTarget.getTargetInfo(), TargetUpdateStatus.PENDING,
|
||||
System.currentTimeMillis(), URI.create("http://127.0.0.1"));
|
||||
|
||||
final TargetInfoUpdateEvent targetInfoUpdatedEvent = eventListener.waitForEvent(TargetInfoUpdateEvent.class, 1,
|
||||
TimeUnit.SECONDS);
|
||||
assertThat(targetInfoUpdatedEvent).isNotNull();
|
||||
assertThat(targetInfoUpdatedEvent.getEntity().getTarget().getId()).isEqualTo(createdTarget.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that the target deleted event is published when a target has been deleted")
|
||||
public void targetDeletedEventIsPublished() throws InterruptedException {
|
||||
final Target createdTarget = targetManagement.createTarget(entityFactory.generateTarget("12345"));
|
||||
|
||||
targetManagement.deleteTargets(createdTarget.getId());
|
||||
|
||||
final TargetDeletedEvent targetDeletedEvent = eventListener.waitForEvent(TargetDeletedEvent.class, 1,
|
||||
TimeUnit.SECONDS);
|
||||
assertThat(targetDeletedEvent).isNotNull();
|
||||
assertThat(targetDeletedEvent.getTargetId()).isEqualTo(createdTarget.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that the distribution set created event is published when a distribution set has been created")
|
||||
public void distributionSetCreatedEventIsPublished() throws InterruptedException {
|
||||
final DistributionSet generateDistributionSet = entityFactory.generateDistributionSet();
|
||||
generateDistributionSet.setName("dsEventTest");
|
||||
generateDistributionSet.setVersion("1");
|
||||
final DistributionSet createDistributionSet = distributionSetManagement
|
||||
.createDistributionSet(generateDistributionSet);
|
||||
|
||||
final DistributionCreatedEvent dsCreatedEvent = eventListener.waitForEvent(DistributionCreatedEvent.class, 1,
|
||||
TimeUnit.SECONDS);
|
||||
assertThat(dsCreatedEvent).isNotNull();
|
||||
assertThat(dsCreatedEvent.getEntity().getId()).isEqualTo(createDistributionSet.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that the distribution set deleted event is published when a distribution set has been deleted")
|
||||
public void distributionSetDeletedEventIsPublished() throws InterruptedException {
|
||||
|
||||
final DistributionSet generateDistributionSet = entityFactory.generateDistributionSet();
|
||||
generateDistributionSet.setName("dsEventTest");
|
||||
generateDistributionSet.setVersion("1");
|
||||
final DistributionSet createDistributionSet = distributionSetManagement
|
||||
.createDistributionSet(generateDistributionSet);
|
||||
|
||||
distributionSetManagement.deleteDistributionSet(createDistributionSet);
|
||||
|
||||
final DistributionDeletedEvent dsDeletedEvent = eventListener.waitForEvent(DistributionDeletedEvent.class, 1,
|
||||
TimeUnit.SECONDS);
|
||||
assertThat(dsDeletedEvent).isNotNull();
|
||||
assertThat(dsDeletedEvent.getDistributionSetId()).isEqualTo(createDistributionSet.getId());
|
||||
}
|
||||
|
||||
private class MyEventListener {
|
||||
|
||||
private final BlockingQueue<Event> queue = new LinkedBlockingQueue<>();
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(final Event event) {
|
||||
queue.offer(event);
|
||||
}
|
||||
|
||||
public <T> T waitForEvent(final Class<T> eventType, final long timeout, final TimeUnit timeUnit)
|
||||
throws InterruptedException {
|
||||
Event event = null;
|
||||
while ((event = queue.poll(timeout, timeUnit)) != null) {
|
||||
if (event.getClass().isAssignableFrom(eventType)) {
|
||||
return (T) event;
|
||||
}
|
||||
}
|
||||
Assertions.fail("Missing event " + eventType + " within timeout " + timeout + " " + timeUnit);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.repository.jpa.model;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityInterceptorHolder;
|
||||
import org.eclipse.hawkbit.repository.model.EntityInterceptor;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.junit.Test;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
/**
|
||||
* Test the entity listener interceptor.
|
||||
*/
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("Entity Listener Interceptor")
|
||||
public class EntityInterceptorListenerTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Override
|
||||
public void after() {
|
||||
EntityInterceptorHolder.getInstance().getEntityInterceptors().clear();
|
||||
super.after();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that the pre persist is called after a entity creation.")
|
||||
public void prePersistIsCalledWhenPersistingATarget() {
|
||||
executePersistAndAssertCallbackResult(new PrePersistEntityListener());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that the post persist is called after a entity creation.")
|
||||
public void postPersistIsCalledWhenPersistingATarget() {
|
||||
executePersistAndAssertCallbackResult(new PostPersistEntityListener());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that the post load is called after a entity is loaded.")
|
||||
public void postLoadIsCalledWhenLoadATarget() {
|
||||
final PostLoadEntityListener postLoadEntityListener = new PostLoadEntityListener();
|
||||
EntityInterceptorHolder.getInstance().getEntityInterceptors().add(postLoadEntityListener);
|
||||
|
||||
final Target targetToBeCreated = entityFactory.generateTarget("targetToBeCreated");
|
||||
|
||||
targetManagement.createTarget(targetToBeCreated);
|
||||
|
||||
final Target loadedTarget = targetManagement.findTargetByControllerID(targetToBeCreated.getControllerId());
|
||||
assertThat(postLoadEntityListener.getEntity()).isNotNull();
|
||||
assertThat(postLoadEntityListener.getEntity()).isEqualTo(loadedTarget);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that the pre update is called after a entity update.")
|
||||
public void preUpdateIsCalledWhenUpdateATarget() {
|
||||
executeUpdateAndAssertCallbackResult(new PreUpdateEntityListener());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that the post update is called after a entity update.")
|
||||
public void postUpdateIsCalledWhenUpdateATarget() {
|
||||
executeUpdateAndAssertCallbackResult(new PostUpdateEntityListener());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that the pre remove is called after a entity deletion.")
|
||||
public void preRemoveIsCalledWhenDeletingATarget() {
|
||||
executeDeleteAndAssertCallbackResult(new PreRemoveEntityListener());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that the post remove is called after a entity deletion.")
|
||||
public void postRemoveIsCalledWhenDeletingATarget() {
|
||||
executeDeleteAndAssertCallbackResult(new PostRemoveEntityListener());
|
||||
}
|
||||
|
||||
private void executePersistAndAssertCallbackResult(final AbstractEntityListener entityInterceptor) {
|
||||
final Target targetToBeCreated = entityFactory.generateTarget("targetToBeCreated");
|
||||
addListenerAndCreateTarget(entityInterceptor, targetToBeCreated);
|
||||
|
||||
assertThat(entityInterceptor.getEntity()).isNotNull();
|
||||
assertThat(entityInterceptor.getEntity()).isEqualTo(targetToBeCreated);
|
||||
}
|
||||
|
||||
private void executeUpdateAndAssertCallbackResult(final AbstractEntityListener entityInterceptor) {
|
||||
Target updateTarget = addListenerAndCreateTarget(entityInterceptor,
|
||||
entityFactory.generateTarget("targetToBeCreated"));
|
||||
updateTarget.setDescription("New");
|
||||
|
||||
updateTarget = targetManagement.updateTarget(updateTarget);
|
||||
|
||||
assertThat(entityInterceptor.getEntity()).isNotNull();
|
||||
assertThat(entityInterceptor.getEntity()).isEqualTo(updateTarget);
|
||||
}
|
||||
|
||||
private void executeDeleteAndAssertCallbackResult(final AbstractEntityListener entityInterceptor) {
|
||||
EntityInterceptorHolder.getInstance().getEntityInterceptors().add(entityInterceptor);
|
||||
final SoftwareModuleType type = softwareManagement
|
||||
.createSoftwareModuleType(entityFactory.generateSoftwareModuleType("test", "test", "test", 1));
|
||||
|
||||
softwareManagement.deleteSoftwareModuleType(type);
|
||||
assertThat(entityInterceptor.getEntity()).isNotNull();
|
||||
assertThat(entityInterceptor.getEntity()).isEqualTo(type);
|
||||
}
|
||||
|
||||
private Target addListenerAndCreateTarget(final AbstractEntityListener entityInterceptor,
|
||||
final Target targetToBeCreated) {
|
||||
EntityInterceptorHolder.getInstance().getEntityInterceptors().add(entityInterceptor);
|
||||
return targetManagement.createTarget(targetToBeCreated);
|
||||
}
|
||||
|
||||
private static abstract class AbstractEntityListener implements EntityInterceptor {
|
||||
|
||||
private Object entity;
|
||||
|
||||
public Object getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
public void setEntity(final Object entity) {
|
||||
this.entity = entity;
|
||||
}
|
||||
}
|
||||
|
||||
private static class PrePersistEntityListener extends AbstractEntityListener {
|
||||
@Override
|
||||
public void prePersist(final Object entity) {
|
||||
setEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
private static class PostPersistEntityListener extends AbstractEntityListener {
|
||||
@Override
|
||||
public void postPersist(final Object entity) {
|
||||
setEntity(entity);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class PostLoadEntityListener extends AbstractEntityListener {
|
||||
@Override
|
||||
public void postLoad(final Object entity) {
|
||||
setEntity(entity);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class PreUpdateEntityListener extends AbstractEntityListener {
|
||||
@Override
|
||||
public void preUpdate(final Object entity) {
|
||||
setEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
private static class PostUpdateEntityListener extends AbstractEntityListener {
|
||||
@Override
|
||||
public void postUpdate(final Object entity) {
|
||||
setEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
private static class PreRemoveEntityListener extends AbstractEntityListener {
|
||||
@Override
|
||||
public void preRemove(final Object entity) {
|
||||
setEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
private static class PostRemoveEntityListener extends AbstractEntityListener {
|
||||
@Override
|
||||
public void postRemove(final Object entity) {
|
||||
setEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ import org.hamcrest.Matchers;
|
||||
/**
|
||||
* Matcher for {@link BaseEntity}.
|
||||
*/
|
||||
public class BaseEntityMatcher {
|
||||
public final class BaseEntityMatcher {
|
||||
|
||||
private BaseEntityMatcher() {
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.test.util;
|
||||
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.SYSTEM_ROLE;
|
||||
|
||||
import org.eclipse.hawkbit.ExcludePathAwareShallowETagFilter;
|
||||
import org.eclipse.hawkbit.TestConfiguration;
|
||||
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||
@@ -60,7 +63,7 @@ import org.springframework.web.context.WebApplicationContext;
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@WebAppConfiguration
|
||||
@ActiveProfiles({ "test" })
|
||||
@WithUser(principal = "bumlux", allSpPermissions = true, authorities = "ROLE_CONTROLLER")
|
||||
@WithUser(principal = "bumlux", allSpPermissions = true, authorities = { CONTROLLER_ROLE, SYSTEM_ROLE })
|
||||
@SpringApplicationConfiguration(classes = { TestConfiguration.class })
|
||||
// destroy the context after each test class because otherwise we get problem
|
||||
// when context is
|
||||
@@ -226,7 +229,7 @@ public abstract class AbstractIntegrationTest implements EnvironmentAware {
|
||||
createTestdatabaseAndStart();
|
||||
}
|
||||
|
||||
private static void createTestdatabaseAndStart() {
|
||||
private static synchronized void createTestdatabaseAndStart() {
|
||||
if ("MYSQL".equals(System.getProperty("spring.jpa.database"))) {
|
||||
tesdatabase = new CIMySqlTestDatabase();
|
||||
tesdatabase.before();
|
||||
|
||||
@@ -13,11 +13,14 @@ import java.util.List;
|
||||
import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
public class JpaTestRepositoryManagement implements TestRepositoryManagement {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(JpaTestRepositoryManagement.class);
|
||||
@Autowired
|
||||
private TenantAwareCacheManager cacheManager;
|
||||
|
||||
@@ -28,6 +31,7 @@ public class JpaTestRepositoryManagement implements TestRepositoryManagement {
|
||||
private SystemManagement systemManagement;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void clearTestRepository() {
|
||||
deleteAllRepos();
|
||||
cacheManager.getDirectCacheNames().forEach(name -> cacheManager.getDirectCache(name).clear());
|
||||
@@ -43,7 +47,7 @@ public class JpaTestRepositoryManagement implements TestRepositoryManagement {
|
||||
return null;
|
||||
});
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
LOGGER.error("Error hile delete tenant", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ package org.eclipse.hawkbit.repository.test.util;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
@@ -191,16 +191,17 @@ public class TestdataFactory {
|
||||
public DistributionSet createDistributionSet(final String prefix, final String version,
|
||||
final boolean isRequiredMigrationStep) {
|
||||
|
||||
final SoftwareModule appMod = softwareManagement.createSoftwareModule(entityFactory.generateSoftwareModule(
|
||||
findOrCreateSoftwareModuleType(SM_TYPE_APP, Integer.MAX_VALUE), prefix + SM_TYPE_APP,
|
||||
version + "." + new Random().nextInt(100), LOREM.words(20), prefix + " vendor Limited, California"));
|
||||
final SoftwareModule appMod = softwareManagement.createSoftwareModule(
|
||||
entityFactory.generateSoftwareModule(findOrCreateSoftwareModuleType(SM_TYPE_APP, Integer.MAX_VALUE),
|
||||
prefix + SM_TYPE_APP, version + "." + new SecureRandom().nextInt(100), LOREM.words(20),
|
||||
prefix + " vendor Limited, California"));
|
||||
final SoftwareModule runtimeMod = softwareManagement
|
||||
.createSoftwareModule(entityFactory.generateSoftwareModule(findOrCreateSoftwareModuleType(SM_TYPE_RT),
|
||||
prefix + "app runtime", version + "." + new Random().nextInt(100), LOREM.words(20),
|
||||
prefix + "app runtime", version + "." + new SecureRandom().nextInt(100), LOREM.words(20),
|
||||
prefix + " vendor GmbH, Stuttgart, Germany"));
|
||||
final SoftwareModule osMod = softwareManagement
|
||||
.createSoftwareModule(entityFactory.generateSoftwareModule(findOrCreateSoftwareModuleType(SM_TYPE_OS),
|
||||
prefix + " Firmware", version + "." + new Random().nextInt(100), LOREM.words(20),
|
||||
prefix + " Firmware", version + "." + new SecureRandom().nextInt(100), LOREM.words(20),
|
||||
prefix + " vendor Limited Inc, California"));
|
||||
|
||||
return distributionSetManagement
|
||||
|
||||
@@ -28,16 +28,12 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
public class WithSpringAuthorityRule implements TestRule {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.junit.rules.TestRule#apply(org.junit.runners.model.Statement,
|
||||
* org.junit.runner.Description)
|
||||
*/
|
||||
@Override
|
||||
public Statement apply(final Statement base, final Description description) {
|
||||
return new Statement() {
|
||||
@Override
|
||||
// throwable comes from jnuit evaluate signature
|
||||
@SuppressWarnings("squid:S00112")
|
||||
public void evaluate() throws Throwable {
|
||||
final SecurityContext oldContext = before(description);
|
||||
try {
|
||||
@@ -49,33 +45,28 @@ public class WithSpringAuthorityRule implements TestRule {
|
||||
};
|
||||
}
|
||||
|
||||
private SecurityContext before(final Description description) throws Throwable {
|
||||
private SecurityContext before(final Description description) {
|
||||
final SecurityContext oldContext = SecurityContextHolder.getContext();
|
||||
WithUser annotation = description.getAnnotation(WithUser.class);
|
||||
if (annotation == null) {
|
||||
annotation = description.getTestClass().getAnnotation(WithUser.class);
|
||||
}
|
||||
if (annotation != null) {
|
||||
setSecurityContext(annotation);
|
||||
if (annotation.autoCreateTenant()) {
|
||||
SystemManagementHolder.getInstance().getSystemManagement().getTenantMetadata(annotation.tenantId());
|
||||
createTenant(annotation.tenantId());
|
||||
}
|
||||
setSecurityContext(annotation);
|
||||
}
|
||||
return oldContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param annotation
|
||||
*/
|
||||
|
||||
private void setSecurityContext(final WithUser annotation) {
|
||||
SecurityContextHolder.setContext(new SecurityContext() {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public void setAuthentication(final Authentication authentication) {
|
||||
// nothing todo
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,7 +104,8 @@ public class WithSpringAuthorityRule implements TestRule {
|
||||
if (addPermission) {
|
||||
allPermissions.add(permissionName);
|
||||
}
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
// don't want to log this exceptions.
|
||||
} catch (@SuppressWarnings("squid:S1166") IllegalArgumentException | IllegalAccessException e) {
|
||||
// nope
|
||||
}
|
||||
}
|
||||
@@ -129,18 +121,17 @@ public class WithSpringAuthorityRule implements TestRule {
|
||||
private void after(final SecurityContext oldContext) {
|
||||
SecurityContextHolder.setContext(oldContext);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clears the current security context.
|
||||
*/
|
||||
public void clear()
|
||||
{
|
||||
public void clear() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable
|
||||
* @return
|
||||
* @return the callable result
|
||||
* @throws Exception
|
||||
*/
|
||||
public <T> T runAsPrivileged(final Callable<T> callable) throws Exception {
|
||||
@@ -148,17 +139,17 @@ public class WithSpringAuthorityRule implements TestRule {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param withUser
|
||||
* @param callable
|
||||
* @return
|
||||
* @return callable result
|
||||
* @throws Exception
|
||||
*/
|
||||
public <T> T runAs(final WithUser withUser, final Callable<T> callable) throws Exception {
|
||||
final SecurityContext oldContext = SecurityContextHolder.getContext();
|
||||
setSecurityContext(withUser);
|
||||
if (withUser.autoCreateTenant()) {
|
||||
SystemManagementHolder.getInstance().getSystemManagement().getTenantMetadata(withUser.tenantId());
|
||||
createTenant(withUser.tenantId());
|
||||
}
|
||||
try {
|
||||
return callable.call();
|
||||
@@ -167,10 +158,20 @@ public class WithSpringAuthorityRule implements TestRule {
|
||||
}
|
||||
}
|
||||
|
||||
private void createTenant(final String tenantId) {
|
||||
final SecurityContext oldContext = SecurityContextHolder.getContext();
|
||||
setSecurityContext(privilegedUser());
|
||||
try {
|
||||
SystemManagementHolder.getInstance().getSystemManagement().getTenantMetadata(tenantId);
|
||||
} finally {
|
||||
after(oldContext);
|
||||
}
|
||||
}
|
||||
|
||||
public static WithUser withUser(final String principal, final String... authorities) {
|
||||
return withUserAndTenant(principal, "default", true, true, authorities);
|
||||
}
|
||||
|
||||
|
||||
public static WithUser withUser(final String principal, final boolean allSpPermision, final String... authorities) {
|
||||
return withUserAndTenant(principal, "default", true, allSpPermision, authorities);
|
||||
}
|
||||
@@ -185,6 +186,15 @@ public class WithSpringAuthorityRule implements TestRule {
|
||||
|
||||
public static WithUser withUserAndTenant(final String principal, final String tenant,
|
||||
final boolean autoCreateTenant, final boolean allSpPermission, final String... authorities) {
|
||||
return createWithUser(principal, tenant, autoCreateTenant, allSpPermission, authorities);
|
||||
}
|
||||
|
||||
private static WithUser privilegedUser() {
|
||||
return createWithUser("bumlux", "default", true, true, new String[] { "ROLE_CONTROLLER", "ROLE_SYSTEM_CODE" });
|
||||
}
|
||||
|
||||
private static WithUser createWithUser(final String principal, final String tenant, final boolean autoCreateTenant,
|
||||
final boolean allSpPermission, final String... authorities) {
|
||||
return new WithUser() {
|
||||
|
||||
@Override
|
||||
@@ -214,7 +224,7 @@ public class WithSpringAuthorityRule implements TestRule {
|
||||
|
||||
@Override
|
||||
public String[] removeFromAllPermission() {
|
||||
return null;
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -222,65 +232,10 @@ public class WithSpringAuthorityRule implements TestRule {
|
||||
return tenant;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.hawkbit.WithUser#autoCreateTenant()
|
||||
*/
|
||||
@Override
|
||||
public boolean autoCreateTenant() {
|
||||
return autoCreateTenant;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static WithUser privilegedUser() {
|
||||
return new WithUser() {
|
||||
|
||||
@Override
|
||||
public Class<? extends Annotation> annotationType() {
|
||||
return WithUser.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String principal() {
|
||||
return "bumlux";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String credentials() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] authorities() {
|
||||
return new String[] { "ROLE_CONTROLLER" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allSpPermissions() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] removeFromAllPermission() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tenantId() {
|
||||
return "default";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.hawkbit.WithUser#autoCreateTenant()
|
||||
*/
|
||||
@Override
|
||||
public boolean autoCreateTenant() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user