diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulatorUpdater.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulatorUpdater.java index 9c4c43ad2..01a9231e3 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulatorUpdater.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulatorUpdater.java @@ -8,9 +8,12 @@ */ package org.eclipse.hawkbit.simulator; +import static java.util.concurrent.Executors.newScheduledThreadPool; + import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.security.DigestOutputStream; import java.security.KeyManagementException; import java.security.KeyStoreException; @@ -20,7 +23,6 @@ import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; import java.util.Random; -import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -56,9 +58,10 @@ import com.google.common.io.ByteStreams; */ @Service public class DeviceSimulatorUpdater { + private static final Logger LOGGER = LoggerFactory.getLogger(DeviceSimulatorUpdater.class); - private static final ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(8); + private static final ScheduledExecutorService threadPool = newScheduledThreadPool(8); @Autowired private SpSenderService spSenderService; @@ -118,14 +121,9 @@ public class DeviceSimulatorUpdater { } private static final class DeviceSimulatorUpdateThread implements Runnable { - /** - * - */ + private static final String BUT_GOT_LOG_MESSAGE = " but got: "; - /** - * - */ private static final String DOWNLOAD_LOG_MESSAGE = "Download "; private static final int MINIMUM_TOKENLENGTH_FOR_HINT = 6; @@ -279,13 +277,17 @@ public class DeviceSimulatorUpdater { private static long getOverallRead(final CloseableHttpResponse response, final MessageDigest md) throws IOException { + long overallread; - try (final BufferedOutputStream bdos = new BufferedOutputStream( - new DigestOutputStream(ByteStreams.nullOutputStream(), md))) { + + try (final OutputStream os = ByteStreams.nullOutputStream(); + final BufferedOutputStream bos = new BufferedOutputStream(new DigestOutputStream(os, md))) { + try (BufferedInputStream bis = new BufferedInputStream(response.getEntity().getContent())) { - overallread = ByteStreams.copy(bis, bdos); + overallread = ByteStreams.copy(bis, bos); } } + return overallread; } diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/FieldNameProvider.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/FieldNameProvider.java index 574ce61e2..d8fd4281c 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/FieldNameProvider.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/FieldNameProvider.java @@ -16,9 +16,10 @@ import java.util.Map; * An interface for declaring the name of the field described in the database * which is used as string representation of the field, e.g. for sorting the * fields over REST. - * */ +@FunctionalInterface public interface FieldNameProvider { + /** * Separator for the sub attributes */ @@ -32,64 +33,18 @@ public interface FieldNameProvider { /** * Contains the sub entity the given field. - * + * * @param propertyField * the given field * @return contains contains not */ default boolean containsSubEntityAttribute(final String propertyField) { - return FieldNameProvider.containsSubEntityAttribute(propertyField, getSubEntityAttributes()); - } - /** - * - * @return all sub entities attributes. - */ - default List getSubEntityAttributes() { - return Collections.emptyList(); - } - - /** - * the database column for the key - * - * @return key fieldname - */ - default String getKeyFieldName() { - return null; - } - - /** - * the database column for the value - * - * @return key fieldname - */ - default String getValueFieldName() { - return null; - } - - /** - * Is the entity field a {@link Map}. - * - * @return is a map is not a map - */ - default boolean isMap() { - return getKeyFieldName() != null; - } - - /** - * Check if a sub attribute exists. - * - * @param propertyField - * the sub property field. - * @param subEntityAttribues - * the list of available properties - * @return property exists not exists - */ - static boolean containsSubEntityAttribute(final String propertyField, final List subEntityAttribues) { - if (subEntityAttribues.contains(propertyField)) { + final List subEntityAttributes = getSubEntityAttributes(); + if (subEntityAttributes.contains(propertyField)) { return true; } - for (final String attribute : subEntityAttribues) { + for (final String attribute : subEntityAttributes) { final String[] graph = attribute.split("\\" + SUB_ATTRIBUTE_SEPERATOR); for (final String subAttribute : graph) { @@ -102,4 +57,37 @@ public interface FieldNameProvider { return false; } + /** + * @return all sub entities attributes. + */ + default List getSubEntityAttributes() { + return Collections.emptyList(); + } + + /** + * The database column for the key + * + * @return key fieldname + */ + default String getKeyFieldName() { + return null; + } + + /** + * The database column for the value + * + * @return key fieldname + */ + default String getValueFieldName() { + return null; + } + + /** + * Is the entity field a {@link Map}. + * + * @return is a map is not a map + */ + default boolean isMap() { + return getKeyFieldName() != null; + } } diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTargetAttributes.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTargetAttributes.java index dad8e868f..ea01b87ca 100644 --- a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTargetAttributes.java +++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTargetAttributes.java @@ -8,8 +8,9 @@ import java.util.Map; /** * {@link Map} with attributes of SP Target. - * */ public class MgmtTargetAttributes extends HashMap { + private static final long serialVersionUID = 1L; + } diff --git a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java b/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java index f647106af..57e2c096d 100644 --- a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java +++ b/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java @@ -52,9 +52,7 @@ import org.eclipse.hawkbit.rest.json.model.ExceptionInfo; import org.eclipse.hawkbit.rest.util.JsonBuilder; import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; import org.eclipse.hawkbit.util.IpUtil; -import org.json.JSONException; import org.json.JSONObject; -import org.junit.Ignore; import org.junit.Test; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Slice; @@ -80,7 +78,6 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest { private static final String TARGET_DESCRIPTION_TEST = "created in test"; - // json paths private static final String JSON_PATH_ROOT = "$"; // fields, attributes @@ -633,69 +630,8 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest { final String knownName = "someName"; createSingleTarget(knownControllerId, knownName); - // test - mvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId + "/installedDS")) .andExpect(status().isNoContent()).andExpect(content().string("")); - - } - - @Test - @Ignore - public void getInstalledDistributionSetOfTarget() throws JSONException, Exception { - // create first a target which can be retrieved by rest interface - final String knownControllerId = "1"; - final String knownName = "someName"; - createSingleTarget(knownControllerId, knownName); - final DistributionSet ds = testdataFactory.createDistributionSet(""); - // assign ds to target - final Long actionId = deploymentManagement.assignDistributionSet(ds.getId(), knownControllerId).getActions() - .get(0); - // give feedback, so installedDS is in SNYC - feedbackToByInSync(actionId); - // test - - final SoftwareModule os = ds.findFirstModuleByType(osType); - final SoftwareModule jvm = ds.findFirstModuleByType(runtimeType); - final SoftwareModule bApp = ds.findFirstModuleByType(appType); - mvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId + "/installedDS")) - .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) - .andExpect(jsonPath(JSON_PATH_ID, equalTo(ds.getId().intValue()))) - .andExpect(jsonPath(JSON_PATH_NAME, equalTo(ds.getName()))) - .andExpect(jsonPath(JSON_PATH_DESCRIPTION, equalTo(ds.getDescription()))) - // os - .andExpect( - jsonPath("$modules.[?(@.type==" + osType.getKey() + ")][0].id", equalTo(os.getId().intValue()))) - .andExpect(jsonPath("$modules.[?(@.type==" + osType.getKey() + ")][0].name", equalTo(os.getName()))) - .andExpect(jsonPath("$modules.[?(@.type==" + osType.getKey() + ")][0].description", - equalTo(os.getDescription()))) - .andExpect( - jsonPath("$modules.[?(@.type==" + osType.getKey() + ")][0].version", equalTo(os.getVersion()))) - .andExpect(jsonPath("$modules.[?(@.type==" + osType.getKey() + ")][0].vendor", equalTo(os.getVendor()))) - .andExpect(jsonPath("$modules.[?(@.type==" + osType.getKey() + ")][0].type", equalTo("os"))) - // jvm - .andExpect(jsonPath("$modules.[?(@.type==" + runtimeType.getKey() + ")][0].id", - equalTo(jvm.getId().intValue()))) - .andExpect( - jsonPath("$modules.[?(@.type==" + runtimeType.getKey() + ")][0].name", equalTo(jvm.getName()))) - .andExpect(jsonPath("$modules.[?(@.type==" + runtimeType.getKey() + ")][0].description", - equalTo(jvm.getDescription()))) - .andExpect(jsonPath("$modules.[?(@.type==" + runtimeType.getKey() + ")][0].version", - equalTo(jvm.getVersion()))) - .andExpect(jsonPath("$modules.[?(@.type==" + runtimeType.getKey() + ")][0].vendor", - equalTo(jvm.getVendor()))) - .andExpect(jsonPath("$modules.[?(@.type==" + runtimeType.getKey() + ")][0].type", equalTo("runtime"))) - // baseApp - .andExpect(jsonPath("$modules.[?(@.type==" + appType.getKey() + ")][0].id", - equalTo(bApp.getId().intValue()))) - .andExpect(jsonPath("$modules.[?(@.type==" + appType.getKey() + ")][0].name", equalTo(bApp.getName()))) - .andExpect(jsonPath("$modules.[?(@.type==" + appType.getKey() + ")][0].description", - equalTo(bApp.getDescription()))) - .andExpect(jsonPath("$modules.[?(@.type==" + appType.getKey() + ")][0].version", - equalTo(bApp.getVersion()))) - .andExpect( - jsonPath("$modules.[?(@.type==" + appType.getKey() + ")][0].vendor", equalTo(bApp.getVendor()))) - .andExpect(jsonPath("$modules.[?(@.type==" + appType.getKey() + ")][0].type", equalTo("application"))); } @Test diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/AbstractPropertyChangeEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/AbstractPropertyChangeEvent.java index 97cf13b66..2520ebc9c 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/AbstractPropertyChangeEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/AbstractPropertyChangeEvent.java @@ -20,18 +20,18 @@ import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; public class AbstractPropertyChangeEvent extends AbstractBaseEntityEvent { private static final long serialVersionUID = -3671601415138242311L; - private final transient Map changeSet; + private final transient Map changeSet; /** * Initialize base entity and property changed with old and new value. - * + * * @param baseEntity * entity changed * @param changeSetValues * details of properties changed and old value and new value of * the changed properties */ - public AbstractPropertyChangeEvent(final E baseEntity, final Map changeSetValues) { + public AbstractPropertyChangeEvent(final E baseEntity, final Map changeSetValues) { super(baseEntity); this.changeSet = changeSetValues; } @@ -39,27 +39,27 @@ public class AbstractPropertyChangeEvent extend /** * @return the changeSet */ - public Map getChangeSet() { + public Map getChangeSet() { return changeSet; } /** * Carries old value and new value of a property . - * */ - public class Values { + public static class PropertyChange { + private final Object oldValue; private final Object newValue; /** * Initialize old value and new changes value of property. - * + * * @param oldValue * old value before change * @param newValue * new value after change */ - public Values(final Object oldValue, final Object newValue) { + public PropertyChange(final Object oldValue, final Object newValue) { super(); this.oldValue = oldValue; this.newValue = newValue; @@ -78,6 +78,5 @@ public class AbstractPropertyChangeEvent extend public Object getNewValue() { return newValue; } - } } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/ActionPropertyChangeEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/ActionPropertyChangeEvent.java index 84487547e..5197bd9a0 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/ActionPropertyChangeEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/ActionPropertyChangeEvent.java @@ -22,8 +22,7 @@ public class ActionPropertyChangeEvent extends AbstractPropertyChangeEvent.Values> changeSetValues) { + public ActionPropertyChangeEvent(final Action action, final Map changeSetValues) { super(action, changeSetValues); } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/RolloutGroupPropertyChangeEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/RolloutGroupPropertyChangeEvent.java index 887a1c2ff..b0b31b79a 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/RolloutGroupPropertyChangeEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/RolloutGroupPropertyChangeEvent.java @@ -20,12 +20,12 @@ public class RolloutGroupPropertyChangeEvent extends AbstractPropertyChangeEvent private static final long serialVersionUID = 4026477044419472686L; /** - * + * * @param rolloutGroup * @param changeSetValues */ public RolloutGroupPropertyChangeEvent(final RolloutGroup rolloutGroup, - final Map.Values> changeSetValues) { + final Map changeSetValues) { super(rolloutGroup, changeSetValues); } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/RolloutPropertyChangeEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/RolloutPropertyChangeEvent.java index 9287a0fb3..9bb975c3a 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/RolloutPropertyChangeEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/RolloutPropertyChangeEvent.java @@ -19,12 +19,11 @@ public class RolloutPropertyChangeEvent extends AbstractPropertyChangeEvent.Values> changeSetValues) { + public RolloutPropertyChangeEvent(final Rollout rollout, final Map changeSetValues) { super(rollout, changeSetValues); } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/report/model/AbstractReportSeries.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/report/model/AbstractReportSeries.java index 747cd8279..9ba5ba2da 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/report/model/AbstractReportSeries.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/report/model/AbstractReportSeries.java @@ -12,16 +12,9 @@ import java.io.Serializable; /** * An abstract report series. - * - * - * - * */ public class AbstractReportSeries implements Serializable { - /** - * - */ private static final long serialVersionUID = 1L; private final String name; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/report/model/ListReportSeries.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/report/model/ListReportSeries.java index 18b011420..27f5fb3ec 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/report/model/ListReportSeries.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/report/model/ListReportSeries.java @@ -14,13 +14,11 @@ import java.util.List; /** * A simple list report series which just contains a list of values of a report. - * - * - * - * */ public class ListReportSeries extends AbstractReportSeries { + private static final long serialVersionUID = 1L; + private final List data = new ArrayList<>(); /** @@ -50,8 +48,8 @@ public class ListReportSeries extends AbstractReportSeries { * @param values */ private void setData(final Number... values) { - this.data.clear(); - Collections.addAll(this.data, values); + data.clear(); + Collections.addAll(data, values); } /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java index 6236e8d6f..5a2c6fdda 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java @@ -82,7 +82,6 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.Modifying; -import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -599,11 +598,16 @@ public class JpaDeploymentManagement implements DeploymentManagement { @Override public Page findActionsByTarget(final String rsqlParam, final Target target, final Pageable pageable) { - final Specification specification = RSQLUtility.parse(rsqlParam, ActionFields.class); - return convertAcPage(actionRepository.findAll((Specification) (root, query, cb) -> cb - .and(specification.toPredicate(root, query, cb), cb.equal(root.get(JpaAction_.target), target)), - pageable), pageable); + final Specification byTargetSpec = createSpecificationFor(target, rsqlParam); + final Page actions = actionRepository.findAll(byTargetSpec, pageable); + return convertAcPage(actions, pageable); + } + + private Specification createSpecificationFor(final Target target, final String rsqlParam) { + final Specification spec = RSQLUtility.parse(rsqlParam, ActionFields.class); + return (root, query, cb) -> cb.and(spec.toPredicate(root, query, cb), + cb.equal(root.get(JpaAction_.target), target)); } private static Page convertAcPage(final Page findAll, final Pageable pageable) { @@ -642,10 +646,7 @@ public class JpaDeploymentManagement implements DeploymentManagement { @Override public Long countActionsByTarget(final String rsqlParam, final Target target) { - final Specification spec = RSQLUtility.parse(rsqlParam, ActionFields.class); - - return actionRepository.count((root, query, cb) -> cb.and(spec.toPredicate(root, query, cb), - cb.equal(root.get(JpaAction_.target), target))); + return actionRepository.count(createSpecificationFor(target, rsqlParam)); } @Override diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java index 8736fefd7..e170ccad7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java @@ -483,7 +483,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { if (distributionSetMetadataRepository.exists(metadata.getId())) { throwMetadataKeyAlreadyExists(metadata.getId().getKey()); } - + touch(metadata.getDistributionSet()); return distributionSetMetadataRepository.save(metadata); } @@ -515,7 +515,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { findOne(metadata.getDistributionSet(), metadata.getKey()); // touch it to update the lock revision because we are modifying the // DS indirectly - touch(metadata.getDistributionSet());; + touch(metadata.getDistributionSet()); return distributionSetMetadataRepository.save(metadata); } @@ -528,8 +528,11 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } /** - * Method to get the latest distribution set based on ds ID after the metadata changes for that distribution set. - * @param distributionSet Distribution set + * Method to get the latest distribution set based on ds ID after the + * metadata changes for that distribution set. + * + * @param distributionSet + * Distribution set */ private void touch(final DistributionSet distributionSet) { final DistributionSet latestDistributionSet = findDistributionSetById(distributionSet.getId()); @@ -552,7 +555,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { @Override public List findDistributionSetMetadataByDistributionSetId(final Long distributionSetId) { - return new ArrayList(distributionSetMetadataRepository + return new ArrayList<>(distributionSetMetadataRepository .findAll((Specification) (root, query, cb) -> cb.equal( root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id), distributionSetId))); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java index 239302a70..3a903ea89 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java @@ -599,7 +599,7 @@ public class JpaRolloutManagement implements RolloutManagement { /** * Get count of targets in different status in rollout. * - * @param page + * @param pageable * the page request to sort and limit the result * @return a list of rollouts with details of targets count for different * statuses diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java index 65ed6faa4..6438e19f6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java @@ -26,7 +26,6 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specifications; import org.springframework.data.jpa.repository.Modifying; -import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/aspects/ExceptionMappingAspectHandler.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/aspects/ExceptionMappingAspectHandler.java index be21cdfe7..c18f614fd 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/aspects/ExceptionMappingAspectHandler.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/aspects/ExceptionMappingAspectHandler.java @@ -46,6 +46,7 @@ import org.springframework.transaction.TransactionSystemException; */ @Aspect public class ExceptionMappingAspectHandler implements Ordered { + private static final Logger LOG = LoggerFactory.getLogger(ExceptionMappingAspectHandler.class); private static final Map EXCEPTION_MAPPING = new HashMap<>(); @@ -63,6 +64,7 @@ public class ExceptionMappingAspectHandler implements Ordered { private final SQLStateSQLExceptionTranslator sqlStateExceptionTranslator = new SQLStateSQLExceptionTranslator(); static { + MAPPED_EXCEPTION_ORDER.add(DuplicateKeyException.class); MAPPED_EXCEPTION_ORDER.add(DataIntegrityViolationException.class); MAPPED_EXCEPTION_ORDER.add(ConcurrencyFailureException.class); @@ -90,9 +92,11 @@ public class ExceptionMappingAspectHandler implements Ordered { + " || execution( * org.eclipse.hawkbit.controller.*.*(..)) " + " || execution( * org.eclipse.hawkbit.rest.resource.*.*(..)) " + " || execution( * org.eclipse.hawkbit.service.*.*(..)) )", throwing = "ex") - // Exception squid:S00112 - Is aspectJ proxy - @SuppressWarnings({ "squid:S00112" }) + // Exception for squid:S00112, squid:S1162 + // It is a AspectJ proxy which deals with exceptions. + @SuppressWarnings({ "squid:S00112", "squid:S1162" }) public void catchAndWrapJpaExceptionsService(final Exception ex) throws Throwable { + LOG.trace("exception occured", ex); Exception translatedAccessException = translateEclipseLinkExceptionIfPossible(ex); @@ -122,6 +126,7 @@ public class ExceptionMappingAspectHandler implements Ordered { break; } } + LOG.trace("mapped exception {} to {}", translatedAccessException.getClass(), mappingException.getClass()); throw mappingException; } @@ -138,7 +143,7 @@ public class ExceptionMappingAspectHandler implements Ordered { * translate the exception by the sql error code. Luckily, there we can use * {@link SQLStateSQLExceptionTranslator} if we can get a * {@link SQLException}. - * + * * @param accessException * the base access exception from jpa * @return the translated accessException diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityPropertyChangeListener.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityPropertyChangeListener.java index 27fbc687e..429c128dd 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityPropertyChangeListener.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityPropertyChangeListener.java @@ -43,11 +43,11 @@ public class EntityPropertyChangeListener extends DescriptorEventAdapter { } } - private boolean isEventAwareEntity(final Object object) { + private static boolean isEventAwareEntity(final Object object) { return object instanceof EventAwareEntity; } - private void doNotifiy(final Runnable runnable) { + private static void doNotifiy(final Runnable runnable) { AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(runnable); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaActionStatus.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaActionStatus.java index 3a8cb8683..e1843eb33 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaActionStatus.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaActionStatus.java @@ -98,8 +98,8 @@ public class JpaActionStatus extends AbstractJpaTenantAwareBaseEntity implements * the status for this action status * @param occurredAt * the occurred timestamp - * @param messages - * the messages which should be added to this action status + * @param message + * the message which should be added to this action status */ public JpaActionStatus(final JpaAction action, final Status status, final Long occurredAt, final String message) { this.action = action; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java index 0fa2d0c33..661474668 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java @@ -34,7 +34,7 @@ import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.UniqueConstraint; -import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent; +import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent.PropertyChange; import org.eclipse.hawkbit.repository.eventbus.event.DistributionCreatedEvent; import org.eclipse.hawkbit.repository.eventbus.event.DistributionDeletedEvent; import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetUpdateEvent; @@ -299,8 +299,8 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen @Override public void fireUpdateEvent(final DescriptorEvent descriptorEvent) { - final Map.Values> changeSet = EntityPropertyChangeHelper - .getChangeSet(JpaDistributionSet.class, descriptorEvent); + final Map changeSet = EntityPropertyChangeHelper.getChangeSet(JpaDistributionSet.class, + descriptorEvent); EventBusHolder.getInstance().getEventBus().post(new DistributionSetUpdateEvent(this)); if (changeSet.containsKey(DELETED_PROPERTY)) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java index c91247321..c32a5e673 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java @@ -70,6 +70,7 @@ import org.springframework.data.domain.Persistable; // sub entities @SuppressWarnings("squid:S2160") public class JpaTarget extends AbstractJpaNamedEntity implements Persistable, Target, EventAwareEntity { + private static final long serialVersionUID = 1L; @Column(name = "controller_id", length = 64) @@ -185,7 +186,7 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Persistable, TargetInfo, EventAwareE private boolean requestControllerAttributes = true; /** - * Constructor for {@link TargetStatus}. + * Constructor for {@link JpaTargetInfo}. * * @param target * related to this status. @@ -149,7 +149,7 @@ public class JpaTargetInfo implements Persistable, TargetInfo, EventAwareE } /** - * @param isNew + * @param entityNew * the isNew to set */ public void setNew(final boolean entityNew) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/EntityPropertyChangeHelper.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/EntityPropertyChangeHelper.java index 2be398e24..9e759640d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/EntityPropertyChangeHelper.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/EntityPropertyChangeHelper.java @@ -11,7 +11,7 @@ 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.eventbus.event.AbstractPropertyChangeEvent.PropertyChange; import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; import org.eclipse.persistence.descriptors.DescriptorEvent; import org.eclipse.persistence.internal.sessions.ObjectChangeSet; @@ -32,15 +32,14 @@ public class EntityPropertyChangeHelper { * @param event * @return the map of the changeSet */ - public static Map.Values> getChangeSet( - final Class clazz, final DescriptorEvent event) { + public static Map getChangeSet(final Class 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(rolloutGroup, null).new Values( - record.getOldValue(), record.getNewValue()))); + record -> new PropertyChange(record.getOldValue(), record.getNewValue()))); } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtility.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtility.java index 91e03342e..90dd039f5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtility.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtility.java @@ -8,6 +8,8 @@ */ package org.eclipse.hawkbit.repository.jpa.rsql; +import static org.eclipse.hawkbit.repository.FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -15,7 +17,6 @@ import java.util.List; import java.util.Set; import java.util.stream.Collectors; -import javax.persistence.EntityManager; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; @@ -49,7 +50,7 @@ import cz.jirutka.rsql.parser.ast.RSQLVisitor; * A utility class which is able to parse RSQL strings into an spring data * {@link Specification} which then can be enhanced sql queries to filter * entities. RSQL parser library: https://github.com/jirutka/rsql-parser - * + * *
    *
  • Equal to : ==
  • *
  • Not equal to : !=
  • @@ -83,14 +84,12 @@ public final class RSQLUtility { /** * parses an RSQL valid string into an JPA {@link Specification} which then * can be used to filter for JPA entities with the given RSQL query. - * + * * @param rsql * the rsql query * @param fieldNameProvider * the enum class type which implements the * {@link FieldNameProvider} - * @param entityManager - * {@link EntityManager} * @return an specification which can be used with JPA * @throws RSQLParameterUnsupportedFieldException * if a field in the RSQL string is used but not provided by the @@ -105,10 +104,10 @@ public final class RSQLUtility { /** * Validate the given rsql string regarding existence and correct syntax. - * + * * @param rsql * the rsql string to get validated - * + * */ public static void isValid(final String rsql) { parseRsql(rsql); @@ -156,7 +155,7 @@ public final class RSQLUtility { /** * An implementation of the {@link RSQLVisitor} to visit the parsed tokens * and build jpa where clauses. - * + * * * * @param @@ -205,7 +204,7 @@ public final class RSQLUtility { } private String getAndValidatePropertyFieldName(final A propertyEnum, final ComparisonNode node) { - String finalProperty = propertyEnum.getFieldName(); + final String[] graph = node.getSelector().split("\\" + FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR); validateMapParamter(propertyEnum, node, graph); @@ -215,9 +214,12 @@ public final class RSQLUtility { throw createRSQLParameterUnsupportedException(node); } + final StringBuilder fieldNameBuilder = new StringBuilder(propertyEnum.getFieldName()); + for (int i = 1; i < graph.length; i++) { + final String propertyField = graph[i]; - finalProperty += FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR + propertyField; + fieldNameBuilder.append(SUB_ATTRIBUTE_SEPERATOR).append(propertyField); // the key of map is not in the graph if (propertyEnum.isMap() && graph.length == (i + 1)) { @@ -229,7 +231,7 @@ public final class RSQLUtility { } } - return finalProperty; + return fieldNameBuilder.toString(); } private void validateMapParamter(final A propertyEnum, final ComparisonNode node, final String[] graph) { diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/RestResourceConversionHelper.java b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/RestResourceConversionHelper.java index 0c9dd39c5..7e2fbed7c 100644 --- a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/RestResourceConversionHelper.java +++ b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/RestResourceConversionHelper.java @@ -9,11 +9,24 @@ package org.eclipse.hawkbit.rest.util; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.net.HttpHeaders.ACCEPT_RANGES; +import static com.google.common.net.HttpHeaders.CONTENT_DISPOSITION; +import static com.google.common.net.HttpHeaders.CONTENT_LENGTH; +import static com.google.common.net.HttpHeaders.CONTENT_RANGE; +import static com.google.common.net.HttpHeaders.ETAG; +import static com.google.common.net.HttpHeaders.IF_RANGE; +import static com.google.common.net.HttpHeaders.LAST_MODIFIED; +import static java.math.RoundingMode.DOWN; +import static javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT; +import static org.eclipse.hawkbit.rest.util.ByteRange.MULTIPART_BOUNDARY; +import static org.springframework.http.HttpStatus.OK; +import static org.springframework.http.HttpStatus.PARTIAL_CONTENT; +import static org.springframework.http.HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE; +import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.math.RoundingMode; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -27,23 +40,19 @@ import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.LocalArtifact; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import com.google.common.math.DoubleMath; -import com.google.common.net.HttpHeaders; /** * Utility class for the Rest Source API. - * */ public final class RestResourceConversionHelper { + private static final Logger LOG = LoggerFactory.getLogger(RestResourceConversionHelper.class); private static final int BUFFER_SIZE = 4096; - // utility class, private constructor. private RestResourceConversionHelper() { } @@ -92,7 +101,8 @@ public final class RestResourceConversionHelper { * * @return http code * - * @see https://tools.ietf.org/html/rfc7233 + * @see https://tools.ietf.org + * /html/rfc7233 */ public static ResponseEntity writeFileResponse(final LocalArtifact artifact, final HttpServletResponse response, final HttpServletRequest request, final DbArtifact file, @@ -107,11 +117,11 @@ public final class RestResourceConversionHelper { response.reset(); response.setBufferSize(BUFFER_SIZE); - response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + artifact.getFilename()); - response.setHeader(HttpHeaders.ETAG, etag); - response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes"); - response.setDateHeader(HttpHeaders.LAST_MODIFIED, lastModified); - response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); + response.setHeader(CONTENT_DISPOSITION, "attachment;filename=" + artifact.getFilename()); + response.setHeader(ETAG, etag); + response.setHeader(ACCEPT_RANGES, "bytes"); + response.setDateHeader(LAST_MODIFIED, lastModified); + response.setContentType(APPLICATION_OCTET_STREAM_VALUE); final ByteRange full = new ByteRange(0, length - 1, length); final List ranges = new ArrayList<>(); @@ -123,9 +133,9 @@ public final class RestResourceConversionHelper { // Range header matches"bytes=n-n,n-n,n-n..." if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) { - response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes */" + length); + response.setHeader(CONTENT_RANGE, "bytes */" + length); LOG.debug("range header for filename ({}) is not satisfiable: ", artifact.getFilename()); - return new ResponseEntity<>(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE); + return new ResponseEntity<>(REQUESTED_RANGE_NOT_SATISFIABLE); } // RFC: if the representation is unchanged, send me the part(s) that @@ -144,32 +154,31 @@ public final class RestResourceConversionHelper { // full request - no range if (ranges.isEmpty() || ranges.get(0).equals(full)) { LOG.debug("filename ({}) results into a full request: ", artifact.getFilename()); - fullfileRequest(artifact, response, file, controllerManagement, statusId, full); - result = new ResponseEntity<>(HttpStatus.OK); + handleFullFileRequest(artifact, response, file, controllerManagement, statusId, full); + result = new ResponseEntity<>(OK); } // standard range request else if (ranges.size() == 1) { LOG.debug("filename ({}) results into a standard range request: ", artifact.getFilename()); - standardRangeRequest(artifact, response, file, controllerManagement, statusId, ranges); - result = new ResponseEntity<>(HttpStatus.PARTIAL_CONTENT); + handleStandardRangeRequest(artifact, response, file, controllerManagement, statusId, ranges); + result = new ResponseEntity<>(PARTIAL_CONTENT); } // multipart range request else { LOG.debug("filename ({}) results into a multipart range request: ", artifact.getFilename()); - multipartRangeRequest(artifact, response, file, controllerManagement, statusId, ranges); - result = new ResponseEntity<>(HttpStatus.PARTIAL_CONTENT); + handleMultipartRangeRequest(artifact, response, file, controllerManagement, statusId, ranges); + result = new ResponseEntity<>(PARTIAL_CONTENT); } return result; - } - private static void fullfileRequest(final LocalArtifact artifact, final HttpServletResponse response, + private static void handleFullFileRequest(final LocalArtifact artifact, final HttpServletResponse response, final DbArtifact file, final ControllerManagement controllerManagement, final Long statusId, final ByteRange full) { final ByteRange r = full; - response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal()); - response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(r.getLength())); + response.setHeader(CONTENT_RANGE, "bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal()); + response.setHeader(CONTENT_LENGTH, String.valueOf(r.getLength())); try { copyStreams(file.getFileInputStream(), response.getOutputStream(), controllerManagement, statusId, @@ -182,7 +191,7 @@ public final class RestResourceConversionHelper { private static ResponseEntity extractRange(final HttpServletResponse response, final long length, final List ranges, final String range) { - ResponseEntity result = null; + if (ranges.isEmpty()) { for (final String part : range.substring(6).split(",")) { long start = sublong(part, 0, part.indexOf('-')); @@ -198,9 +207,8 @@ public final class RestResourceConversionHelper { // Check if Range is syntactically valid. If not, then return // 416. if (start > end) { - response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes */" + length); - result = new ResponseEntity<>(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE); - return result; + response.setHeader(CONTENT_RANGE, "bytes */" + length); + return new ResponseEntity<>(REQUESTED_RANGE_NOT_SATISFIABLE); } // Add range. @@ -218,10 +226,10 @@ public final class RestResourceConversionHelper { private static void checkForShortcut(final HttpServletRequest request, final String etag, final long lastModified, final ByteRange full, final List ranges) { - final String ifRange = request.getHeader(HttpHeaders.IF_RANGE); + final String ifRange = request.getHeader(IF_RANGE); if (ifRange != null && !ifRange.equals(etag)) { try { - final long ifRangeTime = request.getDateHeader(HttpHeaders.IF_RANGE); + final long ifRangeTime = request.getDateHeader(IF_RANGE); if (ifRangeTime != -1 && ifRangeTime + 1000 < lastModified) { ranges.add(full); } @@ -232,17 +240,17 @@ public final class RestResourceConversionHelper { } } - private static void multipartRangeRequest(final LocalArtifact artifact, final HttpServletResponse response, + private static void handleMultipartRangeRequest(final LocalArtifact artifact, final HttpServletResponse response, final DbArtifact file, final ControllerManagement controllerManagement, final Long statusId, final List ranges) { - response.setContentType("multipart/byteranges; boundary=" + ByteRange.MULTIPART_BOUNDARY); - response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); + response.setContentType("multipart/byteranges; boundary=" + MULTIPART_BOUNDARY); + response.setStatus(SC_PARTIAL_CONTENT); try { for (final ByteRange r : ranges) { // Add multipart boundary and header fields for every range. response.getOutputStream().println(); - response.getOutputStream().println("--" + ByteRange.MULTIPART_BOUNDARY); + response.getOutputStream().println("--" + MULTIPART_BOUNDARY); response.getOutputStream() .println("Content-Range: bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal()); @@ -253,20 +261,20 @@ public final class RestResourceConversionHelper { // End with final multipart boundary. response.getOutputStream().println(); - response.getOutputStream().print("--" + ByteRange.MULTIPART_BOUNDARY + "--"); + response.getOutputStream().print("--" + MULTIPART_BOUNDARY + "--"); } catch (final IOException e) { LOG.error("multipartRangeRequest of file ({}) failed!", artifact.getFilename(), e); throw new FileSteamingFailedException(artifact.getFilename()); } } - private static void standardRangeRequest(final LocalArtifact artifact, final HttpServletResponse response, + private static void handleStandardRangeRequest(final LocalArtifact artifact, final HttpServletResponse response, final DbArtifact file, final ControllerManagement controllerManagement, final Long statusId, final List ranges) { final ByteRange r = ranges.get(0); - response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal()); - response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(r.getLength())); - response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); + response.setHeader(CONTENT_RANGE, "bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal()); + response.setHeader(CONTENT_LENGTH, String.valueOf(r.getLength())); + response.setStatus(SC_PARTIAL_CONTENT); try { copyStreams(file.getFileInputStream(), response.getOutputStream(), controllerManagement, statusId, @@ -315,7 +323,7 @@ public final class RestResourceConversionHelper { } if (controllerManagement != null) { - final int newPercent = DoubleMath.roundToInt(total * 100.0 / length, RoundingMode.DOWN); + final int newPercent = DoubleMath.roundToInt(total * 100.0 / length, DOWN); // every 10 percent an event if (newPercent == 100 || newPercent > progressPercent + 10) { diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/DosFilter.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/DosFilter.java index 008aa3e95..89d0f4387 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/DosFilter.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/DosFilter.java @@ -100,7 +100,8 @@ public class DosFilter extends OncePerRequestFilter { boolean processChain; - final String ip = IpUtil.getClientIpFromRequest(request, forwardHeader, true).getHost(); + final String ip = IpUtil.getClientIpFromRequest(request, forwardHeader).getHost(); + if (checkIpFails(ip)) { processChain = handleMissingIpAddress(response); } else { @@ -121,7 +122,6 @@ public class DosFilter extends OncePerRequestFilter { if (processChain) { filterChain.doFilter(request, response); } - } /** diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/util/IpUtil.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/util/IpUtil.java index c7778f776..30306526a 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/util/IpUtil.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/util/IpUtil.java @@ -44,7 +44,7 @@ public final class IpUtil { * {@link HttpServletRequest} by either the * {@link HttpHeaders#X_FORWARDED_FOR} or by the * {@link HttpServletRequest#getRemoteAddr()} methods. - * + * * @param request * the {@link HttpServletRequest} to determine the IP address * where this request has been sent from @@ -65,21 +65,23 @@ public final class IpUtil { * {@link HttpServletRequest} by either the * {@link HttpHeaders#X_FORWARDED_FOR} or by the * {@link HttpServletRequest#getRemoteAddr()} methods. - * + * * @param request * the {@link HttpServletRequest} to determine the IP address * where this request has been sent from * @param forwardHeader * the header name containing the IP address e.g. forwarded by a * proxy {@code x-forwarded-for} - * - * @param trackRemoteIp - * to true if remote IP should be tracked. * @return the {@link URI} based IP address from the client which sent the * request */ - public static URI getClientIpFromRequest(final HttpServletRequest request, final String forwardHeader, + public static URI getClientIpFromRequest(final HttpServletRequest request, final String forwardHeader) { + return getClientIpFromRequest(request, forwardHeader, true); + } + + private static URI getClientIpFromRequest(final HttpServletRequest request, final String forwardHeader, final boolean trackRemoteIp) { + String ip; if (trackRemoteIp) { @@ -113,7 +115,7 @@ public final class IpUtil { /** * Create a {@link URI} with scheme and host. - * + * * @param scheme * the scheme * @param host @@ -132,7 +134,7 @@ public final class IpUtil { /** * Create a {@link URI} with amqp scheme and host. - * + * * @param host * the host * @param exchange @@ -147,7 +149,7 @@ public final class IpUtil { /** * Create a {@link URI} with http scheme and host. - * + * * @param host * the host * @return the {@link URI} @@ -160,7 +162,7 @@ public final class IpUtil { /** * Check if scheme contains http and uri ist not null. - * + * * @param uri * the uri * @return true = is http host false = not @@ -171,7 +173,7 @@ public final class IpUtil { /** * Check if host scheme amqp and uri ist not null. - * + * * @param uri * the uri * @return true = is http host false = not @@ -183,7 +185,7 @@ public final class IpUtil { /** * Check if the IP address of that {@link URI} is known, i.e. not an AQMP * exchange in DMF case and not HIDDEN_IP in DDI case. - * + * * @param uri * the uri * @return true if IP address is actually known by the server diff --git a/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/util/IpUtilTest.java b/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/util/IpUtilTest.java index 0f4a01d26..836a9f13e 100644 --- a/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/util/IpUtilTest.java +++ b/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/util/IpUtilTest.java @@ -8,6 +8,7 @@ */ package org.eclipse.hawkbit.util; +import static com.google.common.net.HttpHeaders.X_FORWARDED_FOR; import static org.fest.assertions.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -21,13 +22,13 @@ import java.net.URI; import javax.servlet.http.HttpServletRequest; +import org.eclipse.hawkbit.security.HawkbitSecurityProperties; +import org.eclipse.hawkbit.security.HawkbitSecurityProperties.Clients; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import com.google.common.net.HttpHeaders; - import ru.yandex.qatools.allure.annotations.Description; import ru.yandex.qatools.allure.annotations.Features; import ru.yandex.qatools.allure.annotations.Stories; @@ -37,69 +38,73 @@ import ru.yandex.qatools.allure.annotations.Stories; @Stories("IP Util Test") public class IpUtilTest { + private static final String KNOWN_REQUEST_HEADER = "bumlux"; + @Mock private HttpServletRequest requestMock; + @Mock + private Clients clientMock; + + @Mock + private HawkbitSecurityProperties securityPropertyMock; + @Test @Description("Tests create uri from request") public void getRemoteAddrFromRequestIfForwaredHeaderNotPresent() { - // known values + final URI knownRemoteClientIP = IpUtil.createHttpUri("127.0.0.1"); - // mock - when(requestMock.getHeader(HttpHeaders.X_FORWARDED_FOR)).thenReturn(null); + when(requestMock.getHeader(X_FORWARDED_FOR)).thenReturn(null); when(requestMock.getRemoteAddr()).thenReturn(knownRemoteClientIP.getHost()); - // test - final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "bumlux", true); + final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, KNOWN_REQUEST_HEADER); // verify assertThat(remoteAddr).as("The remote address should be as the known client IP address") .isEqualTo(knownRemoteClientIP); - verify(requestMock, times(1)).getHeader("bumlux"); + verify(requestMock, times(1)).getHeader(KNOWN_REQUEST_HEADER); verify(requestMock, times(1)).getRemoteAddr(); } @Test @Description("Tests create uri from request with masked IP when IP tracking is disabled") public void maskRemoteAddrIfDisabled() { - // known values + final URI knownRemoteClientIP = IpUtil.createHttpUri("***"); - // mock - when(requestMock.getHeader(HttpHeaders.X_FORWARDED_FOR)).thenReturn(null); + when(requestMock.getHeader(X_FORWARDED_FOR)).thenReturn(null); when(requestMock.getRemoteAddr()).thenReturn(knownRemoteClientIP.getHost()); + when(securityPropertyMock.getClients()).thenReturn(clientMock); + when(clientMock.getRemoteIpHeader()).thenReturn(KNOWN_REQUEST_HEADER); + when(clientMock.isTrackRemoteIp()).thenReturn(false); - // test - final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "bumlux", false); + final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, securityPropertyMock); - // verify assertThat(remoteAddr).as("The remote address should be as the known client IP address") .isEqualTo(knownRemoteClientIP); - verify(requestMock, times(0)).getHeader("bumlux"); + verify(requestMock, times(0)).getHeader(KNOWN_REQUEST_HEADER); verify(requestMock, times(0)).getRemoteAddr(); } @Test @Description("Tests create uri from x forward header") public void getRemoteAddrFromXForwardedForHeader() { - // known values + final URI knownRemoteClientIP = IpUtil.createHttpUri("10.99.99.1"); - // mock - when(requestMock.getHeader(HttpHeaders.X_FORWARDED_FOR)).thenReturn(knownRemoteClientIP.getHost()); + when(requestMock.getHeader(X_FORWARDED_FOR)).thenReturn(knownRemoteClientIP.getHost()); when(requestMock.getRemoteAddr()).thenReturn(null); - // test - final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "X-Forwarded-For", true); + final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "X-Forwarded-For"); - // verify assertThat(remoteAddr).as("The remote address should be as the known client IP address") .isEqualTo(knownRemoteClientIP); - verify(requestMock, times(1)).getHeader(HttpHeaders.X_FORWARDED_FOR); + verify(requestMock, times(1)).getHeader(X_FORWARDED_FOR); verify(requestMock, times(0)).getRemoteAddr(); } @Test @Description("Tests create http uri ipv4 and ipv6") public void testCreateHttpUri() { + final String ipv4 = "10.99.99.1"; URI httpUri = IpUtil.createHttpUri(ipv4); assertHttpUri(ipv4, httpUri); @@ -111,7 +116,6 @@ public class IpUtilTest { final String ipv6 = "0:0:0:0:0:0:0:1"; httpUri = IpUtil.createHttpUri(ipv6); assertHttpUri("[" + ipv6 + "]", httpUri); - } private void assertHttpUri(final String host, final URI httpUri) { @@ -124,6 +128,7 @@ public class IpUtilTest { @Test @Description("Tests create amqp uri ipv4 and ipv6") public void testCreateAmqpUri() { + final String ipv4 = "10.99.99.1"; URI amqpUri = IpUtil.createAmqpUri(ipv4, "path"); assertAmqpUri(ipv4, amqpUri); @@ -138,6 +143,7 @@ public class IpUtilTest { } private void assertAmqpUri(final String host, final URI amqpUri) { + assertTrue("The given URI is an AMQP scheme", IpUtil.isAmqpUri(amqpUri)); assertFalse("The given URI is not an HTTP scheme", IpUtil.isHttpUri(amqpUri)); assertEquals("The given host matches the URI host", host, amqpUri.getHost()); @@ -148,17 +154,19 @@ public class IpUtilTest { @Test @Description("Tests create invalid uri") public void testCreateInvalidUri() { + final String host = "10.99.99.1"; final URI testUri = IpUtil.createUri("test", host); + assertFalse("The given URI is not an AMQP address", IpUtil.isAmqpUri(testUri)); assertFalse("The given URI is not an HTTP address", IpUtil.isHttpUri(testUri)); assertEquals("The given host matches the URI host", host, testUri.getHost()); + try { IpUtil.createUri(":/", host); fail("Missing expected IllegalArgumentException due invalid URI"); } catch (final IllegalArgumentException e) { // expected } - } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/details/ArtifactBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/details/ArtifactBeanQuery.java index 4ba722284..d08474a5a 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/details/ArtifactBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/details/ArtifactBeanQuery.java @@ -8,6 +8,11 @@ */ package org.eclipse.hawkbit.ui.artifacts.details; +import static org.apache.commons.lang3.ArrayUtils.isEmpty; +import static org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil.isNotNullOrEmpty; +import static org.springframework.data.domain.Sort.Direction.ASC; +import static org.springframework.data.domain.Sort.Direction.DESC; + import java.util.List; import java.util.Map; @@ -15,7 +20,6 @@ import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.OffsetBasedPageRequest; import org.eclipse.hawkbit.repository.model.LocalArtifact; -import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.eclipse.hawkbit.ui.utils.SpringContextHelper; import org.springframework.data.domain.Page; @@ -39,7 +43,7 @@ public class ArtifactBeanQuery extends AbstractBeanQuery { /** * Parametric Constructor. - * + * * @param definition * as Def * @param queryConfig @@ -51,18 +55,18 @@ public class ArtifactBeanQuery extends AbstractBeanQuery { */ public ArtifactBeanQuery(final QueryDefinition definition, final Map queryConfig, final Object[] sortIds, final boolean[] sortStates) { + super(definition, queryConfig, sortIds, sortStates); - if (HawkbitCommonUtil.mapCheckStrKey(queryConfig)) { + if (isNotNullOrEmpty(queryConfig)) { baseSwModuleId = (Long) queryConfig.get(SPUIDefinitions.BY_BASE_SOFTWARE_MODULE); } - if (HawkbitCommonUtil.checkBolArray(sortStates)) { - // Initalize Sor - sort = new Sort(sortStates[0] ? Direction.ASC : Direction.DESC, (String) sortIds[0]); - // Add sort. + if (!isEmpty(sortStates)) { + sort = new Sort(sortStates[0] ? ASC : DESC, (String) sortIds[0]); + for (int targetId = 1; targetId < sortIds.length; targetId++) { - sort.and(new Sort(sortStates[targetId] ? Direction.ASC : Direction.DESC, (String) sortIds[targetId])); + sort.and(new Sort(sortStates[targetId] ? ASC : DESC, (String) sortIds[targetId])); } } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/details/ArtifactDetailsLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/details/ArtifactDetailsLayout.java index c62637117..8408f7c74 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/details/ArtifactDetailsLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/details/ArtifactDetailsLayout.java @@ -24,6 +24,7 @@ import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent; import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent.SoftwareModuleEventType; import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState; import org.eclipse.hawkbit.ui.common.ConfirmationDialog; +import org.eclipse.hawkbit.ui.common.builder.LabelBuilder; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; import org.eclipse.hawkbit.ui.components.SPUIButton; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; @@ -149,8 +150,8 @@ public class ArtifactDetailsLayout extends VerticalLayout { final SoftwareModule softwareModule = artifactUploadState.getSelectedBaseSoftwareModule().get(); labelStr = HawkbitCommonUtil.getFormattedNameVersion(softwareModule.getName(), softwareModule.getVersion()); } - titleOfArtifactDetails = SPUIComponentProvider.getLabel( - HawkbitCommonUtil.getArtifactoryDetailsLabelId(labelStr), SPUILabelDefinitions.SP_WIDGET_CAPTION); + titleOfArtifactDetails = new LabelBuilder().name(HawkbitCommonUtil.getArtifactoryDetailsLabelId(labelStr)) + .buildCaptionLabel(); titleOfArtifactDetails.setContentMode(ContentMode.HTML); titleOfArtifactDetails.setSizeFull(); titleOfArtifactDetails.setImmediate(true); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/BaseSwModuleBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/BaseSwModuleBeanQuery.java index 29bea30eb..103481f89 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/BaseSwModuleBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/BaseSwModuleBeanQuery.java @@ -43,7 +43,7 @@ public class BaseSwModuleBeanQuery extends AbstractBeanQuery queryConfig, final Object[] sortIds, final boolean[] sortStates) { super(definition, queryConfig, sortIds, sortStates); - if (HawkbitCommonUtil.mapCheckStrKey(queryConfig)) { + if (HawkbitCommonUtil.isNotNullOrEmpty(queryConfig)) { type = (SoftwareModuleType) queryConfig.get(SPUIDefinitions.BY_SOFTWARE_MODULE_TYPE); searchText = (String) queryConfig.get(SPUIDefinitions.FILTER_BY_TEXT); if (!Strings.isNullOrEmpty(searchText)) { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleAddUpdateWindow.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleAddUpdateWindow.java index c8eb74313..a437c0039 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleAddUpdateWindow.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleAddUpdateWindow.java @@ -18,9 +18,11 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent; import org.eclipse.hawkbit.ui.common.CommonDialogWindow; import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery; +import org.eclipse.hawkbit.ui.common.builder.TextAreaBuilder; +import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder; +import org.eclipse.hawkbit.ui.common.builder.WindowBuilder; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; -import org.eclipse.hawkbit.ui.decorators.SPUIWindowDecorator; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.I18N; import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; @@ -118,26 +120,17 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se } private void createRequiredComponents() { - /* name textfield */ - nameTextField = SPUIComponentProvider.getTextField(i18n.get("textfield.name"), "", ValoTheme.TEXTFIELD_TINY, - true, null, i18n.get("textfield.name"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH); - nameTextField.setId(SPUIComponentIdProvider.SOFT_MODULE_NAME); - /* version text field */ - versionTextField = SPUIComponentProvider.getTextField(i18n.get("textfield.version"), "", - ValoTheme.TEXTFIELD_TINY, true, null, i18n.get("textfield.version"), true, - SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH); - versionTextField.setId(SPUIComponentIdProvider.SOFT_MODULE_VERSION); + nameTextField = createTextField("textfield.name", SPUIComponentIdProvider.SOFT_MODULE_NAME); - /* Vendor text field */ - vendorTextField = SPUIComponentProvider.getTextField(i18n.get("textfield.vendor"), "", ValoTheme.TEXTFIELD_TINY, - false, null, i18n.get("textfield.vendor"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH); - vendorTextField.setId(SPUIComponentIdProvider.SOFT_MODULE_VENDOR); + versionTextField = createTextField("textfield.version", SPUIComponentIdProvider.SOFT_MODULE_VERSION); - descTextArea = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "text-area-style", - ValoTheme.TEXTAREA_TINY, false, null, i18n.get("textfield.description"), - SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH); - descTextArea.setId(SPUIComponentIdProvider.ADD_SW_MODULE_DESCRIPTION); + vendorTextField = createTextField("textfield.vendor", SPUIComponentIdProvider.SOFT_MODULE_VENDOR); + vendorTextField.setRequired(false); + + descTextArea = new TextAreaBuilder().caption(i18n.get("textfield.description")).style("text-area-style") + .prompt(i18n.get("textfield.description")).id(SPUIComponentIdProvider.ADD_SW_MODULE_DESCRIPTION) + .buildTextComponent(); typeComboBox = SPUIComponentProvider.getComboBox(i18n.get("upload.swmodule.type"), "", "", null, null, true, null, i18n.get("upload.swmodule.type")); @@ -148,6 +141,11 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se populateTypeNameCombo(); } + private TextField createTextField(final String in18Key, final String id) { + return new TextFieldBuilder().caption(i18n.get(in18Key)).required(true).prompt(i18n.get(in18Key)) + .immediate(true).id(id).buildTextComponent(); + } + private void populateTypeNameCombo() { typeComboBox.setContainerDataSource(HawkbitCommonUtil.createLazyQueryContainer( new BeanQueryFactory(SoftwareModuleTypeBeanQuery.class))); @@ -181,8 +179,11 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se setCompositionRoot(formLayout); - window = SPUIWindowDecorator.getWindow(i18n.get("upload.caption.add.new.swmodule"), null, - SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> saveOrUpdate(), null, null, formLayout, i18n); + window = new WindowBuilder(SPUIDefinitions.CREATE_UPDATE_WINDOW) + .caption(i18n.get("upload.caption.add.new.swmodule")).content(this) + .saveButtonClickListener(event -> saveOrUpdate()).layout(formLayout).i18n(i18n) + .buildCommonDialogWindow(); + window.getButtonsLayout().removeStyleName("actionButtonsMargin"); nameTextField.setEnabled(!editSwModule); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTable.java index 1cfd28718..8ce3b8519 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTable.java @@ -52,8 +52,8 @@ import com.vaadin.ui.UI; /** * Header of Software module table. */ -@SpringComponent @ViewScope +@SpringComponent public class SoftwareModuleTable extends AbstractNamedVersionTable { private static final long serialVersionUID = 6469417305487144809L; @@ -66,7 +66,7 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable refreshFilter()); + UI.getCurrent().access(this::refreshFilter); } } @@ -197,12 +197,12 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable showMetadataDetails((Long) itemId, nameVersionStr)); + manageMetaDataBtn.addClickListener(event -> showMetadataDetails((Long) itemId)); return manageMetaDataBtn; } }); } - + @Override protected List getTableVisibleColumns() { final List columnList = super.getTableVisibleColumns(); @@ -237,8 +237,7 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable onSave(), event -> onCancel(), null, mainLayout, - i18n); + + metadataWindow = new WindowBuilder(SPUIDefinitions.CUSTOM_METADATA_WINDOW) + .caption(getMetadataCaption(nameVersion)).content(this).saveButtonClickListener(event -> onSave()) + .cancelButtonClickListener(event -> onCancel()).layout(mainLayout).i18n(i18n).buildCommonDialogWindow(); + metadataWindow.setId(SPUIComponentIdProvider.METADATA_POPUP_ID); metadataWindow.setHeight(550, Unit.PIXELS); metadataWindow.setWidth(800, Unit.PIXELS); @@ -204,9 +207,9 @@ public abstract class AbstractMetadataPopupLayout onKeyChange(event)); keyField.setTextChangeEventMode(TextChangeEventMode.EAGER); keyField.setWidth("100%"); @@ -214,9 +217,9 @@ public abstract class AbstractMetadataPopupLayout 110) { - v = 1f - (y - 110f) / 110f; + v = 1F - (y - 110F) / 110F; } return new Color(Color.HSVtoRGB(h, s, v)); } - private int calculateYCoordinateOfColor(final float[] hsv) { + private static int calculateYCoordinateOfColor(final float[] hsv) { int y; // lower half /* Assuming hsv[] array value will have in the range of 0 to 1 */ - if (hsv[1] < 1f) { - y = Math.round(hsv[1] * 110f); + if (hsv[1] < 1F) { + y = Math.round(hsv[1] * 110F); } else { - y = Math.round(110f - (hsv[1] + hsv[2]) * 110f); + y = Math.round(110F - (hsv[1] + hsv[2]) * 110F); } return y; } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/builder/AbstractTextFieldBuilder.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/builder/AbstractTextFieldBuilder.java new file mode 100644 index 000000000..591983650 --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/builder/AbstractTextFieldBuilder.java @@ -0,0 +1,151 @@ +/** + * 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.ui.common.builder; + +import org.apache.commons.lang3.StringUtils; + +import com.vaadin.ui.AbstractTextField; + +/** + * Abstract Text field builder. + * + * @param + * the concrete text component + */ +public abstract class AbstractTextFieldBuilder { + + private String caption; + private String style; + private String styleName; + private String prompt; + private String id; + private boolean immediate; + private boolean required; + private int maxLengthAllowed; + + /** + * @param caption + * the caption to set + * @return the builder + */ + public AbstractTextFieldBuilder caption(final String caption) { + this.caption = caption; + return this; + } + + /** + * @param style + * the style to set * @return the builder + * @return the builder + */ + public AbstractTextFieldBuilder style(final String style) { + this.style = style; + return this; + } + + /** + * @param styleName + * the styleName to set + * @return the builder + */ + public AbstractTextFieldBuilder styleName(final String styleName) { + this.styleName = styleName; + return this; + } + + /** + * @param required + * the required to set + * @return the builder + */ + public AbstractTextFieldBuilder required(final boolean required) { + this.required = required; + return this; + } + + /** + * @param prompt + * the prompt to set + * @return the builder + */ + public AbstractTextFieldBuilder prompt(final String prompt) { + this.prompt = prompt; + return this; + } + + /** + * @param immediate + * the immediate to set + * @return the builder + */ + public AbstractTextFieldBuilder immediate(final boolean immediate) { + this.immediate = immediate; + return this; + } + + /** + * @param maxLengthAllowed + * the maxLengthAllowed to set + * @return the builder + */ + public AbstractTextFieldBuilder maxLengthAllowed(final int maxLengthAllowed) { + this.maxLengthAllowed = maxLengthAllowed; + return this; + } + + /** + * @param id + * the id to set + * @return the builder + */ + public AbstractTextFieldBuilder id(final String id) { + this.id = id; + return this; + } + + /** + * Build a textfield + * + * @return textfield + */ + public E buildTextComponent() { + final E textComponent = createTextComponent(); + + textComponent.setRequired(required); + textComponent.setImmediate(immediate); + + if (StringUtils.isNotEmpty(caption)) { + textComponent.setCaption(caption); + } + + if (StringUtils.isNotEmpty(style)) { + textComponent.setStyleName(style); + } + + if (StringUtils.isNotEmpty(styleName)) { + textComponent.addStyleName(styleName); + } + if (StringUtils.isNotEmpty(prompt)) { + textComponent.setInputPrompt(prompt); + } + + if (maxLengthAllowed > 0) { + textComponent.setMaxLength(maxLengthAllowed); + } + + if (StringUtils.isNotEmpty(id)) { + textComponent.setId(id); + } + + return textComponent; + } + + protected abstract E createTextComponent(); + +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/builder/LabelBuilder.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/builder/LabelBuilder.java new file mode 100644 index 000000000..12d50149a --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/builder/LabelBuilder.java @@ -0,0 +1,96 @@ +/** + * 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.ui.common.builder; + +import com.vaadin.ui.Label; +import com.vaadin.ui.themes.ValoTheme; + +/** + * Label Builder. + * + */ +public class LabelBuilder { + + private String name; + + private String id; + + private boolean visible = true; + + /** + * @param name + * the name to set + * @return builder + */ + public LabelBuilder name(final String name) { + this.name = name; + return this; + } + + /** + * @param id + * the id to set + * @return builder + */ + public LabelBuilder id(final String id) { + this.id = id; + return this; + } + + /** + * @param visible + * the visible to set + * @return builder + */ + public LabelBuilder visible(final boolean visible) { + this.visible = visible; + return this; + } + + /** + * Build caption label. + * + * @return Label + */ + public Label buildCaptionLabel() { + final Label label = createLabel(); + label.setValue(name); + label.addStyleName("header-caption"); + return label; + } + + /** + * Build label. + * + * @return Label + */ + public Label buildLabel() { + final Label label = createLabel(); + label.setImmediate(false); + label.setWidth("-1px"); + label.setHeight("-1px"); + + return label; + } + + private Label createLabel() { + final Label label = new Label(name); + label.setVisible(visible); + final StringBuilder style = new StringBuilder(ValoTheme.LABEL_SMALL); + style.append(' '); + style.append(ValoTheme.LABEL_BOLD); + label.addStyleName(style.toString()); + if (id != null) { + label.setId(id); + } + + return label; + } + +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/builder/TextAreaBuilder.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/builder/TextAreaBuilder.java new file mode 100644 index 000000000..d75b408d4 --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/builder/TextAreaBuilder.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.ui.common.builder; + +import com.vaadin.ui.TextArea; +import com.vaadin.ui.themes.ValoTheme; + +/** + * TextArea builder. + * + */ +public class TextAreaBuilder extends AbstractTextFieldBuilder