Removed the extra level of abstraction and modified the code

accordingly.
This commit is contained in:
GAH6KOR
2016-07-21 12:39:54 +02:00
parent 7afb2f996f
commit 5f1db53def
12 changed files with 1673 additions and 1687 deletions

View File

@@ -1,189 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.jpa.model;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
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.DistributionCreatedEvent;
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetUpdateEvent;
import org.eclipse.hawkbit.repository.eventbus.event.RolloutGroupPropertyChangeEvent;
import org.eclipse.hawkbit.repository.eventbus.event.RolloutPropertyChangeEvent;
import org.eclipse.hawkbit.repository.eventbus.event.TargetCreatedEvent;
import org.eclipse.hawkbit.repository.eventbus.event.TargetInfoUpdateEvent;
import org.eclipse.hawkbit.repository.eventbus.event.TargetUpdatedEvent;
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
import org.eclipse.hawkbit.repository.jpa.model.DescriptorEventDetails.ActionType;
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.internal.sessions.ObjectChangeSet;
import org.eclipse.persistence.queries.UpdateObjectQuery;
import org.eclipse.persistence.sessions.changesets.DirectToFieldChangeRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.eventbus.EventBus;
/**
* Implementation of @link{AbstractDescriptorEventVisitor} .Publishes the
* appropriate event after any action on entity like create/update.
*
*/
public class AbstractDescriptorEventVisitorImpl implements
AbstractDescriptorEventVisitor {
private static final String COMPLETE = "complete";
private static final Logger LOG = LoggerFactory
.getLogger(AbstractDescriptorEventVisitorImpl.class);
@Override
public void publishEventPostAction(final DescriptorEventDetails event) {
Method method = null;
DescriptorEvent descriptorEvent = event.getDescriptorEvent();
ActionType actiontype = event.getActiontype();
try {
method = getMethod(descriptorEvent, actiontype);
if (method != null) {
method.invoke(this, descriptorEvent.getObject(),
descriptorEvent);
}
} catch (NoSuchMethodException | SecurityException
| IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
LOG.info(
"Exception when invoking approriate method to publis event {}",
e);
}
}
private Method getMethod(DescriptorEvent descriptorEvent,
ActionType actiontype) throws NoSuchMethodException {
if (actiontype == ActionType.UPDATE) {
return this.getClass().getMethod("publishEventAfterUpdate",
descriptorEvent.getObject().getClass(),
DescriptorEvent.class);
} else if (actiontype == ActionType.CREATE) {
return this.getClass().getMethod("publishEventAfterCreate",
descriptorEvent.getObject().getClass(),
DescriptorEvent.class);
}
return null;
}
public void publishEventAfterCreate(JpaAction action, DescriptorEvent event) {
if (action.getRollout() != null) {
getAfterTransactionCommmitExecutor().afterCommit(
() -> getEventBus().post(new ActionCreatedEvent(action)));
}
}
public void publishEventAfterCreate(JpaTarget target, DescriptorEvent event) {
getAfterTransactionCommmitExecutor().afterCommit(
() -> getEventBus().post(new TargetCreatedEvent(target)));
}
public void publishEventAfterCreate(JpaDistributionSet ds,
DescriptorEvent event) {
getAfterTransactionCommmitExecutor().afterCommit(
() -> getEventBus().post(new DistributionCreatedEvent(ds)));
}
public void publishEventAfterUpdate(JpaAction action, DescriptorEvent event) {
getAfterTransactionCommmitExecutor().afterCommit(
() -> getEventBus().post(
new ActionPropertyChangeEvent(action, getChangeSet(
Action.class, event))));
}
public void publishEventAfterUpdate(JpaTarget target, DescriptorEvent event) {
getAfterTransactionCommmitExecutor().afterCommit(
() -> getEventBus().post(new TargetUpdatedEvent(target)));
}
public void publishEventAfterUpdate(JpaTargetInfo targetInfo,
DescriptorEvent event) {
getAfterTransactionCommmitExecutor()
.afterCommit(
() -> getEventBus().post(
new TargetInfoUpdateEvent(targetInfo)));
}
public void publishEventAfterUpdate(JpaRollout entity, DescriptorEvent event) {
getAfterTransactionCommmitExecutor().afterCommit(
() -> getEventBus().post(
new RolloutPropertyChangeEvent(entity, getChangeSet(
Rollout.class, event))));
}
public void publishEventAfterUpdate(JpaRolloutGroup entity,
DescriptorEvent event) {
getAfterTransactionCommmitExecutor().afterCommit(
() -> getEventBus().post(
new RolloutGroupPropertyChangeEvent(entity,
getChangeSet(RolloutGroup.class, event))));
}
public void publishEventAfterUpdate(JpaDistributionSet entity,
DescriptorEvent event) {
Map<String, AbstractPropertyChangeEvent<JpaDistributionSet>.Values> changeSet = getChangeSet(
JpaDistributionSet.class, event);
if (changeSet.containsKey(COMPLETE)
&& changeSet.get(COMPLETE).getOldValue().equals(false)
&& changeSet.get(COMPLETE).getNewValue().equals(true)) {
getAfterTransactionCommmitExecutor().afterCommit(
() -> getEventBus().post(
new DistributionCreatedEvent(entity)));
}
getAfterTransactionCommmitExecutor().afterCommit(
() -> getEventBus()
.post(new DistributionSetUpdateEvent(entity)));
}
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())));
}
private AfterTransactionCommitExecutor getAfterTransactionCommmitExecutor() {
return AfterTransactionCommitExecutorHolder.getInstance()
.getAfterCommit();
}
private EventBus getEventBus() {
return EventBusHolder.getInstance().getEventBus();
}
}

View File

@@ -32,7 +32,7 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@MappedSuperclass @MappedSuperclass
@Access(AccessType.FIELD) @Access(AccessType.FIELD)
@EntityListeners({ AuditingEntityListener.class, CacheFieldEntityListener.class, EntityPropertyChangeListener.class }) @EntityListeners({ AuditingEntityListener.class, CacheFieldEntityListener.class, EntityPropertyChangeListener.class })
public abstract class AbstractJpaBaseEntity implements BaseEntity,AcceptVisitor { public abstract class AbstractJpaBaseEntity implements BaseEntity {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@Id @Id
@@ -179,8 +179,4 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity,AcceptVisitor
} }
@Override
public void postActionOnEntity(AbstractDescriptorEventVisitor visitor, DescriptorEventDetails eventDetails){
visitor.publishEventPostAction(eventDetails);
}
} }

View File

@@ -1,18 +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.model;
/**
* Interface to accept visitor @link{AbstractDescriptorEventVisitor}.
*
*/
public interface AcceptVisitor {
public void postActionOnEntity(AbstractDescriptorEventVisitor visitor,
DescriptorEventDetails eventDetails);
}

View File

@@ -8,7 +8,6 @@
*/ */
package org.eclipse.hawkbit.repository.jpa.model; package org.eclipse.hawkbit.repository.jpa.model;
import org.eclipse.hawkbit.repository.jpa.model.DescriptorEventDetails.ActionType;
import org.eclipse.persistence.descriptors.DescriptorEvent; import org.eclipse.persistence.descriptors.DescriptorEvent;
import org.eclipse.persistence.descriptors.DescriptorEventAdapter; import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
@@ -18,19 +17,23 @@ import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
*/ */
public class EntityPropertyChangeListener extends DescriptorEventAdapter { public class EntityPropertyChangeListener extends DescriptorEventAdapter {
@Override @Override
public void postInsert(final DescriptorEvent event) { public void postInsert(final DescriptorEvent event) {
AbstractDescriptorEventVisitor visitor = new AbstractDescriptorEventVisitorImpl();
((AbstractJpaBaseEntity) event.getObject()).postActionOnEntity(visitor, final Object object = event.getObject();
new DescriptorEventDetails(ActionType.CREATE, event)); if (object instanceof EventAwareEntity) {
((EventAwareEntity) object).fireCreateEvent(object,event);
}
}
@Override
public void postUpdate(final DescriptorEvent event) {
final Object object = event.getObject();
if (object instanceof EventAwareEntity) {
((EventAwareEntity) object).fireUpdateEvent(object,event);
}
}
}
@Override
public void postUpdate(final DescriptorEvent event) {
AbstractDescriptorEventVisitor visitor = new AbstractDescriptorEventVisitorImpl();
((AbstractJpaBaseEntity) event.getObject()).postActionOnEntity(visitor,
new DescriptorEventDetails(ActionType.UPDATE, event));
}
} }

View File

@@ -8,12 +8,13 @@
*/ */
package org.eclipse.hawkbit.repository.jpa.model; package org.eclipse.hawkbit.repository.jpa.model;
/** import org.eclipse.persistence.descriptors.DescriptorEvent;
*
* Interface defining the action to be performed after entity is public interface EventAwareEntity<T> {
* created/updated.
* public void fireCreateEvent(T t,DescriptorEvent descriptorEvent);
*/
public interface AbstractDescriptorEventVisitor { public void fireUpdateEvent(T t,DescriptorEvent descriptorEvent);
void publishEventPostAction(DescriptorEventDetails eventDetails);
public void fireDeleteEvent(T t,DescriptorEvent descriptorEvent);
} }

View File

@@ -1,174 +1,199 @@
/** /**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others. * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
* *
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.jpa.model; package org.eclipse.hawkbit.repository.jpa.model;
import java.util.List; import java.util.List;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.ConstraintMode; import javax.persistence.ConstraintMode;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.EnumType; import javax.persistence.EnumType;
import javax.persistence.Enumerated; import javax.persistence.Enumerated;
import javax.persistence.FetchType; import javax.persistence.FetchType;
import javax.persistence.ForeignKey; import javax.persistence.ForeignKey;
import javax.persistence.Index; import javax.persistence.Index;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;
import javax.persistence.NamedAttributeNode; import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph; import javax.persistence.NamedEntityGraph;
import javax.persistence.NamedEntityGraphs; import javax.persistence.NamedEntityGraphs;
import javax.persistence.NamedSubgraph; import javax.persistence.NamedSubgraph;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.persistence.Table; import javax.persistence.Table;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.eventbus.event.ActionCreatedEvent;
import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.eventbus.event.ActionPropertyChangeEvent;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.persistence.annotations.CascadeOnDelete; import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.DistributionSet;
/** import org.eclipse.hawkbit.repository.model.Rollout;
* JPA implementation of {@link Action}. import org.eclipse.hawkbit.repository.model.RolloutGroup;
*/ import org.eclipse.hawkbit.repository.model.Target;
@Table(name = "sp_action", indexes = { @Index(name = "sp_idx_action_01", columnList = "tenant,distribution_set"), import org.eclipse.persistence.annotations.CascadeOnDelete;
@Index(name = "sp_idx_action_02", columnList = "tenant,target,active"), import org.eclipse.persistence.descriptors.DescriptorEvent;
@Index(name = "sp_idx_action_prim", columnList = "tenant,id") })
@NamedEntityGraphs({ @NamedEntityGraph(name = "Action.ds", attributeNodes = { @NamedAttributeNode("distributionSet") }), /**
@NamedEntityGraph(name = "Action.all", attributeNodes = { @NamedAttributeNode("distributionSet"), * JPA implementation of {@link Action}.
@NamedAttributeNode(value = "target", subgraph = "target.ds") }, subgraphs = @NamedSubgraph(name = "target.ds", attributeNodes = @NamedAttributeNode("assignedDistributionSet"))) }) */
@Entity @Table(name = "sp_action", indexes = { @Index(name = "sp_idx_action_01", columnList = "tenant,distribution_set"),
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for @Index(name = "sp_idx_action_02", columnList = "tenant,target,active"),
// sub entities @Index(name = "sp_idx_action_prim", columnList = "tenant,id") })
@SuppressWarnings("squid:S2160") @NamedEntityGraphs({ @NamedEntityGraph(name = "Action.ds", attributeNodes = { @NamedAttributeNode("distributionSet") }),
public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Action { @NamedEntityGraph(name = "Action.all", attributeNodes = { @NamedAttributeNode("distributionSet"),
private static final long serialVersionUID = 1L; @NamedAttributeNode(value = "target", subgraph = "target.ds") }, subgraphs = @NamedSubgraph(name = "target.ds", attributeNodes = @NamedAttributeNode("assignedDistributionSet"))) })
@Entity
@ManyToOne(fetch = FetchType.LAZY) // exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
@JoinColumn(name = "distribution_set", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_ds")) // sub entities
private JpaDistributionSet distributionSet; @SuppressWarnings("squid:S2160")
public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Action,EventAwareEntity<JpaAction> {
@ManyToOne(fetch = FetchType.LAZY) private static final long serialVersionUID = 1L;
@JoinColumn(name = "target", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_target"))
private JpaTarget target; @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "distribution_set", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_ds"))
@Column(name = "active") private JpaDistributionSet distributionSet;
private boolean active;
@ManyToOne(fetch = FetchType.LAZY)
@Column(name = "action_type", nullable = false) @JoinColumn(name = "target", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_target"))
@Enumerated(EnumType.STRING) private JpaTarget target;
private ActionType actionType;
@Column(name = "active")
@Column(name = "forced_time") private boolean active;
private long forcedTime;
@Column(name = "action_type", nullable = false)
@Column(name = "status") @Enumerated(EnumType.STRING)
private Status status; private ActionType actionType;
@CascadeOnDelete @Column(name = "forced_time")
@OneToMany(mappedBy = "action", targetEntity = JpaActionStatus.class, fetch = FetchType.LAZY, cascade = { private long forcedTime;
CascadeType.REMOVE })
private List<ActionStatus> actionStatus; @Column(name = "status")
private Status status;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "rolloutgroup", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_rolloutgroup")) @CascadeOnDelete
private JpaRolloutGroup rolloutGroup; @OneToMany(mappedBy = "action", targetEntity = JpaActionStatus.class, fetch = FetchType.LAZY, cascade = {
CascadeType.REMOVE })
@ManyToOne(fetch = FetchType.LAZY) private List<ActionStatus> actionStatus;
@JoinColumn(name = "rollout", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_rollout"))
private JpaRollout rollout; @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "rolloutgroup", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_rolloutgroup"))
@Override private JpaRolloutGroup rolloutGroup;
public DistributionSet getDistributionSet() {
return distributionSet; @ManyToOne(fetch = FetchType.LAZY)
} @JoinColumn(name = "rollout", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_rollout"))
private JpaRollout rollout;
@Override
public void setDistributionSet(final DistributionSet distributionSet) { @Override
this.distributionSet = (JpaDistributionSet) distributionSet; public DistributionSet getDistributionSet() {
} return distributionSet;
}
public void setActive(final boolean active) {
this.active = active; @Override
} public void setDistributionSet(final DistributionSet distributionSet) {
this.distributionSet = (JpaDistributionSet) distributionSet;
@Override }
public Status getStatus() {
return status; public void setActive(final boolean active) {
} this.active = active;
}
@Override
public void setStatus(final Status status) { @Override
this.status = status; public Status getStatus() {
} return status;
}
@Override
public boolean isActive() { @Override
return active; public void setStatus(final Status status) {
} this.status = status;
}
public void setActionType(final ActionType actionType) {
this.actionType = actionType; @Override
} public boolean isActive() {
return active;
@Override }
public ActionType getActionType() {
return actionType; public void setActionType(final ActionType actionType) {
} this.actionType = actionType;
}
@Override
public List<ActionStatus> getActionStatus() { @Override
return actionStatus; public ActionType getActionType() {
} return actionType;
}
@Override
public void setTarget(final Target target) { @Override
this.target = (JpaTarget) target; public List<ActionStatus> getActionStatus() {
} return actionStatus;
}
@Override
public Target getTarget() { @Override
return target; public void setTarget(final Target target) {
} this.target = (JpaTarget) target;
}
@Override
public long getForcedTime() { @Override
return forcedTime; public Target getTarget() {
} return target;
}
public void setForcedTime(final long forcedTime) {
this.forcedTime = forcedTime; @Override
} public long getForcedTime() {
return forcedTime;
@Override }
public RolloutGroup getRolloutGroup() {
return rolloutGroup; public void setForcedTime(final long forcedTime) {
} this.forcedTime = forcedTime;
}
public void setRolloutGroup(final RolloutGroup rolloutGroup) {
this.rolloutGroup = (JpaRolloutGroup) rolloutGroup; @Override
} public RolloutGroup getRolloutGroup() {
return rolloutGroup;
@Override }
public Rollout getRollout() {
return rollout; public void setRolloutGroup(final RolloutGroup rolloutGroup) {
} this.rolloutGroup = (JpaRolloutGroup) rolloutGroup;
}
public void setRollout(final Rollout rollout) {
this.rollout = (JpaRollout) rollout; @Override
} public Rollout getRollout() {
return rollout;
@Override }
public String toString() {
return "Action [distributionSet=" + distributionSet + ", getId()=" + getId() + "]"; public void setRollout(final Rollout rollout) {
} this.rollout = (JpaRollout) rollout;
}
}
@Override
public String toString() {
return "Action [distributionSet=" + distributionSet + ", getId()=" + getId() + "]";
}
@Override
public void fireCreateEvent(final JpaAction jpaAction, final DescriptorEvent descriptorEvent) {
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( () ->EventBusHolder.getInstance().getEventBus().post(new ActionCreatedEvent(jpaAction)));
}
@Override
public void fireUpdateEvent(final JpaAction jpaAction, final DescriptorEvent descriptorEvent) {
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( () ->EventBusHolder.getInstance().getEventBus().
post(new ActionPropertyChangeEvent(jpaAction, EntityPropertyChangeHelper.getChangeSet(Action.class, descriptorEvent))));
}
@Override
public void fireDeleteEvent(final JpaAction jpaAction, final DescriptorEvent descriptorEvent) {
}
}

View File

@@ -1,282 +1,320 @@
/** /**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others. * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
* *
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.jpa.model; package org.eclipse.hawkbit.repository.jpa.model;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Map;
import java.util.Set; import java.util.Optional;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column; import javax.persistence.CascadeType;
import javax.persistence.ConstraintMode; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.ConstraintMode;
import javax.persistence.FetchType; import javax.persistence.Entity;
import javax.persistence.ForeignKey; import javax.persistence.FetchType;
import javax.persistence.Index; import javax.persistence.ForeignKey;
import javax.persistence.JoinColumn; import javax.persistence.Index;
import javax.persistence.JoinTable; import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany; import javax.persistence.JoinTable;
import javax.persistence.ManyToOne; import javax.persistence.ManyToMany;
import javax.persistence.NamedAttributeNode; import javax.persistence.ManyToOne;
import javax.persistence.NamedEntityGraph; import javax.persistence.NamedAttributeNode;
import javax.persistence.OneToMany; import javax.persistence.NamedEntityGraph;
import javax.persistence.Table; import javax.persistence.OneToMany;
import javax.persistence.UniqueConstraint; import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.eclipse.hawkbit.repository.exception.DistributionSetTypeUndefinedException;
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException; import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.eventbus.event.DistributionCreatedEvent;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetUpdateEvent;
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; import org.eclipse.hawkbit.repository.exception.DistributionSetTypeUndefinedException;
import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.TargetInfo; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.persistence.annotations.CascadeOnDelete; import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
/** import org.eclipse.hawkbit.repository.model.DistributionSetType;
* Jpa implementation of {@link DistributionSet}. import org.eclipse.hawkbit.repository.model.SoftwareModule;
* import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
*/ import org.eclipse.hawkbit.repository.model.Target;
@Entity import org.eclipse.hawkbit.repository.model.TargetInfo;
@Table(name = "sp_distribution_set", uniqueConstraints = { import org.eclipse.persistence.annotations.CascadeOnDelete;
@UniqueConstraint(columnNames = { "name", "version", "tenant" }, name = "uk_distrib_set") }, indexes = { import org.eclipse.persistence.descriptors.DescriptorEvent;
@Index(name = "sp_idx_distribution_set_01", columnList = "tenant,deleted,name,complete"),
@Index(name = "sp_idx_distribution_set_02", columnList = "tenant,required_migration_step"), /**
@Index(name = "sp_idx_distribution_set_prim", columnList = "tenant,id") }) * Jpa implementation of {@link DistributionSet}.
@NamedEntityGraph(name = "DistributionSet.detail", attributeNodes = { @NamedAttributeNode("modules"), *
@NamedAttributeNode("tags"), @NamedAttributeNode("type") }) */
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for @Entity
// sub entities @Table(name = "sp_distribution_set", uniqueConstraints = {
@SuppressWarnings("squid:S2160") @UniqueConstraint(columnNames = { "name", "version", "tenant" }, name = "uk_distrib_set") }, indexes = {
public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implements DistributionSet { @Index(name = "sp_idx_distribution_set_01", columnList = "tenant,deleted,name,complete"),
private static final long serialVersionUID = 1L; @Index(name = "sp_idx_distribution_set_02", columnList = "tenant,required_migration_step"),
@Index(name = "sp_idx_distribution_set_prim", columnList = "tenant,id") })
@Column(name = "required_migration_step") @NamedEntityGraph(name = "DistributionSet.detail", attributeNodes = { @NamedAttributeNode("modules"),
private boolean requiredMigrationStep; @NamedAttributeNode("tags"), @NamedAttributeNode("type") })
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
@ManyToMany(targetEntity = JpaSoftwareModule.class, fetch = FetchType.LAZY) // sub entities
@JoinTable(name = "sp_ds_module", joinColumns = { @SuppressWarnings("squid:S2160")
@JoinColumn(name = "ds_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_module_ds")) }, inverseJoinColumns = { public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implements DistributionSet,EventAwareEntity<JpaDistributionSet> {
@JoinColumn(name = "module_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_module_module")) }) private static final long serialVersionUID = 1L;
private final Set<SoftwareModule> modules = new HashSet<>();
private static final String COMPLETE = "complete";
@ManyToMany(targetEntity = JpaDistributionSetTag.class)
@JoinTable(name = "sp_ds_dstag", joinColumns = { @Column(name = "required_migration_step")
@JoinColumn(name = "ds", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_dstag_ds")) }, inverseJoinColumns = { private boolean requiredMigrationStep;
@JoinColumn(name = "TAG", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_dstag_tag")) })
private Set<DistributionSetTag> tags = new HashSet<>(); @ManyToMany(targetEntity = JpaSoftwareModule.class, fetch = FetchType.LAZY)
@JoinTable(name = "sp_ds_module", joinColumns = {
@Column(name = "deleted") @JoinColumn(name = "ds_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_module_ds")) }, inverseJoinColumns = {
private boolean deleted; @JoinColumn(name = "module_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_module_module")) })
private final Set<SoftwareModule> modules = new HashSet<>();
@OneToMany(mappedBy = "assignedDistributionSet", targetEntity = JpaTarget.class, fetch = FetchType.LAZY)
private List<Target> assignedToTargets; @ManyToMany(targetEntity = JpaDistributionSetTag.class)
@JoinTable(name = "sp_ds_dstag", joinColumns = {
@OneToMany(mappedBy = "installedDistributionSet", targetEntity = JpaTargetInfo.class, fetch = FetchType.LAZY) @JoinColumn(name = "ds", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_dstag_ds")) }, inverseJoinColumns = {
private List<TargetInfo> installedAtTargets; @JoinColumn(name = "TAG", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_dstag_tag")) })
private Set<DistributionSetTag> tags = new HashSet<>();
@OneToMany(mappedBy = "distributionSet", targetEntity = JpaAction.class, fetch = FetchType.LAZY)
private List<Action> actions; @Column(name = "deleted")
private boolean deleted;
@CascadeOnDelete
@OneToMany(fetch = FetchType.LAZY, targetEntity = JpaDistributionSetMetadata.class, cascade = { @OneToMany(mappedBy = "assignedDistributionSet", targetEntity = JpaTarget.class, fetch = FetchType.LAZY)
CascadeType.REMOVE }) private List<Target> assignedToTargets;
@JoinColumn(name = "ds_id", insertable = false, updatable = false)
private final List<DistributionSetMetadata> metadata = new ArrayList<>(); @OneToMany(mappedBy = "installedDistributionSet", targetEntity = JpaTargetInfo.class, fetch = FetchType.LAZY)
private List<TargetInfo> installedAtTargets;
@ManyToOne(fetch = FetchType.LAZY, targetEntity = JpaDistributionSetType.class)
@JoinColumn(name = "ds_id", nullable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_dstype_ds")) @OneToMany(mappedBy = "distributionSet", targetEntity = JpaAction.class, fetch = FetchType.LAZY)
private DistributionSetType type; private List<Action> actions;
@Column(name = "complete") @CascadeOnDelete
private boolean complete; @OneToMany(fetch = FetchType.LAZY, targetEntity = JpaDistributionSetMetadata.class, cascade = {
CascadeType.REMOVE })
/** @JoinColumn(name = "ds_id", insertable = false, updatable = false)
* Default constructor. private final List<DistributionSetMetadata> metadata = new ArrayList<>();
*/
public JpaDistributionSet() { @ManyToOne(fetch = FetchType.LAZY, targetEntity = JpaDistributionSetType.class)
super(); @JoinColumn(name = "ds_id", nullable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_dstype_ds"))
} private DistributionSetType type;
/** @Column(name = "complete")
* Parameterized constructor. private boolean complete;
*
* @param name /**
* of the {@link DistributionSet} * Default constructor.
* @param version */
* of the {@link DistributionSet} public JpaDistributionSet() {
* @param description super();
* of the {@link DistributionSet} }
* @param type
* of the {@link DistributionSet} /**
* @param moduleList * Parameterized constructor.
* {@link SoftwareModule}s of the {@link DistributionSet} *
*/ * @param name
public JpaDistributionSet(final String name, final String version, final String description, * of the {@link DistributionSet}
final DistributionSetType type, final Collection<SoftwareModule> moduleList) { * @param version
super(name, version, description); * of the {@link DistributionSet}
* @param description
this.type = type; * of the {@link DistributionSet}
if (moduleList != null) { * @param type
moduleList.forEach(this::addModule); * of the {@link DistributionSet}
} * @param moduleList
if (this.type != null) { * {@link SoftwareModule}s of the {@link DistributionSet}
complete = this.type.checkComplete(this); */
} public JpaDistributionSet(final String name, final String version, final String description,
} final DistributionSetType type, final Collection<SoftwareModule> moduleList) {
super(name, version, description);
@Override
public Set<DistributionSetTag> getTags() { this.type = type;
return tags; if (moduleList != null) {
} moduleList.forEach(this::addModule);
}
@Override if (this.type != null) {
public boolean isDeleted() { complete = this.type.checkComplete(this);
return deleted; }
} }
@Override @Override
public List<DistributionSetMetadata> getMetadata() { public Set<DistributionSetTag> getTags() {
return Collections.unmodifiableList(metadata); return tags;
} }
public List<Action> getActions() { @Override
return actions; public boolean isDeleted() {
} return deleted;
}
@Override
public boolean isRequiredMigrationStep() { @Override
return requiredMigrationStep; public List<DistributionSetMetadata> getMetadata() {
} return Collections.unmodifiableList(metadata);
}
@Override
public DistributionSet setDeleted(final boolean deleted) { public List<Action> getActions() {
this.deleted = deleted; return actions;
return this; }
}
@Override
@Override public boolean isRequiredMigrationStep() {
public DistributionSet setRequiredMigrationStep(final boolean isRequiredMigrationStep) { return requiredMigrationStep;
requiredMigrationStep = isRequiredMigrationStep; }
return this;
} @Override
public DistributionSet setDeleted(final boolean deleted) {
public DistributionSet setTags(final Set<DistributionSetTag> tags) { this.deleted = deleted;
this.tags = tags; return this;
return this; }
}
@Override
@Override public DistributionSet setRequiredMigrationStep(final boolean isRequiredMigrationStep) {
public List<Target> getAssignedTargets() { requiredMigrationStep = isRequiredMigrationStep;
return assignedToTargets; return this;
} }
@Override public DistributionSet setTags(final Set<DistributionSetTag> tags) {
public List<TargetInfo> getInstalledTargets() { this.tags = tags;
return installedAtTargets; return this;
} }
@Override @Override
public String toString() { public List<Target> getAssignedTargets() {
return "DistributionSet [getName()=" + getName() + ", getOptLockRevision()=" + getOptLockRevision() return assignedToTargets;
+ ", getId()=" + getId() + "]"; }
}
@Override
@Override public List<TargetInfo> getInstalledTargets() {
public Set<SoftwareModule> getModules() { return installedAtTargets;
return Collections.unmodifiableSet(modules); }
}
@Override
@Override public String toString() {
public boolean addModule(final SoftwareModule softwareModule) { return "DistributionSet [getName()=" + getName() + ", getOptLockRevision()=" + getOptLockRevision()
+ ", getId()=" + getId() + "]";
// we cannot allow that modules are added without a type defined }
if (type == null) {
throw new DistributionSetTypeUndefinedException(); @Override
} public Set<SoftwareModule> getModules() {
return Collections.unmodifiableSet(modules);
// check if it is allowed to such a module to this DS type }
if (!type.containsModuleType(softwareModule.getType())) {
throw new UnsupportedSoftwareModuleForThisDistributionSetException(); @Override
} public boolean addModule(final SoftwareModule softwareModule) {
final Optional<SoftwareModule> found = modules.stream() // we cannot allow that modules are added without a type defined
.filter(module -> module.getId().equals(softwareModule.getId())).findFirst(); if (type == null) {
throw new DistributionSetTypeUndefinedException();
if (found.isPresent()) { }
return false;
} // check if it is allowed to such a module to this DS type
if (!type.containsModuleType(softwareModule.getType())) {
final long allready = modules.stream() throw new UnsupportedSoftwareModuleForThisDistributionSetException();
.filter(module -> module.getType().getKey().equals(softwareModule.getType().getKey())).count(); }
if (allready >= softwareModule.getType().getMaxAssignments()) { final Optional<SoftwareModule> found = modules.stream()
final Optional<SoftwareModule> sameKey = modules.stream() .filter(module -> module.getId().equals(softwareModule.getId())).findFirst();
.filter(module -> module.getType().getKey().equals(softwareModule.getType().getKey())).findFirst();
modules.remove(sameKey.get()); if (found.isPresent()) {
} return false;
}
if (modules.add(softwareModule)) {
complete = type.checkComplete(this); final long allready = modules.stream()
return true; .filter(module -> module.getType().getKey().equals(softwareModule.getType().getKey())).count();
}
if (allready >= softwareModule.getType().getMaxAssignments()) {
return false; final Optional<SoftwareModule> sameKey = modules.stream()
} .filter(module -> module.getType().getKey().equals(softwareModule.getType().getKey())).findFirst();
modules.remove(sameKey.get());
@Override }
public boolean removeModule(final SoftwareModule softwareModule) {
final Optional<SoftwareModule> found = modules.stream() if (modules.add(softwareModule)) {
.filter(module -> module.getId().equals(softwareModule.getId())).findFirst(); complete = type.checkComplete(this);
return true;
if (found.isPresent()) { }
modules.remove(found.get());
complete = type.checkComplete(this); return false;
return true; }
}
@Override
return false; public boolean removeModule(final SoftwareModule softwareModule) {
final Optional<SoftwareModule> found = modules.stream()
} .filter(module -> module.getId().equals(softwareModule.getId())).findFirst();
@Override if (found.isPresent()) {
public SoftwareModule findFirstModuleByType(final SoftwareModuleType type) { modules.remove(found.get());
final Optional<SoftwareModule> result = modules.stream().filter(module -> module.getType().equals(type)) complete = type.checkComplete(this);
.findFirst(); return true;
}
if (result.isPresent()) {
return result.get(); return false;
}
}
return null;
} @Override
public SoftwareModule findFirstModuleByType(final SoftwareModuleType type) {
@Override final Optional<SoftwareModule> result = modules.stream().filter(module -> module.getType().equals(type))
public DistributionSetType getType() { .findFirst();
return type;
} if (result.isPresent()) {
return result.get();
@Override }
public void setType(final DistributionSetType type) {
this.type = type; return null;
} }
@Override @Override
public boolean isComplete() { public DistributionSetType getType() {
return complete; return type;
} }
} @Override
public void setType(final DistributionSetType type) {
this.type = type;
}
@Override
public boolean isComplete() {
return complete;
}
@Override
public void fireCreateEvent(final JpaDistributionSet jpaDistributionSet, final DescriptorEvent descriptorEvent) {
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( () -> EventBusHolder.getInstance().getEventBus().post(new DistributionCreatedEvent(jpaDistributionSet)));
}
@Override
public void fireUpdateEvent(final JpaDistributionSet jpaDistributionSet, final DescriptorEvent descriptorEvent) {
final Map<String, AbstractPropertyChangeEvent<JpaDistributionSet>.Values> changeSet = EntityPropertyChangeHelper.getChangeSet(
JpaDistributionSet.class, descriptorEvent);
if (changeSet.containsKey(COMPLETE)
&& changeSet.get(COMPLETE).getOldValue().equals(false)
&& changeSet.get(COMPLETE).getNewValue().equals(true)) {
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(
() -> EventBusHolder.getInstance().getEventBus().post(
new DistributionCreatedEvent(jpaDistributionSet)));
}
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(
() -> EventBusHolder.getInstance().getEventBus().post(new DistributionSetUpdateEvent(jpaDistributionSet)));
}
@Override
public void fireDeleteEvent(final JpaDistributionSet jpaDistributionSet, final DescriptorEvent descriptorEvent) {
}
}

View File

@@ -1,200 +1,223 @@
/** /**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others. * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
* *
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.jpa.model; package org.eclipse.hawkbit.repository.jpa.model;
import java.util.List; import java.util.List;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.ConstraintMode; import javax.persistence.ConstraintMode;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.EnumType; import javax.persistence.EnumType;
import javax.persistence.Enumerated; import javax.persistence.Enumerated;
import javax.persistence.FetchType; import javax.persistence.FetchType;
import javax.persistence.ForeignKey; import javax.persistence.ForeignKey;
import javax.persistence.Index; import javax.persistence.Index;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Transient; import javax.persistence.Transient;
import javax.persistence.UniqueConstraint; import javax.persistence.UniqueConstraint;
import org.eclipse.hawkbit.repository.jpa.cache.CacheField; import org.eclipse.hawkbit.repository.eventbus.event.RolloutPropertyChangeEvent;
import org.eclipse.hawkbit.repository.jpa.cache.CacheKeys; import org.eclipse.hawkbit.repository.jpa.cache.CacheField;
import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.jpa.cache.CacheKeys;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.DistributionSet;
/** import org.eclipse.hawkbit.repository.model.Rollout;
* JPA implementation of a {@link Rollout}. import org.eclipse.hawkbit.repository.model.RolloutGroup;
* import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
*/ import org.eclipse.persistence.descriptors.DescriptorEvent;
@Entity
@Table(name = "sp_rollout", indexes = { /**
@Index(name = "sp_idx_rollout_01", columnList = "tenant,name") }, uniqueConstraints = @UniqueConstraint(columnNames = { * JPA implementation of a {@link Rollout}.
"name", "tenant" }, name = "uk_rollout")) *
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for */
// sub entities @Entity
@SuppressWarnings("squid:S2160") @Table(name = "sp_rollout", indexes = {
public class JpaRollout extends AbstractJpaNamedEntity implements Rollout { @Index(name = "sp_idx_rollout_01", columnList = "tenant,name") }, uniqueConstraints = @UniqueConstraint(columnNames = {
"name", "tenant" }, name = "uk_rollout"))
private static final long serialVersionUID = 1L; // exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
// sub entities
@OneToMany(targetEntity = JpaRolloutGroup.class) @SuppressWarnings("squid:S2160")
@JoinColumn(name = "rollout", insertable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_rollout_rolloutgroup")) public class JpaRollout extends AbstractJpaNamedEntity implements Rollout,EventAwareEntity<JpaRollout> {
private List<RolloutGroup> rolloutGroups;
private static final long serialVersionUID = 1L;
@Column(name = "target_filter", length = 1024, nullable = false)
private String targetFilterQuery; @OneToMany(targetEntity = JpaRolloutGroup.class)
@JoinColumn(name = "rollout", insertable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_rollout_rolloutgroup"))
@ManyToOne(fetch = FetchType.LAZY) private List<RolloutGroup> rolloutGroups;
@JoinColumn(name = "distribution_set", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_rolltout_ds"))
private JpaDistributionSet distributionSet; @Column(name = "target_filter", length = 1024, nullable = false)
private String targetFilterQuery;
@Column(name = "status")
private RolloutStatus status = RolloutStatus.CREATING; @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "distribution_set", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_rolltout_ds"))
@Column(name = "last_check") private JpaDistributionSet distributionSet;
private long lastCheck;
@Column(name = "status")
@Column(name = "action_type", nullable = false) private RolloutStatus status = RolloutStatus.CREATING;
@Enumerated(EnumType.STRING)
private ActionType actionType = ActionType.FORCED; @Column(name = "last_check")
private long lastCheck;
@Column(name = "forced_time")
private long forcedTime; @Column(name = "action_type", nullable = false)
@Enumerated(EnumType.STRING)
@Column(name = "total_targets") private ActionType actionType = ActionType.FORCED;
private long totalTargets;
@Column(name = "forced_time")
@Transient private long forcedTime;
@CacheField(key = CacheKeys.ROLLOUT_GROUP_TOTAL)
private int rolloutGroupsTotal; @Column(name = "total_targets")
private long totalTargets;
@Transient
@CacheField(key = CacheKeys.ROLLOUT_GROUP_CREATED) @Transient
private int rolloutGroupsCreated; @CacheField(key = CacheKeys.ROLLOUT_GROUP_TOTAL)
private int rolloutGroupsTotal;
@Transient
private transient TotalTargetCountStatus totalTargetCountStatus; @Transient
@CacheField(key = CacheKeys.ROLLOUT_GROUP_CREATED)
@Override private int rolloutGroupsCreated;
public DistributionSet getDistributionSet() {
return distributionSet; @Transient
} private transient TotalTargetCountStatus totalTargetCountStatus;
@Override @Override
public void setDistributionSet(final DistributionSet distributionSet) { public DistributionSet getDistributionSet() {
this.distributionSet = (JpaDistributionSet) distributionSet; return distributionSet;
} }
@Override @Override
public List<RolloutGroup> getRolloutGroups() { public void setDistributionSet(final DistributionSet distributionSet) {
return rolloutGroups; this.distributionSet = (JpaDistributionSet) distributionSet;
} }
public void setRolloutGroups(final List<RolloutGroup> rolloutGroups) { @Override
this.rolloutGroups = rolloutGroups; public List<RolloutGroup> getRolloutGroups() {
} return rolloutGroups;
}
@Override
public String getTargetFilterQuery() { public void setRolloutGroups(final List<RolloutGroup> rolloutGroups) {
return targetFilterQuery; this.rolloutGroups = rolloutGroups;
} }
@Override @Override
public void setTargetFilterQuery(final String targetFilterQuery) { public String getTargetFilterQuery() {
this.targetFilterQuery = targetFilterQuery; return targetFilterQuery;
} }
@Override @Override
public RolloutStatus getStatus() { public void setTargetFilterQuery(final String targetFilterQuery) {
return status; this.targetFilterQuery = targetFilterQuery;
} }
public void setStatus(final RolloutStatus status) { @Override
this.status = status; public RolloutStatus getStatus() {
} return status;
}
public long getLastCheck() {
return lastCheck; public void setStatus(final RolloutStatus status) {
} this.status = status;
}
public void setLastCheck(final long lastCheck) {
this.lastCheck = lastCheck; public long getLastCheck() {
} return lastCheck;
}
@Override
public ActionType getActionType() { public void setLastCheck(final long lastCheck) {
return actionType; this.lastCheck = lastCheck;
} }
@Override @Override
public void setActionType(final ActionType actionType) { public ActionType getActionType() {
this.actionType = actionType; return actionType;
} }
@Override @Override
public long getForcedTime() { public void setActionType(final ActionType actionType) {
return forcedTime; this.actionType = actionType;
} }
@Override @Override
public void setForcedTime(final long forcedTime) { public long getForcedTime() {
this.forcedTime = forcedTime; return forcedTime;
} }
@Override @Override
public long getTotalTargets() { public void setForcedTime(final long forcedTime) {
return totalTargets; this.forcedTime = forcedTime;
} }
public void setTotalTargets(final long totalTargets) { @Override
this.totalTargets = totalTargets; public long getTotalTargets() {
} return totalTargets;
}
public int getRolloutGroupsTotal() {
return rolloutGroupsTotal; public void setTotalTargets(final long totalTargets) {
} this.totalTargets = totalTargets;
}
public void setRolloutGroupsTotal(final int rolloutGroupsTotal) {
this.rolloutGroupsTotal = rolloutGroupsTotal; public int getRolloutGroupsTotal() {
} return rolloutGroupsTotal;
}
@Override
public int getRolloutGroupsCreated() { public void setRolloutGroupsTotal(final int rolloutGroupsTotal) {
return rolloutGroupsCreated; this.rolloutGroupsTotal = rolloutGroupsTotal;
} }
public void setRolloutGroupsCreated(final int rolloutGroupsCreated) { @Override
this.rolloutGroupsCreated = rolloutGroupsCreated; public int getRolloutGroupsCreated() {
} return rolloutGroupsCreated;
}
@Override
public TotalTargetCountStatus getTotalTargetCountStatus() { public void setRolloutGroupsCreated(final int rolloutGroupsCreated) {
if (totalTargetCountStatus == null) { this.rolloutGroupsCreated = rolloutGroupsCreated;
totalTargetCountStatus = new TotalTargetCountStatus(totalTargets); }
}
return totalTargetCountStatus; @Override
} public TotalTargetCountStatus getTotalTargetCountStatus() {
if (totalTargetCountStatus == null) {
public void setTotalTargetCountStatus(final TotalTargetCountStatus totalTargetCountStatus) { totalTargetCountStatus = new TotalTargetCountStatus(totalTargets);
this.totalTargetCountStatus = totalTargetCountStatus; }
} return totalTargetCountStatus;
}
@Override
public String toString() { public void setTotalTargetCountStatus(final TotalTargetCountStatus totalTargetCountStatus) {
return "Rollout [rolloutGroups=" + rolloutGroups + ", targetFilterQuery=" + targetFilterQuery this.totalTargetCountStatus = totalTargetCountStatus;
+ ", distributionSet=" + distributionSet + ", status=" + status + ", lastCheck=" + lastCheck }
+ ", getName()=" + getName() + ", getId()=" + getId() + "]";
} @Override
public String toString() {
} return "Rollout [rolloutGroups=" + rolloutGroups + ", targetFilterQuery=" + targetFilterQuery
+ ", distributionSet=" + distributionSet + ", status=" + status + ", lastCheck=" + lastCheck
+ ", getName()=" + getName() + ", getId()=" + getId() + "]";
}
@Override
public void fireCreateEvent(final JpaRollout jpaRollout, final DescriptorEvent descriptorEvent) {
}
@Override
public void fireUpdateEvent(final JpaRollout jpaRollout, final DescriptorEvent descriptorEvent) {
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(() -> EventBusHolder.getInstance().getEventBus().
post(new RolloutPropertyChangeEvent(jpaRollout, EntityPropertyChangeHelper.getChangeSet(
Rollout.class, descriptorEvent))));
}
@Override
public void fireDeleteEvent(final JpaRollout jpaRollout, final DescriptorEvent descriptorEvent) {
}
}

View File

@@ -1,239 +1,261 @@
/** /**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others. * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
* *
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.jpa.model; package org.eclipse.hawkbit.repository.jpa.model;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.ConstraintMode; import javax.persistence.ConstraintMode;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.FetchType; import javax.persistence.FetchType;
import javax.persistence.ForeignKey; import javax.persistence.ForeignKey;
import javax.persistence.Index; import javax.persistence.Index;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Transient; import javax.persistence.Transient;
import javax.persistence.UniqueConstraint; import javax.persistence.UniqueConstraint;
import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.eventbus.event.RolloutGroupPropertyChangeEvent;
import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; 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;
* JPA entity definition of persisting a group of an rollout. import org.eclipse.hawkbit.repository.model.RolloutGroup;
* import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
*/ import org.eclipse.persistence.descriptors.DescriptorEvent;
@Entity
@Table(name = "sp_rolloutgroup", indexes = { /**
@Index(name = "sp_idx_rolloutgroup_01", columnList = "tenant,name") }, uniqueConstraints = @UniqueConstraint(columnNames = { * JPA entity definition of persisting a group of an rollout.
"name", "rollout", "tenant" }, name = "uk_rolloutgroup")) *
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for */
// sub entities @Entity
@SuppressWarnings("squid:S2160") @Table(name = "sp_rolloutgroup", indexes = {
public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGroup { @Index(name = "sp_idx_rolloutgroup_01", columnList = "tenant,name") }, uniqueConstraints = @UniqueConstraint(columnNames = {
"name", "rollout", "tenant" }, name = "uk_rolloutgroup"))
private static final long serialVersionUID = 1L; // exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
// sub entities
@ManyToOne(fetch = FetchType.LAZY) @SuppressWarnings("squid:S2160")
@JoinColumn(name = "rollout", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_rolloutgroup_rollout")) public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGroup,EventAwareEntity<JpaRolloutGroup> {
private JpaRollout rollout;
private static final long serialVersionUID = 1L;
@Column(name = "status")
private RolloutGroupStatus status = RolloutGroupStatus.READY; @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "rollout", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_rolloutgroup_rollout"))
@OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST }, targetEntity = RolloutTargetGroup.class) private JpaRollout rollout;
@JoinColumn(name = "rolloutGroup_Id", insertable = false, updatable = false)
private final List<RolloutTargetGroup> rolloutTargetGroup = new ArrayList<>(); @Column(name = "status")
private RolloutGroupStatus status = RolloutGroupStatus.READY;
@ManyToOne(fetch = FetchType.LAZY)
private JpaRolloutGroup parent; @OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST }, targetEntity = RolloutTargetGroup.class)
@JoinColumn(name = "rolloutGroup_Id", insertable = false, updatable = false)
@Column(name = "success_condition", nullable = false) private final List<RolloutTargetGroup> rolloutTargetGroup = new ArrayList<>();
private RolloutGroupSuccessCondition successCondition = RolloutGroupSuccessCondition.THRESHOLD;
@ManyToOne(fetch = FetchType.LAZY)
@Column(name = "success_condition_exp", length = 512, nullable = false) private JpaRolloutGroup parent;
private String successConditionExp;
@Column(name = "success_condition", nullable = false)
@Column(name = "success_action", nullable = false) private RolloutGroupSuccessCondition successCondition = RolloutGroupSuccessCondition.THRESHOLD;
private RolloutGroupSuccessAction successAction = RolloutGroupSuccessAction.NEXTGROUP;
@Column(name = "success_condition_exp", length = 512, nullable = false)
@Column(name = "success_action_exp", length = 512, nullable = false) private String successConditionExp;
private String successActionExp;
@Column(name = "success_action", nullable = false)
@Column(name = "error_condition") private RolloutGroupSuccessAction successAction = RolloutGroupSuccessAction.NEXTGROUP;
private RolloutGroupErrorCondition errorCondition;
@Column(name = "success_action_exp", length = 512, nullable = false)
@Column(name = "error_condition_exp", length = 512) private String successActionExp;
private String errorConditionExp;
@Column(name = "error_condition")
@Column(name = "error_action") private RolloutGroupErrorCondition errorCondition;
private RolloutGroupErrorAction errorAction;
@Column(name = "error_condition_exp", length = 512)
@Column(name = "error_action_exp", length = 512) private String errorConditionExp;
private String errorActionExp;
@Column(name = "error_action")
@Column(name = "total_targets") private RolloutGroupErrorAction errorAction;
private long totalTargets;
@Column(name = "error_action_exp", length = 512)
@Transient private String errorActionExp;
private transient TotalTargetCountStatus totalTargetCountStatus;
@Column(name = "total_targets")
@Override private long totalTargets;
public Rollout getRollout() {
return rollout; @Transient
} private transient TotalTargetCountStatus totalTargetCountStatus;
@Override @Override
public void setRollout(final Rollout rollout) { public Rollout getRollout() {
this.rollout = (JpaRollout) rollout; return rollout;
} }
@Override @Override
public RolloutGroupStatus getStatus() { public void setRollout(final Rollout rollout) {
return status; this.rollout = (JpaRollout) rollout;
} }
@Override @Override
public void setStatus(final RolloutGroupStatus status) { public RolloutGroupStatus getStatus() {
this.status = status; return status;
} }
public List<RolloutTargetGroup> getRolloutTargetGroup() { @Override
return rolloutTargetGroup; public void setStatus(final RolloutGroupStatus status) {
} this.status = status;
}
@Override
public RolloutGroup getParent() { public List<RolloutTargetGroup> getRolloutTargetGroup() {
return parent; return rolloutTargetGroup;
} }
public void setParent(final RolloutGroup parent) { @Override
this.parent = (JpaRolloutGroup) parent; public RolloutGroup getParent() {
} return parent;
}
@Override
public RolloutGroupSuccessCondition getSuccessCondition() { public void setParent(final RolloutGroup parent) {
return successCondition; this.parent = (JpaRolloutGroup) parent;
} }
@Override @Override
public void setSuccessCondition(final RolloutGroupSuccessCondition finishCondition) { public RolloutGroupSuccessCondition getSuccessCondition() {
successCondition = finishCondition; return successCondition;
} }
@Override @Override
public String getSuccessConditionExp() { public void setSuccessCondition(final RolloutGroupSuccessCondition finishCondition) {
return successConditionExp; successCondition = finishCondition;
} }
@Override @Override
public void setSuccessConditionExp(final String finishExp) { public String getSuccessConditionExp() {
successConditionExp = finishExp; return successConditionExp;
} }
@Override @Override
public RolloutGroupErrorCondition getErrorCondition() { public void setSuccessConditionExp(final String finishExp) {
return errorCondition; successConditionExp = finishExp;
} }
@Override @Override
public void setErrorCondition(final RolloutGroupErrorCondition errorCondition) { public RolloutGroupErrorCondition getErrorCondition() {
this.errorCondition = errorCondition; return errorCondition;
} }
@Override @Override
public String getErrorConditionExp() { public void setErrorCondition(final RolloutGroupErrorCondition errorCondition) {
return errorConditionExp; this.errorCondition = errorCondition;
} }
@Override @Override
public void setErrorConditionExp(final String errorExp) { public String getErrorConditionExp() {
errorConditionExp = errorExp; return errorConditionExp;
} }
@Override @Override
public RolloutGroupErrorAction getErrorAction() { public void setErrorConditionExp(final String errorExp) {
return errorAction; errorConditionExp = errorExp;
} }
@Override @Override
public void setErrorAction(final RolloutGroupErrorAction errorAction) { public RolloutGroupErrorAction getErrorAction() {
this.errorAction = errorAction; return errorAction;
} }
@Override @Override
public String getErrorActionExp() { public void setErrorAction(final RolloutGroupErrorAction errorAction) {
return errorActionExp; this.errorAction = errorAction;
} }
@Override @Override
public void setErrorActionExp(final String errorActionExp) { public String getErrorActionExp() {
this.errorActionExp = errorActionExp; return errorActionExp;
} }
@Override @Override
public RolloutGroupSuccessAction getSuccessAction() { public void setErrorActionExp(final String errorActionExp) {
return successAction; this.errorActionExp = errorActionExp;
} }
@Override @Override
public String getSuccessActionExp() { public RolloutGroupSuccessAction getSuccessAction() {
return successActionExp; return successAction;
} }
@Override @Override
public long getTotalTargets() { public String getSuccessActionExp() {
return totalTargets; return successActionExp;
} }
public void setTotalTargets(final long totalTargets) { @Override
this.totalTargets = totalTargets; public long getTotalTargets() {
} return totalTargets;
}
public void setSuccessAction(final RolloutGroupSuccessAction successAction) {
this.successAction = successAction; public void setTotalTargets(final long totalTargets) {
} this.totalTargets = totalTargets;
}
public void setSuccessActionExp(final String successActionExp) {
this.successActionExp = successActionExp; public void setSuccessAction(final RolloutGroupSuccessAction successAction) {
} this.successAction = successAction;
}
/**
* @return the totalTargetCountStatus public void setSuccessActionExp(final String successActionExp) {
*/ this.successActionExp = successActionExp;
@Override }
public TotalTargetCountStatus getTotalTargetCountStatus() {
if (totalTargetCountStatus == null) { /**
totalTargetCountStatus = new TotalTargetCountStatus(totalTargets); * @return the totalTargetCountStatus
} */
return totalTargetCountStatus; @Override
} public TotalTargetCountStatus getTotalTargetCountStatus() {
if (totalTargetCountStatus == null) {
/** totalTargetCountStatus = new TotalTargetCountStatus(totalTargets);
* @param totalTargetCountStatus }
* the totalTargetCountStatus to set return totalTargetCountStatus;
*/ }
@Override
public void setTotalTargetCountStatus(final TotalTargetCountStatus totalTargetCountStatus) { /**
this.totalTargetCountStatus = totalTargetCountStatus; * @param totalTargetCountStatus
} * the totalTargetCountStatus to set
*/
@Override @Override
public String toString() { public void setTotalTargetCountStatus(final TotalTargetCountStatus totalTargetCountStatus) {
return "RolloutGroup [rollout=" + rollout + ", status=" + status + ", rolloutTargetGroup=" + rolloutTargetGroup this.totalTargetCountStatus = totalTargetCountStatus;
+ ", parent=" + parent + ", finishCondition=" + successCondition + ", finishExp=" + successConditionExp }
+ ", errorCondition=" + errorCondition + ", errorExp=" + errorConditionExp + ", getName()=" + getName()
+ ", getId()=" + getId() + "]"; @Override
} public String toString() {
return "RolloutGroup [rollout=" + rollout + ", status=" + status + ", rolloutTargetGroup=" + rolloutTargetGroup
} + ", parent=" + parent + ", finishCondition=" + successCondition + ", finishExp=" + successConditionExp
+ ", errorCondition=" + errorCondition + ", errorExp=" + errorConditionExp + ", getName()=" + getName()
+ ", getId()=" + getId() + "]";
}
@Override
public void fireCreateEvent(final JpaRolloutGroup jpaRolloutGroup, final DescriptorEvent descriptorEvent) {
}
@Override
public void fireUpdateEvent(final JpaRolloutGroup jpaRolloutGroup, final DescriptorEvent descriptorEvent) {
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(() -> EventBusHolder.getInstance().getEventBus().
post(new RolloutGroupPropertyChangeEvent(jpaRolloutGroup,
EntityPropertyChangeHelper.getChangeSet(RolloutGroup.class, descriptorEvent))));
}
@Override
public void fireDeleteEvent(final JpaRolloutGroup jpaRolloutGroup, final DescriptorEvent descriptorEvent) {
}
}

View File

@@ -1,234 +1,257 @@
/** /**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others. * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
* *
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.jpa.model; package org.eclipse.hawkbit.repository.jpa.model;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.ConstraintMode; import javax.persistence.ConstraintMode;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.FetchType; import javax.persistence.FetchType;
import javax.persistence.ForeignKey; import javax.persistence.ForeignKey;
import javax.persistence.Index; import javax.persistence.Index;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.JoinTable; import javax.persistence.JoinTable;
import javax.persistence.ManyToMany; import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;
import javax.persistence.NamedAttributeNode; import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph; import javax.persistence.NamedEntityGraph;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.persistence.OneToOne; import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Transient; import javax.persistence.Transient;
import javax.persistence.UniqueConstraint; import javax.persistence.UniqueConstraint;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityChecker; import org.eclipse.hawkbit.repository.eventbus.event.TargetCreatedEvent;
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHolder; import org.eclipse.hawkbit.repository.eventbus.event.TargetUpdatedEvent;
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityChecker;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHolder;
import org.eclipse.hawkbit.repository.model.TargetInfo; import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.persistence.annotations.CascadeOnDelete; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.springframework.data.domain.Persistable; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetInfo;
/** import org.eclipse.hawkbit.repository.model.TargetTag;
* JPA implementation of {@link Target}. import org.eclipse.persistence.annotations.CascadeOnDelete;
* import org.eclipse.persistence.descriptors.DescriptorEvent;
*/ import org.springframework.data.domain.Persistable;
@Entity
@Table(name = "sp_target", indexes = { /**
@Index(name = "sp_idx_target_01", columnList = "tenant,name,assigned_distribution_set"), * JPA implementation of {@link Target}.
@Index(name = "sp_idx_target_02", columnList = "tenant,name"), *
@Index(name = "sp_idx_target_03", columnList = "tenant,controller_id,assigned_distribution_set"), */
@Index(name = "sp_idx_target_04", columnList = "tenant,created_at"), @Entity
@Index(name = "sp_idx_target_prim", columnList = "tenant,id") }, uniqueConstraints = @UniqueConstraint(columnNames = { @Table(name = "sp_target", indexes = {
"controller_id", "tenant" }, name = "uk_tenant_controller_id")) @Index(name = "sp_idx_target_01", columnList = "tenant,name,assigned_distribution_set"),
@NamedEntityGraph(name = "Target.detail", attributeNodes = { @NamedAttributeNode("tags"), @Index(name = "sp_idx_target_02", columnList = "tenant,name"),
@NamedAttributeNode(value = "assignedDistributionSet"), @NamedAttributeNode(value = "targetInfo") }) @Index(name = "sp_idx_target_03", columnList = "tenant,controller_id,assigned_distribution_set"),
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for @Index(name = "sp_idx_target_04", columnList = "tenant,created_at"),
// sub entities @Index(name = "sp_idx_target_prim", columnList = "tenant,id") }, uniqueConstraints = @UniqueConstraint(columnNames = {
@SuppressWarnings("squid:S2160") "controller_id", "tenant" }, name = "uk_tenant_controller_id"))
public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Long>, Target { @NamedEntityGraph(name = "Target.detail", attributeNodes = { @NamedAttributeNode("tags"),
private static final long serialVersionUID = 1L; @NamedAttributeNode(value = "assignedDistributionSet"), @NamedAttributeNode(value = "targetInfo") })
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
@Column(name = "controller_id", length = 64) // sub entities
@Size(min = 1) @SuppressWarnings("squid:S2160")
@NotNull public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Long>, Target, EventAwareEntity<JpaTarget> {
private String controllerId; private static final long serialVersionUID = 1L;
@Transient @Column(name = "controller_id", length = 64)
private boolean entityNew; @Size(min = 1)
@NotNull
@ManyToMany(targetEntity = JpaTargetTag.class) private String controllerId;
@JoinTable(name = "sp_target_target_tag", joinColumns = {
@JoinColumn(name = "target", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_targtag_target")) }, inverseJoinColumns = { @Transient
@JoinColumn(name = "tag", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_targtag_tag")) }) private boolean entityNew;
private Set<TargetTag> tags = new HashSet<>();
@ManyToMany(targetEntity = JpaTargetTag.class)
@CascadeOnDelete @JoinTable(name = "sp_target_target_tag", joinColumns = {
@OneToMany(fetch = FetchType.LAZY, orphanRemoval = true, cascade = { @JoinColumn(name = "target", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_targtag_target")) }, inverseJoinColumns = {
CascadeType.REMOVE }, targetEntity = JpaAction.class) @JoinColumn(name = "tag", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_targtag_tag")) })
@JoinColumn(name = "target", insertable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_act_hist_targ")) private Set<TargetTag> tags = new HashSet<>();
private final List<Action> actions = new ArrayList<>();
@CascadeOnDelete
@ManyToOne(optional = true, fetch = FetchType.LAZY, targetEntity = JpaDistributionSet.class) @OneToMany(fetch = FetchType.LAZY, orphanRemoval = true, cascade = {
@JoinColumn(name = "assigned_distribution_set", nullable = true, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_assign_ds")) CascadeType.REMOVE }, targetEntity = JpaAction.class)
private JpaDistributionSet assignedDistributionSet; @JoinColumn(name = "target", insertable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_act_hist_targ"))
private final List<Action> actions = new ArrayList<>();
@CascadeOnDelete
@OneToOne(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, targetEntity = JpaTargetInfo.class) @ManyToOne(optional = true, fetch = FetchType.LAZY, targetEntity = JpaDistributionSet.class)
@PrimaryKeyJoinColumn @JoinColumn(name = "assigned_distribution_set", nullable = true, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_assign_ds"))
private JpaTargetInfo targetInfo; private JpaDistributionSet assignedDistributionSet;
/** @CascadeOnDelete
* the security token of the target which allows if enabled to authenticate @OneToOne(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, targetEntity = JpaTargetInfo.class)
* with this security token. @PrimaryKeyJoinColumn
*/ private JpaTargetInfo targetInfo;
@Column(name = "sec_token", insertable = true, updatable = true, nullable = false, length = 128)
private String securityToken; /**
* the security token of the target which allows if enabled to authenticate
@CascadeOnDelete * with this security token.
@OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.REMOVE, CascadeType.PERSIST }) */
@JoinColumn(name = "target_Id", insertable = false, updatable = false) @Column(name = "sec_token", insertable = true, updatable = true, nullable = false, length = 128)
private final List<RolloutTargetGroup> rolloutTargetGroup = new ArrayList<>(); private String securityToken;
/** @CascadeOnDelete
* Constructor. @OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.REMOVE, CascadeType.PERSIST })
* @JoinColumn(name = "target_Id", insertable = false, updatable = false)
* @param controllerId private final List<RolloutTargetGroup> rolloutTargetGroup = new ArrayList<>();
* controller ID of the {@link Target}
*/ /**
public JpaTarget(final String controllerId) { * Constructor.
this(controllerId, SecurityTokenGeneratorHolder.getInstance().generateToken()); *
} * @param controllerId
* controller ID of the {@link Target}
/** */
* Constructor. public JpaTarget(final String controllerId) {
* this(controllerId, SecurityTokenGeneratorHolder.getInstance().generateToken());
* @param controllerId }
* controller ID of the {@link Target}
* @param securityToken /**
* for target authentication if enabled * Constructor.
*/ *
public JpaTarget(final String controllerId, final String securityToken) { * @param controllerId
this.controllerId = controllerId; * controller ID of the {@link Target}
setName(controllerId); * @param securityToken
this.securityToken = securityToken; * for target authentication if enabled
targetInfo = new JpaTargetInfo(this); */
} public JpaTarget(final String controllerId, final String securityToken) {
this.controllerId = controllerId;
/** setName(controllerId);
* empty constructor for JPA. this.securityToken = securityToken;
*/ targetInfo = new JpaTargetInfo(this);
JpaTarget() { }
controllerId = null;
securityToken = null; /**
} * empty constructor for JPA.
*/
@Override JpaTarget() {
public DistributionSet getAssignedDistributionSet() { controllerId = null;
return assignedDistributionSet; securityToken = null;
} }
@Override @Override
public String getControllerId() { public DistributionSet getAssignedDistributionSet() {
return controllerId; return assignedDistributionSet;
} }
@Override @Override
public Set<TargetTag> getTags() { public String getControllerId() {
return tags; return controllerId;
} }
public void setAssignedDistributionSet(final DistributionSet assignedDistributionSet) { @Override
this.assignedDistributionSet = (JpaDistributionSet) assignedDistributionSet; public Set<TargetTag> getTags() {
} return tags;
}
public void setControllerId(final String controllerId) {
this.controllerId = controllerId; public void setAssignedDistributionSet(final DistributionSet assignedDistributionSet) {
} this.assignedDistributionSet = (JpaDistributionSet) assignedDistributionSet;
}
public void setTags(final Set<TargetTag> tags) {
this.tags = tags; public void setControllerId(final String controllerId) {
} this.controllerId = controllerId;
}
@Override
public List<Action> getActions() { public void setTags(final Set<TargetTag> tags) {
return actions; this.tags = tags;
} }
@Override @Override
@Transient public List<Action> getActions() {
public boolean isNew() { return actions;
return entityNew; }
}
@Override
/** @Transient
* @param isNew public boolean isNew() {
* the isNew to set return entityNew;
*/ }
public void setNew(final boolean entityNew) {
this.entityNew = entityNew; /**
} * @param isNew
* the isNew to set
/** */
* @return the targetInfo public void setNew(final boolean entityNew) {
*/ this.entityNew = entityNew;
@Override }
public TargetInfo getTargetInfo() {
return targetInfo; /**
} * @return the targetInfo
*/
/** @Override
* @param targetInfo public TargetInfo getTargetInfo() {
* the targetInfo to set return targetInfo;
*/ }
public void setTargetInfo(final TargetInfo targetInfo) {
this.targetInfo = (JpaTargetInfo) targetInfo; /**
} * @param targetInfo
* the targetInfo to set
/** */
* @return the securityToken if the current security context contains the public void setTargetInfo(final TargetInfo targetInfo) {
* necessary permission {@link SpPermission#READ_TARGET_SEC_TOKEN} this.targetInfo = (JpaTargetInfo) targetInfo;
* or the current context is executed as system code, otherwise }
* {@code null}.
*/ /**
@Override * @return the securityToken if the current security context contains the
public String getSecurityToken() { * necessary permission {@link SpPermission#READ_TARGET_SEC_TOKEN}
if (SystemSecurityContextHolder.getInstance().getSystemSecurityContext().isCurrentThreadSystemCode() * or the current context is executed as system code, otherwise
|| SecurityChecker.hasPermission(SpPermission.READ_TARGET_SEC_TOKEN)) { * {@code null}.
return securityToken; */
} @Override
return null; public String getSecurityToken() {
} if (SystemSecurityContextHolder.getInstance().getSystemSecurityContext().isCurrentThreadSystemCode()
|| SecurityChecker.hasPermission(SpPermission.READ_TARGET_SEC_TOKEN)) {
/** return securityToken;
* @param securityToken }
* the securityToken to set return null;
*/ }
public void setSecurityToken(final String securityToken) {
this.securityToken = securityToken; /**
} * @param securityToken
* the securityToken to set
@Override */
public String toString() { @Override
return "Target [controllerId=" + controllerId + ", getId()=" + getId() + "]"; public void setSecurityToken(final String securityToken) {
} this.securityToken = securityToken;
}
}
@Override
public String toString() {
return "Target [controllerId=" + controllerId + ", getId()=" + getId() + "]";
}
@Override
public void fireCreateEvent(final JpaTarget jpaTarget, final DescriptorEvent descriptorEvent) {
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( () ->EventBusHolder.getInstance().getEventBus().post(new TargetCreatedEvent(jpaTarget)));
}
@Override
public void fireUpdateEvent(final JpaTarget jpaTarget,final DescriptorEvent descriptorEvent) {
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( () -> EventBusHolder.getInstance().getEventBus().post(new TargetUpdatedEvent(jpaTarget)));
}
@Override
public void fireDeleteEvent(final JpaTarget jpaTarget, final DescriptorEvent descriptorEvent) {
}
}

View File

@@ -1,324 +1,344 @@
/** /**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others. * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
* *
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.jpa.model; package org.eclipse.hawkbit.repository.jpa.model;
import java.net.URI; import java.net.URI;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
import javax.persistence.CollectionTable; import javax.persistence.CollectionTable;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.ConstraintMode; import javax.persistence.ConstraintMode;
import javax.persistence.ElementCollection; import javax.persistence.ElementCollection;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.EnumType; import javax.persistence.EntityListeners;
import javax.persistence.Enumerated; import javax.persistence.EnumType;
import javax.persistence.FetchType; import javax.persistence.Enumerated;
import javax.persistence.ForeignKey; import javax.persistence.FetchType;
import javax.persistence.Id; import javax.persistence.ForeignKey;
import javax.persistence.Index; import javax.persistence.Id;
import javax.persistence.JoinColumn; import javax.persistence.Index;
import javax.persistence.ManyToOne; import javax.persistence.JoinColumn;
import javax.persistence.MapKeyColumn; import javax.persistence.ManyToOne;
import javax.persistence.MapsId; import javax.persistence.MapKeyColumn;
import javax.persistence.OneToOne; import javax.persistence.MapsId;
import javax.persistence.Table; import javax.persistence.OneToOne;
import javax.persistence.Transient; import javax.persistence.Table;
import javax.persistence.Transient;
import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException;
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder; import org.eclipse.hawkbit.repository.eventbus.event.TargetInfoUpdateEvent;
import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder; import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
import org.eclipse.hawkbit.repository.model.PollStatus; import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
import org.eclipse.hawkbit.repository.model.TargetInfo; import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper; import org.eclipse.hawkbit.repository.model.PollStatus;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.persistence.annotations.CascadeOnDelete; import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.slf4j.Logger; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.slf4j.LoggerFactory; import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
import org.springframework.data.domain.Persistable; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.eclipse.persistence.annotations.CascadeOnDelete;
/** import org.eclipse.persistence.descriptors.DescriptorEvent;
* A table which contains all the information inserted, updated by the import org.slf4j.Logger;
* controller itself. So this entity does not provide audit information because import org.slf4j.LoggerFactory;
* changes on this entity are mostly only done by controller requests. That's import org.springframework.data.domain.Persistable;
* the reason that we store these information in a separated table so we don't
* modifying the {@link Target} itself when a controller reports it's /**
* {@link #lastTargetQuery} for example. * A table which contains all the information inserted, updated by the
* * controller itself. So this entity does not provide audit information because
*/ * changes on this entity are mostly only done by controller requests. That's
@Table(name = "sp_target_info", indexes = { * the reason that we store these information in a separated table so we don't
@Index(name = "sp_idx_target_info_02", columnList = "target_id,update_status") }) * modifying the {@link Target} itself when a controller reports it's
@Entity * {@link #lastTargetQuery} for example.
public class JpaTargetInfo implements Persistable<Long>, TargetInfo { *
private static final long serialVersionUID = 1L; */
@Table(name = "sp_target_info", indexes = {
private static final Logger LOG = LoggerFactory.getLogger(TargetInfo.class); @Index(name = "sp_idx_target_info_02", columnList = "target_id,update_status") })
@Entity
@Id @EntityListeners(EntityPropertyChangeListener.class)
private Long targetId; public class JpaTargetInfo implements Persistable<Long>, TargetInfo, EventAwareEntity<JpaTargetInfo> {
private static final long serialVersionUID = 1L;
@Transient
private boolean entityNew; private static final Logger LOG = LoggerFactory.getLogger(TargetInfo.class);
@CascadeOnDelete @Id
@OneToOne(cascade = { CascadeType.MERGE, private Long targetId;
CascadeType.REMOVE }, fetch = FetchType.LAZY, targetEntity = JpaTarget.class)
@JoinColumn(name = "target_id", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_stat_targ")) @Transient
@MapsId private boolean entityNew;
private JpaTarget target;
@CascadeOnDelete
@Column(name = "address", length = 512) @OneToOne(cascade = { CascadeType.MERGE,
private String address; CascadeType.REMOVE }, fetch = FetchType.LAZY, targetEntity = JpaTarget.class)
@JoinColumn(name = "target_id", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_stat_targ"))
@Column(name = "last_target_query") @MapsId
private Long lastTargetQuery; private JpaTarget target;
@Column(name = "install_date") @Column(name = "address", length = 512)
private Long installationDate; private String address;
@Column(name = "update_status", nullable = false, length = 255) @Column(name = "last_target_query")
@Enumerated(EnumType.STRING) private Long lastTargetQuery;
private TargetUpdateStatus updateStatus = TargetUpdateStatus.UNKNOWN;
@Column(name = "install_date")
@ManyToOne(optional = true, fetch = FetchType.LAZY) private Long installationDate;
@JoinColumn(name = "installed_distribution_set", nullable = true, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_inst_ds"))
private JpaDistributionSet installedDistributionSet; @Column(name = "update_status", nullable = false, length = 255)
@Enumerated(EnumType.STRING)
/** private TargetUpdateStatus updateStatus = TargetUpdateStatus.UNKNOWN;
* Read only on management API. Are commited by controller.
*/ @ManyToOne(optional = true, fetch = FetchType.LAZY)
@ElementCollection @JoinColumn(name = "installed_distribution_set", nullable = true, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_inst_ds"))
@Column(name = "attribute_value", length = 128) private JpaDistributionSet installedDistributionSet;
@MapKeyColumn(name = "attribute_key", nullable = false, length = 32)
@CollectionTable(name = "sp_target_attributes", joinColumns = { /**
@JoinColumn(name = "target_id") }, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_attrib_target")) * Read only on management API. Are commited by controller.
*/
private final Map<String, String> controllerAttributes = Collections.synchronizedMap(new HashMap<String, String>()); @ElementCollection
@Column(name = "attribute_value", length = 128)
// set default request controller attributes to true, because we want to @MapKeyColumn(name = "attribute_key", nullable = false, length = 32)
// request them the first @CollectionTable(name = "sp_target_attributes", joinColumns = {
// time @JoinColumn(name = "target_id") }, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_attrib_target"))
@Column(name = "request_controller_attributes", nullable = false)
private boolean requestControllerAttributes = true; private final Map<String, String> controllerAttributes = Collections.synchronizedMap(new HashMap<String, String>());
/** // set default request controller attributes to true, because we want to
* Constructor for {@link TargetStatus}. // request them the first
* // time
* @param target @Column(name = "request_controller_attributes", nullable = false)
* related to this status. private boolean requestControllerAttributes = true;
*/
public JpaTargetInfo(final JpaTarget target) { /**
this.target = target; * Constructor for {@link TargetStatus}.
targetId = target.getId(); *
} * @param target
* related to this status.
JpaTargetInfo() { */
target = null; public JpaTargetInfo(final JpaTarget target) {
targetId = null; this.target = target;
} targetId = target.getId();
}
@Override
public Long getId() { JpaTargetInfo() {
return targetId; target = null;
} targetId = null;
}
@Override
@Transient @Override
public boolean isNew() { public Long getId() {
return entityNew; return targetId;
} }
/** @Override
* @param isNew @Transient
* the isNew to set public boolean isNew() {
*/ return entityNew;
public void setNew(final boolean entityNew) { }
this.entityNew = entityNew;
} /**
* @param isNew
/** * the isNew to set
* @return the ipAddress */
*/ public void setNew(final boolean entityNew) {
@Override this.entityNew = entityNew;
public URI getAddress() { }
if (address == null) {
return null; /**
} * @return the ipAddress
try { */
return URI.create(address); @Override
} catch (final IllegalArgumentException e) { public URI getAddress() {
LOG.warn("Invalid address provided. Cloud not be configured to URI", e); if (address == null) {
return null; return null;
} }
} try {
return URI.create(address);
/** } catch (final IllegalArgumentException e) {
* @param address LOG.warn("Invalid address provided. Cloud not be configured to URI", e);
* the target address to set return null;
* }
* @throws IllegalArgumentException }
* If the given string violates RFC&nbsp;2396
*/ /**
@Override * @param address
public void setAddress(final String address) { * the target address to set
// check if this is a real URI *
if (address != null) { * @throws IllegalArgumentException
try { * If the given string violates RFC&nbsp;2396
URI.create(address); */
} catch (final IllegalArgumentException e) { @Override
throw new InvalidTargetAddressException( public void setAddress(final String address) {
"The given address " + address + " violates the RFC-2396 specification", e); // check if this is a real URI
} if (address != null) {
} try {
URI.create(address);
this.address = address; } catch (final IllegalArgumentException e) {
} throw new InvalidTargetAddressException(
"The given address " + address + " violates the RFC-2396 specification", e);
public Long getTargetId() { }
return targetId; }
}
this.address = address;
public void setTargetId(final Long targetId) { }
this.targetId = targetId;
} public Long getTargetId() {
return targetId;
@Override }
public Target getTarget() {
return target; public void setTargetId(final Long targetId) {
} this.targetId = targetId;
}
public void setTarget(final JpaTarget target) {
this.target = target; @Override
} public Target getTarget() {
return target;
@Override }
public Long getLastTargetQuery() {
return lastTargetQuery; public void setTarget(final JpaTarget target) {
} this.target = target;
}
public void setLastTargetQuery(final Long lastTargetQuery) {
this.lastTargetQuery = lastTargetQuery; @Override
} public Long getLastTargetQuery() {
return lastTargetQuery;
public void setRequestControllerAttributes(final boolean requestControllerAttributes) { }
this.requestControllerAttributes = requestControllerAttributes;
} public void setLastTargetQuery(final Long lastTargetQuery) {
this.lastTargetQuery = lastTargetQuery;
@Override }
public Map<String, String> getControllerAttributes() {
return controllerAttributes; public void setRequestControllerAttributes(final boolean requestControllerAttributes) {
} this.requestControllerAttributes = requestControllerAttributes;
}
@Override
public boolean isRequestControllerAttributes() { @Override
return requestControllerAttributes; public Map<String, String> getControllerAttributes() {
} return controllerAttributes;
}
@Override
public Long getInstallationDate() { @Override
return installationDate; public boolean isRequestControllerAttributes() {
} return requestControllerAttributes;
}
public void setInstallationDate(final Long installationDate) {
this.installationDate = installationDate; @Override
} public Long getInstallationDate() {
return installationDate;
@Override }
public TargetUpdateStatus getUpdateStatus() {
return updateStatus; public void setInstallationDate(final Long installationDate) {
} this.installationDate = installationDate;
}
public void setUpdateStatus(final TargetUpdateStatus updateStatus) {
this.updateStatus = updateStatus; @Override
} public TargetUpdateStatus getUpdateStatus() {
return updateStatus;
@Override }
public DistributionSet getInstalledDistributionSet() {
return installedDistributionSet; public void setUpdateStatus(final TargetUpdateStatus updateStatus) {
} this.updateStatus = updateStatus;
}
public void setInstalledDistributionSet(final JpaDistributionSet installedDistributionSet) {
this.installedDistributionSet = installedDistributionSet; @Override
} public DistributionSet getInstalledDistributionSet() {
return installedDistributionSet;
/** }
* @return the poll time which holds the last poll time of the target, the
* next poll time and the overdue time. In case the public void setInstalledDistributionSet(final JpaDistributionSet installedDistributionSet) {
* {@link #lastTargetQuery} is not set e.g. the target never polled this.installedDistributionSet = installedDistributionSet;
* before this method returns {@code null} }
*/
@Override /**
public PollStatus getPollStatus() { * @return the poll time which holds the last poll time of the target, the
if (lastTargetQuery == null) { * next poll time and the overdue time. In case the
return null; * {@link #lastTargetQuery} is not set e.g. the target never polled
} * before this method returns {@code null}
return SystemSecurityContextHolder.getInstance().getSystemSecurityContext().runAsSystem(() -> { */
final Duration pollTime = DurationHelper.formattedStringToDuration(TenantConfigurationManagementHolder @Override
.getInstance().getTenantConfigurationManagement() public PollStatus getPollStatus() {
.getConfigurationValue(TenantConfigurationKey.POLLING_TIME_INTERVAL, String.class).getValue()); if (lastTargetQuery == null) {
final Duration overdueTime = DurationHelper.formattedStringToDuration( return null;
TenantConfigurationManagementHolder.getInstance().getTenantConfigurationManagement() }
.getConfigurationValue(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL, String.class) return SystemSecurityContextHolder.getInstance().getSystemSecurityContext().runAsSystem(() -> {
.getValue()); final Duration pollTime = DurationHelper.formattedStringToDuration(TenantConfigurationManagementHolder
final LocalDateTime currentDate = LocalDateTime.now(); .getInstance().getTenantConfigurationManagement()
final LocalDateTime lastPollDate = LocalDateTime.ofInstant(Instant.ofEpochMilli(lastTargetQuery), .getConfigurationValue(TenantConfigurationKey.POLLING_TIME_INTERVAL, String.class).getValue());
ZoneId.systemDefault()); final Duration overdueTime = DurationHelper.formattedStringToDuration(
final LocalDateTime nextPollDate = lastPollDate.plus(pollTime); TenantConfigurationManagementHolder.getInstance().getTenantConfigurationManagement()
final LocalDateTime overdueDate = nextPollDate.plus(overdueTime); .getConfigurationValue(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL, String.class)
return new PollStatus(lastPollDate, nextPollDate, overdueDate, currentDate); .getValue());
}); final LocalDateTime currentDate = LocalDateTime.now();
} final LocalDateTime lastPollDate = LocalDateTime.ofInstant(Instant.ofEpochMilli(lastTargetQuery),
ZoneId.systemDefault());
@Override final LocalDateTime nextPollDate = lastPollDate.plus(pollTime);
public int hashCode() { final LocalDateTime overdueDate = nextPollDate.plus(overdueTime);
final int prime = 31; return new PollStatus(lastPollDate, nextPollDate, overdueDate, currentDate);
int result = 1; });
result = prime * result + ((target == null) ? 0 : target.hashCode()); }
result = prime * result + ((targetId == null) ? 0 : targetId.hashCode());
return result; @Override
} public int hashCode() {
final int prime = 31;
@Override int result = 1;
public boolean equals(final Object obj) { result = prime * result + ((target == null) ? 0 : target.hashCode());
if (this == obj) { result = prime * result + ((targetId == null) ? 0 : targetId.hashCode());
return true; return result;
} }
if (obj == null) {
return false; @Override
} public boolean equals(final Object obj) {
if (!(obj instanceof TargetInfo)) { if (this == obj) {
return false; return true;
} }
final JpaTargetInfo other = (JpaTargetInfo) obj; if (obj == null) {
if (target == null) { return false;
if (other.target != null) { }
return false; if (!(obj instanceof TargetInfo)) {
} return false;
} else if (!target.equals(other.target)) { }
return false; final JpaTargetInfo other = (JpaTargetInfo) obj;
} if (target == null) {
if (targetId == null) { if (other.target != null) {
if (other.targetId != null) { return false;
return false; }
} } else if (!target.equals(other.target)) {
} else if (!targetId.equals(other.targetId)) { return false;
return false; }
} if (targetId == null) {
return true; if (other.targetId != null) {
} return false;
} }
} else if (!targetId.equals(other.targetId)) {
return false;
}
return true;
}
@Override
public void fireCreateEvent(final JpaTargetInfo jpaTargetInfo,final DescriptorEvent descriptorEvent) {
// there is no target info created event
}
@Override
public void fireUpdateEvent(final JpaTargetInfo jpaTargetInfo, final DescriptorEvent descriptorEvent) {
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( () -> EventBusHolder.getInstance().getEventBus().post(new TargetInfoUpdateEvent(jpaTargetInfo)));
}
@Override
public void fireDeleteEvent(final JpaTargetInfo jpaTargetInfo, final DescriptorEvent descriptorEvent) {
}
}

View File

@@ -0,0 +1,42 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.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;
public class EntityPropertyChangeHelper<T extends TenantAwareBaseEntity> {
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())));
}
}