Merge branch 'eclipse/master' into
fix_unhandled_ConstraintViolationException Conflicts: hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTable.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTable.java Signed-off-by: SirWayne <dennis.melzer@bosch-si.com>
This commit is contained in:
@@ -24,6 +24,12 @@ The simulator has user authentication enabled in **cloud profile**. Default cred
|
||||
|
||||
This can be configured/disabled by spring boot properties
|
||||
|
||||
## hawkBit APIs
|
||||
|
||||
The simulator supports `DDI` as well as the `DMF` integration APIs.
|
||||
In case there is no AMQP message broker (like rabbitMQ) running, you can disable the AMQP support for the device simulator, so the simulator is not trying to connect to an amqp message broker.
|
||||
Configuration property `hawkbit.device.simulator.amqp.enabled=true`
|
||||
|
||||
## Usage
|
||||
|
||||
### Graphical User Interface
|
||||
|
||||
@@ -17,6 +17,4 @@ applications:
|
||||
services:
|
||||
- dmf-rabbit
|
||||
env:
|
||||
SPRING_PROFILES_ACTIVE: cloud,amqp
|
||||
CF_STAGING_TIMEOUT: 15
|
||||
CF_STARTUP_TIMEOUT: 15
|
||||
SPRING_PROFILES_ACTIVE: cloud
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ public class SimulatedDeviceFactory {
|
||||
final int pollDelaySec, final URL baseEndpoint, final String gatewayToken) {
|
||||
switch (protocol) {
|
||||
case DMF_AMQP:
|
||||
spSenderService.createOrUpdateThing(tenant, id);
|
||||
return new DMFSimulatedDevice(id, tenant, spSenderService, pollDelaySec);
|
||||
case DDI_HTTP:
|
||||
final ControllerResource controllerResource = Feign.builder().logger(new Logger.ErrorLogger())
|
||||
|
||||
@@ -8,11 +8,13 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.simulator;
|
||||
|
||||
import static org.eclipse.hawkbit.simulator.amqp.AmqpProperties.CONFIGURATION_PREFIX;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
||||
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
||||
import org.eclipse.hawkbit.simulator.amqp.AmqpProperties;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@@ -21,22 +23,19 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* REST endpoint for controlling the device simulator.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@RestController
|
||||
public class SimulationController {
|
||||
|
||||
@Autowired
|
||||
private SpSenderService spSenderService;
|
||||
|
||||
@Autowired
|
||||
private DeviceSimulatorRepository repository;
|
||||
|
||||
@Autowired
|
||||
private SimulatedDeviceFactory deviceFactory;
|
||||
|
||||
@Autowired
|
||||
private AmqpProperties amqpProperties;
|
||||
|
||||
/**
|
||||
* The start resource to start a device creation.
|
||||
*
|
||||
@@ -82,6 +81,12 @@ public class SimulationController {
|
||||
return ResponseEntity.badRequest().body("query param api only allows value of 'dmf' or 'ddi'");
|
||||
}
|
||||
|
||||
if (protocol == Protocol.DMF_AMQP && isDmfDisabled()) {
|
||||
return ResponseEntity.badRequest()
|
||||
.body("The AMQP interface has been disabled, to use DMF protocol you need to enable the AMQP interface via '"
|
||||
+ CONFIGURATION_PREFIX + ".enabled=true'");
|
||||
}
|
||||
|
||||
for (int i = 0; i < amount; i++) {
|
||||
final String deviceId = name + i;
|
||||
repository.add(deviceFactory.createSimulatedDevice(deviceId, tenant, protocol, pollDelay, new URL(endpoint),
|
||||
@@ -90,4 +95,8 @@ public class SimulationController {
|
||||
|
||||
return ResponseEntity.ok("Updated " + amount + " DMF connected targets!");
|
||||
}
|
||||
|
||||
private boolean isDmfDisabled() {
|
||||
return !amqpProperties.isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ package org.eclipse.hawkbit.simulator;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
||||
import org.eclipse.hawkbit.simulator.amqp.AmqpProperties;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -32,24 +32,27 @@ public class SimulatorStartup implements ApplicationListener<ContextRefreshedEve
|
||||
@Autowired
|
||||
private SimulationProperties simulationProperties;
|
||||
|
||||
@Autowired
|
||||
private SpSenderService spSenderService;
|
||||
|
||||
@Autowired
|
||||
private DeviceSimulatorRepository repository;
|
||||
|
||||
@Autowired
|
||||
private SimulatedDeviceFactory deviceFactory;
|
||||
|
||||
@Autowired
|
||||
private AmqpProperties amqpProperties;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(final ContextRefreshedEvent event) {
|
||||
simulationProperties.getAutostarts().forEach(autostart -> {
|
||||
for (int i = 0; i < autostart.getAmount(); i++) {
|
||||
final String deviceId = autostart.getName() + i;
|
||||
try {
|
||||
repository.add(deviceFactory.createSimulatedDevice(deviceId, autostart.getTenant(),
|
||||
autostart.getApi(), autostart.getPollDelay(), new URL(autostart.getEndpoint()),
|
||||
autostart.getGatewayToken()));
|
||||
if (amqpProperties.isEnabled()) {
|
||||
repository.add(deviceFactory.createSimulatedDevice(deviceId, autostart.getTenant(),
|
||||
autostart.getApi(), autostart.getPollDelay(), new URL(autostart.getEndpoint()),
|
||||
autostart.getGatewayToken()));
|
||||
}
|
||||
|
||||
} catch (final MalformedURLException e) {
|
||||
LOGGER.error("Creation of simulated device at startup failed.", e);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.simulator.amqp;
|
||||
|
||||
import static org.eclipse.hawkbit.simulator.amqp.AmqpProperties.CONFIGURATION_PREFIX;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -27,6 +29,7 @@ import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -39,6 +42,7 @@ import org.springframework.retry.support.RetryTemplate;
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(AmqpProperties.class)
|
||||
@ConditionalOnProperty(prefix = CONFIGURATION_PREFIX, name = "enabled")
|
||||
public class AmqpConfiguration {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AmqpConfiguration.class);
|
||||
|
||||
@@ -19,6 +19,17 @@ import org.springframework.stereotype.Component;
|
||||
@Component
|
||||
@ConfigurationProperties("hawkbit.device.simulator.amqp")
|
||||
public class AmqpProperties {
|
||||
|
||||
/**
|
||||
* The prefix for this configuration.
|
||||
*/
|
||||
public static final String CONFIGURATION_PREFIX = "hawkbit.device.simulator.amqp";
|
||||
|
||||
/**
|
||||
* Indicates if the AMQP interface is enabled for the device simulator.
|
||||
*/
|
||||
private boolean enabled;
|
||||
|
||||
/**
|
||||
* Queue for receiving DMF messages from update server.
|
||||
*/
|
||||
@@ -84,4 +95,12 @@ public class AmqpProperties {
|
||||
public void setDeadLetterTtl(final int deadLetterTtl) {
|
||||
this.deadLetterTtl = deadLetterTtl;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(final boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.simulator.amqp;
|
||||
|
||||
import static org.eclipse.hawkbit.simulator.amqp.AmqpProperties.CONFIGURATION_PREFIX;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
|
||||
@@ -22,6 +24,7 @@ import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.messaging.handler.annotation.Header;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -32,6 +35,7 @@ import com.google.common.collect.Lists;
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
@ConditionalOnProperty(prefix = CONFIGURATION_PREFIX, name = "enabled")
|
||||
public class SpReceiverService extends ReceiverService {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ReceiverService.class);
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ public class GenerateDialog extends Window {
|
||||
private final TextField gatewayTokenTextField;
|
||||
private OptionGroup protocolGroup;
|
||||
private Button buttonOk;
|
||||
private final boolean dmfEnabled;
|
||||
|
||||
/**
|
||||
* Creates a new pop window for setting the configuration of simulating
|
||||
@@ -60,9 +61,12 @@ public class GenerateDialog extends Window {
|
||||
* @param callback
|
||||
* the callback which is called when the dialog has been
|
||||
* successfully confirmed.
|
||||
* @param dmfEnabled
|
||||
* indicates if the AMQP/DMF interface is enabled by
|
||||
* configuration and if the option DMF should be enabled or not
|
||||
*/
|
||||
public GenerateDialog(final GenerateDialogCallback callback) {
|
||||
|
||||
public GenerateDialog(final GenerateDialogCallback callback, final boolean dmfEnabled) {
|
||||
this.dmfEnabled = dmfEnabled;
|
||||
formLayout.setSpacing(true);
|
||||
formLayout.setMargin(true);
|
||||
|
||||
@@ -187,15 +191,19 @@ public class GenerateDialog extends Window {
|
||||
this.protocolGroup = new OptionGroup("Simulated Device Protocol");
|
||||
protocolGroup.addItem(Protocol.DMF_AMQP);
|
||||
protocolGroup.addItem(Protocol.DDI_HTTP);
|
||||
protocolGroup.select(Protocol.DMF_AMQP);
|
||||
protocolGroup.setItemCaption(Protocol.DMF_AMQP, "Device Management Federation API (AMQP push)");
|
||||
protocolGroup.setItemCaption(Protocol.DDI_HTTP, "Direct Device Interface (HTTP poll)");
|
||||
protocolGroup.setNullSelectionAllowed(false);
|
||||
protocolGroup.select(Protocol.DMF_AMQP);
|
||||
protocolGroup.addValueChangeListener(event -> {
|
||||
final boolean directDeviceOptionSelected = event.getProperty().getValue().equals(Protocol.DDI_HTTP);
|
||||
pollUrlTextField.setVisible(directDeviceOptionSelected);
|
||||
gatewayTokenTextField.setVisible(directDeviceOptionSelected);
|
||||
});
|
||||
protocolGroup.setItemEnabled(Protocol.DMF_AMQP, dmfEnabled);
|
||||
if (!dmfEnabled) {
|
||||
protocolGroup.select(Protocol.DDI_HTTP);
|
||||
}
|
||||
}
|
||||
|
||||
private void createOkButton(final GenerateDialogCallback callback) {
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Status;
|
||||
import org.eclipse.hawkbit.simulator.DeviceSimulatorRepository;
|
||||
import org.eclipse.hawkbit.simulator.SimulatedDeviceFactory;
|
||||
import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus;
|
||||
import org.eclipse.hawkbit.simulator.amqp.AmqpProperties;
|
||||
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
||||
import org.eclipse.hawkbit.simulator.event.InitUpdate;
|
||||
import org.eclipse.hawkbit.simulator.event.NextPollCounterUpdate;
|
||||
@@ -90,6 +91,9 @@ public class SimulatorView extends VerticalLayout implements View {
|
||||
@Autowired
|
||||
private transient EventBus eventbus;
|
||||
|
||||
@Autowired
|
||||
private transient AmqpProperties amqpProperties;
|
||||
|
||||
private final Label caption = new Label("DMF/DDI Simulated Devices");
|
||||
private final HorizontalLayout toolbar = new HorizontalLayout();
|
||||
private final Grid grid = new Grid();
|
||||
@@ -266,9 +270,8 @@ public class SimulatorView extends VerticalLayout implements View {
|
||||
final String deviceId = namePrefix + index;
|
||||
beanContainer.addBean(repository.add(deviceFactory.createSimulatedDevice(deviceId,
|
||||
tenant.toLowerCase(), protocol, pollDelay, basePollUrl, gatewayToken)));
|
||||
spSenderService.createOrUpdateThing(tenant, deviceId);
|
||||
}
|
||||
}));
|
||||
}, amqpProperties.isEnabled()));
|
||||
}
|
||||
|
||||
private ProtocolConverter createProtocolConverter() {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#
|
||||
|
||||
## Configuration for DMF communication
|
||||
hawkbit.device.simulator.amqp.enabled=true
|
||||
hawkbit.device.simulator.amqp.receiverConnectorQueueFromSp=simulator_receiver
|
||||
hawkbit.device.simulator.amqp.deadLetterQueue=simulator_deadletter
|
||||
hawkbit.device.simulator.amqp.deadLetterExchange=simulator.deadletter
|
||||
|
||||
@@ -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 <true> contains <false> contains not
|
||||
*/
|
||||
default boolean containsSubEntityAttribute(final String propertyField) {
|
||||
return FieldNameProvider.containsSubEntityAttribute(propertyField, getSubEntityAttributes());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return all sub entities attributes.
|
||||
*/
|
||||
default List<String> 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 <true> is a map <false> 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 <true> property exists <false> not exists
|
||||
*/
|
||||
static boolean containsSubEntityAttribute(final String propertyField, final List<String> subEntityAttribues) {
|
||||
if (subEntityAttribues.contains(propertyField)) {
|
||||
final List<String> 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<String> 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 <true> is a map <false> is not a map
|
||||
*/
|
||||
default boolean isMap() {
|
||||
return getKeyFieldName() != null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import org.eclipse.hawkbit.repository.RepositoryConstants;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.TenantNotExistException;
|
||||
import org.eclipse.hawkbit.repository.exception.ToManyStatusEntriesException;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
@@ -153,8 +154,8 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
return handleAuthentifiactionMessage(message);
|
||||
} catch (final IllegalArgumentException ex) {
|
||||
throw new AmqpRejectAndDontRequeueException("Invalid message!", ex);
|
||||
} catch (final TenantNotExistException teex) {
|
||||
throw new AmqpRejectAndDontRequeueException(teex);
|
||||
} catch (final TenantNotExistException | ToManyStatusEntriesException e) {
|
||||
throw new AmqpRejectAndDontRequeueException(e);
|
||||
} finally {
|
||||
SecurityContextHolder.setContext(oldContext);
|
||||
}
|
||||
|
||||
@@ -8,8 +8,9 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* {@link Map} with attributes of SP Target.
|
||||
*
|
||||
*/
|
||||
public class MgmtTargetAttributes extends HashMap<String, String> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -281,6 +281,16 @@ public interface DistributionSetManagement {
|
||||
Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(@NotNull Long distributionSetId,
|
||||
@NotNull Pageable pageable);
|
||||
|
||||
/**
|
||||
* Finds all meta data by the given distribution set id.
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the distribution set id to retrieve the meta data from
|
||||
* @return list of distributionSetMetadata for a given distribution set Id.
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
List<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(@NotNull Long distributionSetId);
|
||||
|
||||
/**
|
||||
* finds all meta data by the given distribution set id.
|
||||
*
|
||||
|
||||
@@ -483,5 +483,23 @@ public interface SoftwareManagement {
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
|
||||
SoftwareModuleType updateSoftwareModuleType(@NotNull SoftwareModuleType sm);
|
||||
|
||||
/**
|
||||
* Finds all meta data by the given software module id.
|
||||
*
|
||||
* @param softwareModuleId
|
||||
* the software module id to retrieve the meta data from
|
||||
|
||||
*
|
||||
* @throws RSQLParameterUnsupportedFieldException
|
||||
* if a field in the RSQL string is used but not provided by the
|
||||
* given {@code fieldNameProvider}
|
||||
* @throws RSQLParameterSyntaxException
|
||||
* if the RSQL syntax is wrong
|
||||
* @return result of all meta data entries for a given software
|
||||
* module id.
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
List<SoftwareModuleMetadata> findSoftwareModuleMetadataBySoftwareModuleId(Long softwareModuleId);
|
||||
|
||||
}
|
||||
|
||||
@@ -20,18 +20,18 @@ import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
|
||||
public class AbstractPropertyChangeEvent<E extends TenantAwareBaseEntity> extends AbstractBaseEntityEvent<E> {
|
||||
|
||||
private static final long serialVersionUID = -3671601415138242311L;
|
||||
private final transient Map<String, Values> changeSet;
|
||||
private final transient Map<String, PropertyChange> 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<String, Values> changeSetValues) {
|
||||
public AbstractPropertyChangeEvent(final E baseEntity, final Map<String, PropertyChange> changeSetValues) {
|
||||
super(baseEntity);
|
||||
this.changeSet = changeSetValues;
|
||||
}
|
||||
@@ -39,27 +39,27 @@ public class AbstractPropertyChangeEvent<E extends TenantAwareBaseEntity> extend
|
||||
/**
|
||||
* @return the changeSet
|
||||
*/
|
||||
public Map<String, Values> getChangeSet() {
|
||||
public Map<String, PropertyChange> 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<E extends TenantAwareBaseEntity> extend
|
||||
public Object getNewValue() {
|
||||
return newValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,7 @@ public class ActionPropertyChangeEvent extends AbstractPropertyChangeEvent<Actio
|
||||
* @param action
|
||||
* @param changeSetValues
|
||||
*/
|
||||
public ActionPropertyChangeEvent(final Action action,
|
||||
final Map<String, AbstractPropertyChangeEvent<Action>.Values> changeSetValues) {
|
||||
public ActionPropertyChangeEvent(final Action action, final Map<String, PropertyChange> changeSetValues) {
|
||||
super(action, changeSetValues);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.eventbus.event;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
|
||||
/**
|
||||
* Defines the {@link AbstractBaseEntityEvent} of creating a new {@link DistributionSet}.
|
||||
*
|
||||
*/
|
||||
public class DistributionCreatedEvent extends AbstractBaseEntityEvent<DistributionSet> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* @param distributionSet
|
||||
* the distributionSet which has been created
|
||||
*/
|
||||
public DistributionCreatedEvent(final DistributionSet distributionSet) {
|
||||
super(distributionSet);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.eventbus.event;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.event.AbstractDistributedEvent;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
|
||||
/**
|
||||
* Defines the {@link AbstractDistributedEvent} for deletion of
|
||||
* {@link DistributionSet}.
|
||||
*/
|
||||
public class DistributionDeletedEvent extends AbstractDistributedEvent {
|
||||
private static final long serialVersionUID = -3308850381757843098L;
|
||||
private final Long distributionId;
|
||||
|
||||
/**
|
||||
* @param tenant
|
||||
* the tenant for this event
|
||||
* @param distributionId
|
||||
* the ID of the distribution set which has been deleted
|
||||
*/
|
||||
public DistributionDeletedEvent(final String tenant, final Long distributionId) {
|
||||
super(-1, tenant);
|
||||
this.distributionId = distributionId;
|
||||
}
|
||||
|
||||
public Long getDistributionSetId() {
|
||||
return distributionId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.eventbus.event;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
|
||||
/**
|
||||
* Defines the {@link AbstractBaseEntityEvent} for update a {@link DistributionSet}.
|
||||
*
|
||||
*/
|
||||
public class DistributionSetUpdateEvent extends AbstractBaseEntityEvent<DistributionSet> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param ds Distribution Set
|
||||
*/
|
||||
public DistributionSetUpdateEvent(final DistributionSet ds) {
|
||||
super(ds);
|
||||
}
|
||||
}
|
||||
@@ -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<String, AbstractPropertyChangeEvent<RolloutGroup>.Values> changeSetValues) {
|
||||
final Map<String, PropertyChange> changeSetValues) {
|
||||
super(rolloutGroup, changeSetValues);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,12 +19,11 @@ public class RolloutPropertyChangeEvent extends AbstractPropertyChangeEvent<Roll
|
||||
private static final long serialVersionUID = 1056221355466373514L;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param rollout
|
||||
* @param changeSetValues
|
||||
*/
|
||||
public RolloutPropertyChangeEvent(final Rollout rollout,
|
||||
final Map<String, AbstractPropertyChangeEvent<Rollout>.Values> changeSetValues) {
|
||||
public RolloutPropertyChangeEvent(final Rollout rollout, final Map<String, PropertyChange> changeSetValues) {
|
||||
super(rollout, changeSetValues);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.eventbus.event;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.event.AbstractDistributedEvent;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
|
||||
/**
|
||||
*
|
||||
* Defines the {@link AbstractBaseEntityEvent} of deleting a {@link Target}.
|
||||
*/
|
||||
public class TargetDeletedEvent extends AbstractDistributedEvent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final long targetId;
|
||||
|
||||
/**
|
||||
* @param tenant
|
||||
* the tenant for this event
|
||||
* @param targetId
|
||||
* the ID of the target which has been deleted
|
||||
*/
|
||||
public TargetDeletedEvent(final String tenant, final long targetId) {
|
||||
super(-1, tenant);
|
||||
this.targetId = targetId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the targetId
|
||||
*/
|
||||
public long getTargetId() {
|
||||
return targetId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.eventbus.event;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
|
||||
/**
|
||||
* Defines the {@link AbstractBaseEntityEvent} of updating a {@link Target}.
|
||||
*
|
||||
*/
|
||||
public class TargetUpdatedEvent extends AbstractBaseEntityEvent<Target> {
|
||||
|
||||
private static final long serialVersionUID = 5665118668865832477L;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param baseEntity
|
||||
* Target entity
|
||||
*/
|
||||
public TargetUpdatedEvent(final Target baseEntity) {
|
||||
super(baseEntity);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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<Number> 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<Action> findActionsByTarget(final String rsqlParam, final Target target, final Pageable pageable) {
|
||||
final Specification<JpaAction> specification = RSQLUtility.parse(rsqlParam, ActionFields.class);
|
||||
|
||||
return convertAcPage(actionRepository.findAll((Specification<JpaAction>) (root, query, cb) -> cb
|
||||
.and(specification.toPredicate(root, query, cb), cb.equal(root.get(JpaAction_.target), target)),
|
||||
pageable), pageable);
|
||||
final Specification<JpaAction> byTargetSpec = createSpecificationFor(target, rsqlParam);
|
||||
final Page<JpaAction> actions = actionRepository.findAll(byTargetSpec, pageable);
|
||||
return convertAcPage(actions, pageable);
|
||||
}
|
||||
|
||||
private Specification<JpaAction> createSpecificationFor(final Target target, final String rsqlParam) {
|
||||
final Specification<JpaAction> 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<Action> convertAcPage(final Page<JpaAction> 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<JpaAction> 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
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.eclipse.hawkbit.repository.DistributionSetMetadataFields;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetTypeFields;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.repository.TagManagement;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetTagAssigmentResultEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityLockedException;
|
||||
@@ -54,6 +55,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
@@ -102,6 +104,9 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
@Autowired
|
||||
private AfterTransactionCommitExecutor afterCommit;
|
||||
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
|
||||
@Override
|
||||
public DistributionSet findDistributionSetByIdWithDetails(final Long distid) {
|
||||
return distributionSetRepository.findOne(DistributionSetSpecification.byId(distid));
|
||||
@@ -193,6 +198,9 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
// handle the empty list
|
||||
distributionSetRepository.deleteByIdIn(toHardDelete);
|
||||
}
|
||||
|
||||
Arrays.stream(distributionSetIDs)
|
||||
.forEach(dsId -> eventBus.post(new DistributionDeletedEvent(tenantAware.getCurrentTenant(), dsId)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -475,11 +483,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
if (distributionSetMetadataRepository.exists(metadata.getId())) {
|
||||
throwMetadataKeyAlreadyExists(metadata.getId().getKey());
|
||||
}
|
||||
// merge base distribution set so optLockRevision gets updated and audit
|
||||
// log written because
|
||||
// modifying metadata is modifying the base distribution set itself for
|
||||
// auditing purposes.
|
||||
entityManager.merge((JpaDistributionSet) metadata.getDistributionSet()).setLastModifiedAt(0L);
|
||||
|
||||
touch(metadata.getDistributionSet());
|
||||
return distributionSetMetadataRepository.save(metadata);
|
||||
}
|
||||
|
||||
@@ -494,7 +499,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
for (final JpaDistributionSetMetadata distributionSetMetadata : metadata) {
|
||||
checkAndThrowAlreadyIfDistributionSetMetadataExists(distributionSetMetadata.getId());
|
||||
}
|
||||
metadata.forEach(m -> entityManager.merge((JpaDistributionSet) m.getDistributionSet()).setLastModifiedAt(0L));
|
||||
metadata.forEach(m -> touch(m.getDistributionSet()));
|
||||
|
||||
return new ArrayList<>(
|
||||
(Collection<? extends DistributionSetMetadata>) distributionSetMetadataRepository.save(metadata));
|
||||
@@ -510,7 +515,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
findOne(metadata.getDistributionSet(), metadata.getKey());
|
||||
// touch it to update the lock revision because we are modifying the
|
||||
// DS indirectly
|
||||
entityManager.merge((JpaDistributionSet) metadata.getDistributionSet()).setLastModifiedAt(0L);
|
||||
touch(metadata.getDistributionSet());
|
||||
return distributionSetMetadataRepository.save(metadata);
|
||||
}
|
||||
|
||||
@@ -518,13 +523,29 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
|
||||
@Modifying
|
||||
public void deleteDistributionSetMetadata(final DistributionSet distributionSet, final String key) {
|
||||
touch(distributionSet);
|
||||
distributionSetMetadataRepository.delete(new DsMetadataCompositeKey(distributionSet, key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the latest distribution set based on ds ID after the
|
||||
* metadata changes for that distribution set.
|
||||
*
|
||||
* @param distributionSet
|
||||
* Distribution set
|
||||
*/
|
||||
private void touch(final DistributionSet distributionSet) {
|
||||
final DistributionSet latestDistributionSet = findDistributionSetById(distributionSet.getId());
|
||||
// merge base distribution set so optLockRevision gets updated and audit
|
||||
// log written because
|
||||
// modifying metadata is modifying the base distribution set itself for
|
||||
// auditing purposes.
|
||||
entityManager.merge((JpaDistributionSet) latestDistributionSet).setLastModifiedAt(0L);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(final Long distributionSetId,
|
||||
final Pageable pageable) {
|
||||
|
||||
return convertMdPage(distributionSetMetadataRepository
|
||||
.findAll((Specification<JpaDistributionSetMetadata>) (root, query, cb) -> cb.equal(
|
||||
root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id),
|
||||
@@ -532,6 +553,14 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(final Long distributionSetId) {
|
||||
return new ArrayList<>(distributionSetMetadataRepository
|
||||
.findAll((Specification<JpaDistributionSetMetadata>) (root, query, cb) -> cb.equal(
|
||||
root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id),
|
||||
distributionSetId)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(final Long distributionSetId,
|
||||
final String rsqlParam, final Pageable pageable) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -621,6 +621,16 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
||||
pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SoftwareModuleMetadata> findSoftwareModuleMetadataBySoftwareModuleId(final Long softwareModuleId) {
|
||||
return new ArrayList<>(
|
||||
softwareModuleMetadataRepository
|
||||
.findAll((Specification<JpaSoftwareModuleMetadata>) (root, query,
|
||||
cb) -> cb.and(cb.equal(
|
||||
root.get(JpaSoftwareModuleMetadata_.softwareModule).get(JpaSoftwareModule_.id),
|
||||
softwareModuleId))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoftwareModuleMetadata findSoftwareModuleMetadata(final SoftwareModule softwareModule, final String key) {
|
||||
return findSoftwareModuleMetadata(new SwMetadataCompositeKey(softwareModule, key));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -29,6 +29,7 @@ import javax.persistence.criteria.Root;
|
||||
|
||||
import org.eclipse.hawkbit.repository.TargetFields;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetTagAssigmentResultEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||
@@ -48,6 +49,7 @@ import org.eclipse.hawkbit.repository.model.TargetIdName;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.data.domain.Page;
|
||||
@@ -94,6 +96,9 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
@Autowired
|
||||
private EventBus eventBus;
|
||||
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
|
||||
@Autowired
|
||||
private AfterTransactionCommitExecutor afterCommit;
|
||||
|
||||
@@ -206,6 +211,8 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
targetInfoRepository.deleteByTargetIdIn(targetsForCurrentTenant);
|
||||
targetRepository.deleteByIdIn(targetsForCurrentTenant);
|
||||
}
|
||||
targetsForCurrentTenant
|
||||
.forEach(targetId -> eventBus.post(new TargetDeletedEvent(tenantAware.getCurrentTenant(), targetId)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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<String, String> 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
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.eventbus;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.eclipse.hawkbit.eventbus.event.TargetDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetInfoUpdateEvent;
|
||||
import org.eclipse.hawkbit.repository.jpa.TargetRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetInfo;
|
||||
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* An aspect implementation which wraps the necessary repository services for
|
||||
* saving {@link TenantAwareBaseEntity}s to publish create or update events.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
@Aspect
|
||||
public class EntityChangeEventListener {
|
||||
|
||||
@Autowired
|
||||
private EventBus eventBus;
|
||||
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
|
||||
@Autowired
|
||||
private EntityManager entityManager;
|
||||
|
||||
@Autowired
|
||||
private AfterTransactionCommitExecutor afterCommit;
|
||||
|
||||
/**
|
||||
* In case the a {@link Target} is created a corresponding
|
||||
* {@link TargetInfo} is created as well. We need the {@link TargetInfo}
|
||||
* information in the target created event. So we are listening to the
|
||||
* {@link TargetInfo} creation to indicate if an Target has been created.
|
||||
*
|
||||
* @param joinpoint
|
||||
* the aspect join point
|
||||
* @return the object of the {@link ProceedingJoinPoint#proceed()}
|
||||
* @throws Throwable
|
||||
* in case exception happens in the
|
||||
* {@link ProceedingJoinPoint#proceed()}
|
||||
*/
|
||||
@Around("execution(* org.eclipse.hawkbit.repository.jpa.TargetInfoRepository.save(..))")
|
||||
// Exception squid:S00112 - Is aspectJ proxy
|
||||
@SuppressWarnings({ "squid:S00112" })
|
||||
public Object targetCreated(final ProceedingJoinPoint joinpoint) throws Throwable {
|
||||
final boolean isNew = isTargetInfoNew(joinpoint.getArgs()[0]);
|
||||
final Object result = joinpoint.proceed();
|
||||
if (result instanceof TargetInfo) {
|
||||
if (isNew) {
|
||||
notifyTargetCreated(entityManager.merge(entityManager.merge(((TargetInfo) result).getTarget())));
|
||||
} else {
|
||||
notifyTargetInfoChanged((TargetInfo) result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy method around the delete method of the {@link TargetRepository} to
|
||||
* notify the {@link TargetDeletedEvent} in case targets has been deleted.
|
||||
*
|
||||
* @param joinpoint
|
||||
* the aspect join point
|
||||
* @return the object of the {@link ProceedingJoinPoint#proceed()}
|
||||
* @throws Throwable
|
||||
* in case exception happens in the
|
||||
* {@link ProceedingJoinPoint#proceed()}
|
||||
*/
|
||||
@Around("execution(* org.eclipse.hawkbit.repository.jpa.TargetRepository.deleteByIdIn(..))")
|
||||
// Exception squid:S00112 - Is aspectJ proxy
|
||||
@SuppressWarnings({ "squid:S00112" })
|
||||
public Object targetDeletedById(final ProceedingJoinPoint joinpoint) throws Throwable {
|
||||
final String currentTenant = tenantAware.getCurrentTenant();
|
||||
final Object result = joinpoint.proceed();
|
||||
final Collection<Long> targetIds = (Collection<Long>) joinpoint.getArgs()[0];
|
||||
targetIds.forEach(targetId -> notifyTargetDeleted(currentTenant, targetId));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy method around the delete method of the {@link TargetRepository} to
|
||||
* notify the {@link TargetDeletedEvent} in case targets has been deleted.
|
||||
*
|
||||
* @param joinpoint
|
||||
* the aspect join point
|
||||
* @return the object of the {@link ProceedingJoinPoint#proceed()}
|
||||
* @throws Throwable
|
||||
* in case exception happens in the
|
||||
* {@link ProceedingJoinPoint#proceed()}
|
||||
*/
|
||||
@Around("execution(* org.eclipse.hawkbit.repository.jpa.TargetRepository.delete(..))")
|
||||
// Exception squid:S00112 - Is aspectJ proxy
|
||||
@SuppressWarnings({ "squid:S00112", "unchecked" })
|
||||
public Object targetDeleted(final ProceedingJoinPoint joinpoint) throws Throwable {
|
||||
final String currentTenant = tenantAware.getCurrentTenant();
|
||||
final Object result = joinpoint.proceed();
|
||||
final Object param = joinpoint.getArgs()[0];
|
||||
// delete by id
|
||||
if (param instanceof Long) {
|
||||
notifyTargetDeleted(currentTenant, (Long) param);
|
||||
} else if (param instanceof Target) {
|
||||
notifyTargetDeleted(currentTenant, ((Target) param).getId());
|
||||
} else if (param instanceof Iterable) {
|
||||
((Iterable<Target>) param).forEach(target -> notifyTargetDeleted(currentTenant, target.getId()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void notifyTargetCreated(final Target t) {
|
||||
afterCommit.afterCommit(() -> eventBus.post(new TargetCreatedEvent(t)));
|
||||
|
||||
}
|
||||
|
||||
private void notifyTargetInfoChanged(final TargetInfo targetInfo) {
|
||||
afterCommit.afterCommit(() -> eventBus.post(new TargetInfoUpdateEvent(targetInfo)));
|
||||
}
|
||||
|
||||
private void notifyTargetDeleted(final String tenant, final Long targetId) {
|
||||
afterCommit.afterCommit(() -> eventBus.post(new TargetDeletedEvent(tenant, targetId)));
|
||||
}
|
||||
|
||||
private static boolean isTargetInfoNew(final Object targetInfo) {
|
||||
return ((JpaTargetInfo) targetInfo).isNew();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -179,4 +179,5 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -8,79 +8,47 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.model;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.ActionCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.ActionPropertyChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.RolloutGroupPropertyChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.RolloutPropertyChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
|
||||
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
|
||||
import org.eclipse.persistence.queries.UpdateObjectQuery;
|
||||
import org.eclipse.persistence.sessions.changesets.DirectToFieldChangeRecord;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* Listens to change in property values of an entity.
|
||||
* Listens to change in property values of an entity and calls the corresponding
|
||||
* {@link EventAwareEntity}.
|
||||
*
|
||||
*/
|
||||
public class EntityPropertyChangeListener extends DescriptorEventAdapter {
|
||||
|
||||
@Override
|
||||
public void postInsert(final DescriptorEvent event) {
|
||||
if (event.getObject().getClass().equals(Action.class)) {
|
||||
final Action action = (Action) event.getObject();
|
||||
if (action.getRollout() != null) {
|
||||
final EventBus eventBus = getEventBus();
|
||||
final AfterTransactionCommitExecutor afterCommit = getAfterTransactionCommmitExecutor();
|
||||
afterCommit.afterCommit(() -> eventBus.post(new ActionCreatedEvent(action)));
|
||||
}
|
||||
final Object object = event.getObject();
|
||||
if (isEventAwareEntity(object)) {
|
||||
doNotifiy(() -> ((EventAwareEntity) object).fireCreateEvent(event));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postUpdate(final DescriptorEvent event) {
|
||||
if (event.getObject().getClass().equals(JpaAction.class)) {
|
||||
getAfterTransactionCommmitExecutor().afterCommit(() -> getEventBus().post(
|
||||
new ActionPropertyChangeEvent((Action) event.getObject(), getChangeSet(Action.class, event))));
|
||||
} else if (event.getObject().getClass().equals(JpaRollout.class)) {
|
||||
getAfterTransactionCommmitExecutor().afterCommit(() -> getEventBus().post(
|
||||
new RolloutPropertyChangeEvent((Rollout) event.getObject(), getChangeSet(Rollout.class, event))));
|
||||
} else if (event.getObject().getClass().equals(JpaRolloutGroup.class)) {
|
||||
getAfterTransactionCommmitExecutor().afterCommit(
|
||||
() -> getEventBus().post(new RolloutGroupPropertyChangeEvent((RolloutGroup) event.getObject(),
|
||||
getChangeSet(RolloutGroup.class, event))));
|
||||
final Object object = event.getObject();
|
||||
if (isEventAwareEntity(object)) {
|
||||
doNotifiy(() -> ((EventAwareEntity) object).fireUpdateEvent(event));
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends TenantAwareBaseEntity> Map<String, AbstractPropertyChangeEvent<T>.Values> getChangeSet(
|
||||
final Class<T> clazz, final DescriptorEvent event) {
|
||||
final T rolloutGroup = clazz.cast(event.getObject());
|
||||
final ObjectChangeSet changeSet = ((UpdateObjectQuery) event.getQuery()).getObjectChangeSet();
|
||||
return changeSet.getChanges().stream().filter(record -> record instanceof DirectToFieldChangeRecord)
|
||||
.map(record -> (DirectToFieldChangeRecord) record)
|
||||
.collect(Collectors.toMap(record -> record.getAttribute(),
|
||||
record -> new AbstractPropertyChangeEvent<T>(rolloutGroup, null).new Values(
|
||||
record.getOldValue(), record.getNewValue())));
|
||||
@Override
|
||||
public void postDelete(final DescriptorEvent event) {
|
||||
final Object object = event.getObject();
|
||||
if (isEventAwareEntity(object)) {
|
||||
doNotifiy(() -> ((EventAwareEntity) object).fireDeleteEvent(event));
|
||||
}
|
||||
}
|
||||
|
||||
private AfterTransactionCommitExecutor getAfterTransactionCommmitExecutor() {
|
||||
return AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit();
|
||||
private static boolean isEventAwareEntity(final Object object) {
|
||||
return object instanceof EventAwareEntity;
|
||||
}
|
||||
|
||||
private EventBus getEventBus() {
|
||||
return EventBusHolder.getInstance().getEventBus();
|
||||
private static void doNotifiy(final Runnable runnable) {
|
||||
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(runnable);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.model;
|
||||
|
||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||
|
||||
/**
|
||||
* Interfaces which can be implemented by entities to be called when the entity
|
||||
* should fire an event because the entity has been created, updated or deleted.
|
||||
*/
|
||||
public interface EventAwareEntity {
|
||||
|
||||
/**
|
||||
* Fired for the Entity creation.
|
||||
*
|
||||
* @param descriptorEvent
|
||||
*/
|
||||
void fireCreateEvent(DescriptorEvent descriptorEvent);
|
||||
|
||||
/**
|
||||
* Fired for the Entity updation.
|
||||
*
|
||||
* @param descriptorEvent
|
||||
*/
|
||||
void fireUpdateEvent(DescriptorEvent descriptorEvent);
|
||||
|
||||
/**
|
||||
* Fired for the Entity deletion.
|
||||
*
|
||||
* @param descriptorEvent
|
||||
*/
|
||||
void fireDeleteEvent(DescriptorEvent descriptorEvent);
|
||||
}
|
||||
@@ -28,6 +28,10 @@ import javax.persistence.NamedSubgraph;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.ActionCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.ActionPropertyChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
@@ -35,6 +39,7 @@ import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||
|
||||
/**
|
||||
* JPA implementation of {@link Action}.
|
||||
@@ -49,7 +54,7 @@ import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||
// sub entities
|
||||
@SuppressWarnings("squid:S2160")
|
||||
public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Action {
|
||||
public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Action, EventAwareEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@@ -171,4 +176,20 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio
|
||||
return "Action [distributionSet=" + distributionSet + ", getId()=" + getId() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new ActionCreatedEvent(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new ActionPropertyChangeEvent(this,
|
||||
EntityPropertyChangeHelper.getChangeSet(Action.class, descriptorEvent)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireDeleteEvent(final DescriptorEvent descriptorEvent) {
|
||||
// there is no action deletion
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -33,8 +34,14 @@ import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent.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;
|
||||
import org.eclipse.hawkbit.repository.exception.DistributionSetTypeUndefinedException;
|
||||
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
@@ -45,6 +52,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetInfo;
|
||||
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||
|
||||
/**
|
||||
* Jpa implementation of {@link DistributionSet}.
|
||||
@@ -61,9 +69,13 @@ import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||
// sub entities
|
||||
@SuppressWarnings("squid:S2160")
|
||||
public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implements DistributionSet {
|
||||
public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implements DistributionSet, EventAwareEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String COMPLETE_PROPERTY = "complete";
|
||||
|
||||
private static final String DELETED_PROPERTY = "deleted";
|
||||
|
||||
@Column(name = "required_migration_step")
|
||||
private boolean requiredMigrationStep;
|
||||
|
||||
@@ -279,4 +291,30 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
return complete;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new DistributionCreatedEvent(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||
|
||||
final Map<String, PropertyChange> changeSet = EntityPropertyChangeHelper.getChangeSet(JpaDistributionSet.class,
|
||||
descriptorEvent);
|
||||
EventBusHolder.getInstance().getEventBus().post(new DistributionSetUpdateEvent(this));
|
||||
|
||||
if (changeSet.containsKey(DELETED_PROPERTY)) {
|
||||
final Boolean newDeleted = (Boolean) changeSet.get(DELETED_PROPERTY).getNewValue();
|
||||
if (newDeleted) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new DistributionDeletedEvent(getTenant(), getId()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireDeleteEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new DistributionDeletedEvent(getTenant(), getId()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,13 +25,17 @@ import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.RolloutPropertyChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.jpa.cache.CacheField;
|
||||
import org.eclipse.hawkbit.repository.jpa.cache.CacheKeys;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||
|
||||
/**
|
||||
* JPA implementation of a {@link Rollout}.
|
||||
@@ -44,7 +48,7 @@ import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||
// sub entities
|
||||
@SuppressWarnings("squid:S2160")
|
||||
public class JpaRollout extends AbstractJpaNamedEntity implements Rollout {
|
||||
public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, EventAwareEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@@ -197,4 +201,21 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout {
|
||||
+ ", getName()=" + getName() + ", getId()=" + getId() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||
// there is no rollout creation event
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new RolloutPropertyChangeEvent(this,
|
||||
EntityPropertyChangeHelper.getChangeSet(Rollout.class, descriptorEvent)));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireDeleteEvent(final DescriptorEvent descriptorEvent) {
|
||||
// there is no rollout deletion event
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,9 +25,13 @@ import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.RolloutGroupPropertyChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||
|
||||
/**
|
||||
* JPA entity definition of persisting a group of an rollout.
|
||||
@@ -40,7 +44,7 @@ import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||
// sub entities
|
||||
@SuppressWarnings("squid:S2160")
|
||||
public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGroup {
|
||||
public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGroup, EventAwareEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@@ -236,4 +240,19 @@ public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGr
|
||||
+ ", getId()=" + getId() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||
// there is no RolloutGroup created event
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new RolloutGroupPropertyChangeEvent(this,
|
||||
EntityPropertyChangeHelper.getChangeSet(RolloutGroup.class, descriptorEvent)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireDeleteEvent(final DescriptorEvent descriptorEvent) {
|
||||
// there is no RolloutGroup deleted event
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,10 @@ import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityChecker;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
|
||||
@@ -45,6 +49,7 @@ import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetInfo;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||
import org.springframework.data.domain.Persistable;
|
||||
|
||||
/**
|
||||
@@ -64,7 +69,8 @@ import org.springframework.data.domain.Persistable;
|
||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||
// sub entities
|
||||
@SuppressWarnings("squid:S2160")
|
||||
public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Long>, Target {
|
||||
public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Long>, Target, EventAwareEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Column(name = "controller_id", length = 64)
|
||||
@@ -180,7 +186,7 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Lon
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isNew
|
||||
* @param entityNew
|
||||
* the isNew to set
|
||||
*/
|
||||
public void setNew(final boolean entityNew) {
|
||||
@@ -222,6 +228,7 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Lon
|
||||
* @param securityToken
|
||||
* the securityToken to set
|
||||
*/
|
||||
@Override
|
||||
public void setSecurityToken(final String securityToken) {
|
||||
this.securityToken = securityToken;
|
||||
}
|
||||
@@ -231,4 +238,18 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Lon
|
||||
return "Target [controllerId=" + controllerId + ", getId()=" + getId() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new TargetCreatedEvent(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new TargetUpdatedEvent(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireDeleteEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new TargetDeletedEvent(getTenant(), getId()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import javax.persistence.Column;
|
||||
import javax.persistence.ConstraintMode;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EntityListeners;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.FetchType;
|
||||
@@ -37,7 +38,9 @@ import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetInfoUpdateEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
@@ -48,6 +51,7 @@ import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
||||
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.domain.Persistable;
|
||||
@@ -64,7 +68,8 @@ import org.springframework.data.domain.Persistable;
|
||||
@Table(name = "sp_target_info", indexes = {
|
||||
@Index(name = "sp_idx_target_info_02", columnList = "target_id,update_status") })
|
||||
@Entity
|
||||
public class JpaTargetInfo implements Persistable<Long>, TargetInfo {
|
||||
@EntityListeners(EntityPropertyChangeListener.class)
|
||||
public class JpaTargetInfo implements Persistable<Long>, TargetInfo, EventAwareEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TargetInfo.class);
|
||||
@@ -117,7 +122,7 @@ public class JpaTargetInfo implements Persistable<Long>, TargetInfo {
|
||||
private boolean requestControllerAttributes = true;
|
||||
|
||||
/**
|
||||
* Constructor for {@link TargetStatus}.
|
||||
* Constructor for {@link JpaTargetInfo}.
|
||||
*
|
||||
* @param target
|
||||
* related to this status.
|
||||
@@ -144,7 +149,7 @@ public class JpaTargetInfo implements Persistable<Long>, TargetInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isNew
|
||||
* @param entityNew
|
||||
* the isNew to set
|
||||
*/
|
||||
public void setNew(final boolean entityNew) {
|
||||
@@ -321,4 +326,19 @@ public class JpaTargetInfo implements Persistable<Long>, TargetInfo {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||
// there is no target info created event
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventBusHolder.getInstance().getEventBus().post(new TargetInfoUpdateEvent(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireDeleteEvent(final DescriptorEvent descriptorEvent) {
|
||||
// there is no target info deleted event
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.model.helper;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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;
|
||||
import org.eclipse.persistence.queries.UpdateObjectQuery;
|
||||
import org.eclipse.persistence.sessions.changesets.DirectToFieldChangeRecord;
|
||||
|
||||
/**
|
||||
* Helper class to get the change set for the property changes in the Entity.
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public class EntityPropertyChangeHelper<T extends TenantAwareBaseEntity> {
|
||||
|
||||
/**
|
||||
* To get the map of entity property change set
|
||||
*
|
||||
* @param clazz
|
||||
* @param event
|
||||
* @return the map of the changeSet
|
||||
*/
|
||||
public static <T extends TenantAwareBaseEntity> Map<String, PropertyChange> 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 PropertyChange(record.getOldValue(), record.getNewValue())));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
*
|
||||
*
|
||||
* <ul>
|
||||
* <li>Equal to : ==</li>
|
||||
* <li>Not equal to : !=</li>
|
||||
@@ -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 <A>
|
||||
@@ -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) {
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.eventbus;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.event.Event;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetInfoUpdateEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.fest.assertions.api.Assertions;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("Entity Events")
|
||||
public class RepositoryEntityEventTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private EventBus eventBus;
|
||||
|
||||
private final MyEventListener eventListener = new MyEventListener();
|
||||
|
||||
@Before
|
||||
public void beforeTest() {
|
||||
eventListener.queue.clear();
|
||||
eventBus.register(eventListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that the target created event is published when a target has been created")
|
||||
public void targetCreatedEventIsPublished() throws InterruptedException {
|
||||
final Target createdTarget = targetManagement.createTarget(entityFactory.generateTarget("12345"));
|
||||
|
||||
final TargetCreatedEvent targetCreatedEvent = eventListener.waitForEvent(TargetCreatedEvent.class, 1,
|
||||
TimeUnit.SECONDS);
|
||||
assertThat(targetCreatedEvent).isNotNull();
|
||||
assertThat(targetCreatedEvent.getEntity().getId()).isEqualTo(createdTarget.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that the target update event is published when a target has been updated")
|
||||
public void targetUpdateEventIsPublished() throws InterruptedException {
|
||||
final Target createdTarget = targetManagement.createTarget(entityFactory.generateTarget("12345"));
|
||||
createdTarget.setName("updateName");
|
||||
targetManagement.updateTarget(createdTarget);
|
||||
|
||||
final TargetUpdatedEvent targetUpdatedEvent = eventListener.waitForEvent(TargetUpdatedEvent.class, 1,
|
||||
TimeUnit.SECONDS);
|
||||
assertThat(targetUpdatedEvent).isNotNull();
|
||||
assertThat(targetUpdatedEvent.getEntity().getId()).isEqualTo(createdTarget.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that the target info update event is published when a target info has been updated")
|
||||
public void targetInfoUpdateEventIsPublished() throws InterruptedException {
|
||||
final Target createdTarget = targetManagement.createTarget(entityFactory.generateTarget("12345"));
|
||||
controllerManagament.updateTargetStatus(createdTarget.getTargetInfo(), TargetUpdateStatus.PENDING,
|
||||
System.currentTimeMillis(), URI.create("http://127.0.0.1"));
|
||||
|
||||
final TargetInfoUpdateEvent targetInfoUpdatedEvent = eventListener.waitForEvent(TargetInfoUpdateEvent.class, 1,
|
||||
TimeUnit.SECONDS);
|
||||
assertThat(targetInfoUpdatedEvent).isNotNull();
|
||||
assertThat(targetInfoUpdatedEvent.getEntity().getTarget().getId()).isEqualTo(createdTarget.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that the target deleted event is published when a target has been deleted")
|
||||
public void targetDeletedEventIsPublished() throws InterruptedException {
|
||||
final Target createdTarget = targetManagement.createTarget(entityFactory.generateTarget("12345"));
|
||||
|
||||
targetManagement.deleteTargets(createdTarget.getId());
|
||||
|
||||
final TargetDeletedEvent targetDeletedEvent = eventListener.waitForEvent(TargetDeletedEvent.class, 1,
|
||||
TimeUnit.SECONDS);
|
||||
assertThat(targetDeletedEvent).isNotNull();
|
||||
assertThat(targetDeletedEvent.getTargetId()).isEqualTo(createdTarget.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that the distribution set created event is published when a distribution set has been created")
|
||||
public void distributionSetCreatedEventIsPublished() throws InterruptedException {
|
||||
final DistributionSet generateDistributionSet = entityFactory.generateDistributionSet();
|
||||
generateDistributionSet.setName("dsEventTest");
|
||||
generateDistributionSet.setVersion("1");
|
||||
final DistributionSet createDistributionSet = distributionSetManagement
|
||||
.createDistributionSet(generateDistributionSet);
|
||||
|
||||
final DistributionCreatedEvent dsCreatedEvent = eventListener.waitForEvent(DistributionCreatedEvent.class, 1,
|
||||
TimeUnit.SECONDS);
|
||||
assertThat(dsCreatedEvent).isNotNull();
|
||||
assertThat(dsCreatedEvent.getEntity().getId()).isEqualTo(createDistributionSet.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that the distribution set deleted event is published when a distribution set has been deleted")
|
||||
public void distributionSetDeletedEventIsPublished() throws InterruptedException {
|
||||
|
||||
final DistributionSet generateDistributionSet = entityFactory.generateDistributionSet();
|
||||
generateDistributionSet.setName("dsEventTest");
|
||||
generateDistributionSet.setVersion("1");
|
||||
final DistributionSet createDistributionSet = distributionSetManagement
|
||||
.createDistributionSet(generateDistributionSet);
|
||||
|
||||
distributionSetManagement.deleteDistributionSet(createDistributionSet);
|
||||
|
||||
final DistributionDeletedEvent dsDeletedEvent = eventListener.waitForEvent(DistributionDeletedEvent.class, 1,
|
||||
TimeUnit.SECONDS);
|
||||
assertThat(dsDeletedEvent).isNotNull();
|
||||
assertThat(dsDeletedEvent.getDistributionSetId()).isEqualTo(createDistributionSet.getId());
|
||||
}
|
||||
|
||||
private class MyEventListener {
|
||||
|
||||
private final BlockingQueue<Event> queue = new LinkedBlockingQueue<>();
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(final Event event) {
|
||||
queue.offer(event);
|
||||
}
|
||||
|
||||
public <T> T waitForEvent(final Class<T> eventType, final long timeout, final TimeUnit timeUnit)
|
||||
throws InterruptedException {
|
||||
Event event = null;
|
||||
while ((event = queue.poll(timeout, timeUnit)) != null) {
|
||||
if (event.getClass().isAssignableFrom(eventType)) {
|
||||
return (T) event;
|
||||
}
|
||||
}
|
||||
Assertions.fail("Missing event " + eventType + " within timeout " + timeout + " " + timeUnit);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 <a href="https://tools.ietf.org/html/rfc7233">https://tools.ietf.org
|
||||
* /html/rfc7233</a>
|
||||
*/
|
||||
public static ResponseEntity<InputStream> 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<ByteRange> 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<InputStream> extractRange(final HttpServletResponse response, final long length,
|
||||
final List<ByteRange> ranges, final String range) {
|
||||
ResponseEntity<InputStream> 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<ByteRange> 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<ByteRange> 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<ByteRange> 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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 <code>true</code> 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 <code>null</code>.
|
||||
*
|
||||
*
|
||||
* @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 <code>null</code>.
|
||||
*
|
||||
*
|
||||
* @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 <code>true</code> if IP address is actually known by the server
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,25 +12,29 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.event.Event;
|
||||
import org.eclipse.hawkbit.eventbus.event.TargetDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetTagCreatedBulkEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetTagDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetTagUpdateEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetUpdateEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.RolloutChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.RolloutGroupChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetInfoUpdateEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetTagCreatedBulkEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetTagDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetTagUpdateEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetUpdatedEvent;
|
||||
|
||||
/**
|
||||
* The default hawkbit event provider.
|
||||
*/
|
||||
public class HawkbitEventProvider implements UIEventProvider {
|
||||
|
||||
private static final Set<Class<? extends Event>> SINGLE_EVENTS = new HashSet<>(6);
|
||||
private static final Set<Class<? extends Event>> BULK_EVENTS = new HashSet<>(3);
|
||||
private static final Set<Class<? extends Event>> SINGLE_EVENTS = new HashSet<>(9);
|
||||
private static final Set<Class<? extends Event>> BULK_EVENTS = new HashSet<>(5);
|
||||
|
||||
static {
|
||||
SINGLE_EVENTS.add(TargetTagCreatedBulkEvent.class);
|
||||
@@ -41,10 +45,14 @@ public class HawkbitEventProvider implements UIEventProvider {
|
||||
SINGLE_EVENTS.add(RolloutGroupChangeEvent.class);
|
||||
SINGLE_EVENTS.add(RolloutChangeEvent.class);
|
||||
SINGLE_EVENTS.add(TargetTagUpdateEvent.class);
|
||||
SINGLE_EVENTS.add(DistributionSetUpdateEvent.class);
|
||||
|
||||
BULK_EVENTS.add(TargetCreatedEvent.class);
|
||||
BULK_EVENTS.add(TargetInfoUpdateEvent.class);
|
||||
BULK_EVENTS.add(TargetDeletedEvent.class);
|
||||
BULK_EVENTS.add(DistributionDeletedEvent.class);
|
||||
BULK_EVENTS.add(DistributionCreatedEvent.class);
|
||||
BULK_EVENTS.add(TargetUpdatedEvent.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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<LocalArtifact> {
|
||||
|
||||
/**
|
||||
* Parametric Constructor.
|
||||
*
|
||||
*
|
||||
* @param definition
|
||||
* as Def
|
||||
* @param queryConfig
|
||||
@@ -51,18 +55,18 @@ public class ArtifactBeanQuery extends AbstractBeanQuery<LocalArtifact> {
|
||||
*/
|
||||
public ArtifactBeanQuery(final QueryDefinition definition, final Map<String, Object> 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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.artifacts.event;
|
||||
|
||||
/**
|
||||
*
|
||||
* Holds the upload file status.
|
||||
@@ -14,24 +15,36 @@ package org.eclipse.hawkbit.ui.artifacts.event;
|
||||
*/
|
||||
public class UploadStatusEvent {
|
||||
|
||||
/**
|
||||
* Event type definition of events during the artifact upload life-cycle
|
||||
* from receiving the upload until the process end.
|
||||
*/
|
||||
public enum UploadStatusEventType {
|
||||
UPLOAD_FAILED, UPLOAD_IN_PROGRESS, UPLOAD_STARTED, UPLOAD_FINISHED, UPLOAD_SUCCESSFUL, UPLOAD_STREAMING_FAILED, UPLOAD_STREAMING_FINISHED, ABORT_UPLOAD
|
||||
RECEIVE_UPLOAD, UPLOAD_FAILED, UPLOAD_IN_PROGRESS, UPLOAD_STARTED, UPLOAD_FINISHED, UPLOAD_SUCCESSFUL, UPLOAD_STREAMING_FAILED, UPLOAD_STREAMING_FINISHED, ABORT_UPLOAD
|
||||
}
|
||||
|
||||
private UploadStatusEventType uploadProgressEventType;
|
||||
private final UploadStatusEventType uploadProgressEventType;
|
||||
|
||||
private UploadFileStatus uploadStatus;
|
||||
|
||||
public UploadStatusEvent(UploadStatusEventType eventType, UploadFileStatus entity) {
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param eventType
|
||||
* the type of the event
|
||||
* @param uploadStatus
|
||||
* the upload status of this event
|
||||
*/
|
||||
public UploadStatusEvent(final UploadStatusEventType eventType, final UploadFileStatus uploadStatus) {
|
||||
this.uploadProgressEventType = eventType;
|
||||
this.uploadStatus = entity;
|
||||
this.uploadStatus = uploadStatus;
|
||||
}
|
||||
|
||||
public UploadFileStatus getUploadStatus() {
|
||||
return uploadStatus;
|
||||
}
|
||||
|
||||
public void setUploadStatus(UploadFileStatus uploadStatus) {
|
||||
public void setUploadStatus(final UploadFileStatus uploadStatus) {
|
||||
this.uploadStatus = uploadStatus;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ public class BaseSwModuleBeanQuery extends AbstractBeanQuery<ProxyBaseSoftwareMo
|
||||
|
||||
/**
|
||||
* Parametric Constructor.
|
||||
*
|
||||
*
|
||||
* @param definition
|
||||
* as Def
|
||||
* @param queryConfig
|
||||
@@ -56,7 +56,7 @@ public class BaseSwModuleBeanQuery extends AbstractBeanQuery<ProxyBaseSoftwareMo
|
||||
public BaseSwModuleBeanQuery(final QueryDefinition definition, final Map<String, Object> 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)) {
|
||||
|
||||
@@ -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>(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);
|
||||
|
||||
@@ -51,8 +51,8 @@ import com.vaadin.ui.UI;
|
||||
/**
|
||||
* Header of Software module table.
|
||||
*/
|
||||
@SpringComponent
|
||||
@ViewScope
|
||||
@SpringComponent
|
||||
public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModule, Long> {
|
||||
|
||||
private static final long serialVersionUID = 6469417305487144809L;
|
||||
@@ -161,7 +161,7 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
void onEvent(final UploadArtifactUIEvent event) {
|
||||
if (event == UploadArtifactUIEvent.DELETED_ALL_SOFWARE) {
|
||||
UI.getCurrent().access(() -> refreshFilter());
|
||||
UI.getCurrent().access(this::refreshFilter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
|
||||
public Object generateCell(final Table source, final Object itemId, final Object columnId) {
|
||||
final String nameVersionStr = getNameAndVerion(itemId);
|
||||
final Button manageMetaDataBtn = createManageMetadataButton(nameVersionStr);
|
||||
manageMetaDataBtn.addClickListener(event -> showMetadataDetails((Long) itemId, nameVersionStr));
|
||||
manageMetaDataBtn.addClickListener(event -> showMetadataDetails((Long) itemId));
|
||||
return manageMetaDataBtn;
|
||||
}
|
||||
});
|
||||
@@ -244,7 +244,7 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
|
||||
return name + "." + version;
|
||||
}
|
||||
|
||||
private void showMetadataDetails(final Long itemId, final String nameVersionStr) {
|
||||
private void showMetadataDetails(final Long itemId) {
|
||||
final SoftwareModule swmodule = softwareManagement.findSoftwareModuleWithDetails(itemId);
|
||||
/* display the window */
|
||||
UI.getCurrent().addWindow(swMetadataPopupLayout.getWindow(swmodule, null));
|
||||
|
||||
@@ -18,7 +18,9 @@ import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent;
|
||||
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent.SoftwareModuleTypeEnum;
|
||||
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
|
||||
import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery;
|
||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
||||
import org.eclipse.hawkbit.ui.common.builder.TextAreaBuilder;
|
||||
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
|
||||
import org.eclipse.hawkbit.ui.layouts.CreateUpdateTypeLayout;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
@@ -35,6 +37,7 @@ import com.vaadin.spring.annotation.ViewScope;
|
||||
import com.vaadin.ui.Button.ClickEvent;
|
||||
import com.vaadin.ui.Label;
|
||||
import com.vaadin.ui.OptionGroup;
|
||||
import com.vaadin.ui.TextField;
|
||||
import com.vaadin.ui.components.colorpicker.ColorChangeListener;
|
||||
import com.vaadin.ui.themes.ValoTheme;
|
||||
|
||||
@@ -74,29 +77,28 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout {
|
||||
|
||||
singleAssignStr = i18n.get("label.singleAssign.type");
|
||||
multiAssignStr = i18n.get("label.multiAssign.type");
|
||||
singleAssign = SPUIComponentProvider.getLabel(singleAssignStr, null);
|
||||
multiAssign = SPUIComponentProvider.getLabel(multiAssignStr, null);
|
||||
singleAssign = new LabelBuilder().name(singleAssignStr).buildLabel();
|
||||
|
||||
tagName = SPUIComponentProvider.getTextField(i18n.get("textfield.name"), "",
|
||||
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_NAME, true, "", i18n.get("textfield.name"), true,
|
||||
SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
||||
tagName.setId(SPUIDefinitions.NEW_SOFTWARE_TYPE_NAME);
|
||||
multiAssign = new LabelBuilder().name(multiAssignStr).buildLabel();
|
||||
|
||||
typeKey = SPUIComponentProvider.getTextField(i18n.get("textfield.key"), "",
|
||||
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_KEY, true, "", i18n.get("textfield.key"), true,
|
||||
SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
||||
typeKey.setId(SPUIDefinitions.NEW_SOFTWARE_TYPE_KEY);
|
||||
tagName = createTextField("textfield.name", SPUIDefinitions.TYPE_NAME, SPUIDefinitions.NEW_SOFTWARE_TYPE_NAME);
|
||||
|
||||
tagDesc = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "",
|
||||
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_DESC, false, "",
|
||||
i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
|
||||
tagDesc.setId(SPUIDefinitions.NEW_SOFTWARE_TYPE_DESC);
|
||||
tagDesc.setImmediate(true);
|
||||
typeKey = createTextField("textfield.key", SPUIDefinitions.TYPE_KEY, SPUIDefinitions.NEW_SOFTWARE_TYPE_KEY);
|
||||
|
||||
tagDesc = new TextAreaBuilder().caption(i18n.get("textfield.description"))
|
||||
.styleName(ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_DESC)
|
||||
.prompt(i18n.get("textfield.description")).immediate(true).id(SPUIDefinitions.NEW_SOFTWARE_TYPE_DESC)
|
||||
.buildTextComponent();
|
||||
tagDesc.setNullRepresentation("");
|
||||
|
||||
singleMultiOptionGroup();
|
||||
}
|
||||
|
||||
private TextField createTextField(final String in18Key, final String styleName, final String id) {
|
||||
return new TextFieldBuilder().caption(i18n.get(in18Key)).styleName(ValoTheme.TEXTFIELD_TINY + " " + styleName)
|
||||
.required(true).prompt(i18n.get(in18Key)).immediate(true).id(id).buildTextComponent();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildLayout() {
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.artifacts.upload;
|
||||
|
||||
import static org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions.FAILED;
|
||||
import static org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions.SUCCESS;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
@@ -23,6 +26,7 @@ import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
|
||||
import org.eclipse.hawkbit.ui.artifacts.state.CustomFile;
|
||||
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
|
||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleTiny;
|
||||
@@ -56,13 +60,13 @@ import com.vaadin.ui.themes.ValoTheme;
|
||||
|
||||
/**
|
||||
* Artifact upload confirmation popup.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class UploadConfirmationwindow implements Button.ClickListener {
|
||||
public class UploadConfirmationWindow implements Button.ClickListener {
|
||||
|
||||
private static final long serialVersionUID = -1679035890140031740L;
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(UploadConfirmationwindow.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(UploadConfirmationWindow.class);
|
||||
|
||||
private static final String MD5_CHECKSUM = "md5Checksum";
|
||||
|
||||
@@ -114,13 +118,13 @@ public class UploadConfirmationwindow implements Button.ClickListener {
|
||||
|
||||
/**
|
||||
* Initialize the upload confirmation window.
|
||||
*
|
||||
*
|
||||
* @param artifactUploadView
|
||||
* reference of upload layout.
|
||||
* @param artifactUploadState
|
||||
* reference of session variable {@link ArtifactUploadState}.
|
||||
*/
|
||||
public UploadConfirmationwindow(final UploadLayout artifactUploadView,
|
||||
public UploadConfirmationWindow(final UploadLayout artifactUploadView,
|
||||
final ArtifactUploadState artifactUploadState) {
|
||||
this.uploadLayout = artifactUploadView;
|
||||
this.artifactUploadState = artifactUploadState;
|
||||
@@ -245,29 +249,27 @@ public class UploadConfirmationwindow implements Button.ClickListener {
|
||||
deleteIcon.setData(itemId);
|
||||
newItem.getItemProperty(ACTION).setValue(deleteIcon);
|
||||
|
||||
final TextField sha1 = SPUIComponentProvider.getTextField(null, "", ValoTheme.TEXTFIELD_TINY, false, null,
|
||||
null, true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
||||
sha1.setId(swNameVersion + "/" + customFile.getFileName() + "/sha1");
|
||||
final TextField sha1 = createTextField(swNameVersion + "/" + customFile.getFileName() + "/sha1");
|
||||
|
||||
final TextField md5 = SPUIComponentProvider.getTextField(null, "", ValoTheme.TEXTFIELD_TINY, false, null,
|
||||
null, true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
||||
md5.setId(swNameVersion + "/" + customFile.getFileName() + "/md5");
|
||||
final TextField md5 = createTextField(swNameVersion + "/" + customFile.getFileName() + "/md5");
|
||||
|
||||
createTextField(swNameVersion + "/" + customFile.getFileName() + "/customFileName");
|
||||
|
||||
final TextField customFileName = SPUIComponentProvider.getTextField(null, "", ValoTheme.TEXTFIELD_TINY,
|
||||
false, null, null, true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
||||
customFileName.setId(swNameVersion + "/" + customFile.getFileName() + "/customFileName");
|
||||
newItem.getItemProperty(SHA1_CHECKSUM).setValue(sha1);
|
||||
newItem.getItemProperty(MD5_CHECKSUM).setValue(md5);
|
||||
newItem.getItemProperty(CUSTOM_FILE).setValue(customFile);
|
||||
}
|
||||
}
|
||||
|
||||
private static TextField createTextField(final String id) {
|
||||
return new TextFieldBuilder().immediate(true).id(id).buildTextComponent();
|
||||
}
|
||||
|
||||
private void addFileNameLayout(final Item newItem, final String baseSoftwareModuleNameVersion,
|
||||
final String customFileName, final String itemId) {
|
||||
final HorizontalLayout horizontalLayout = new HorizontalLayout();
|
||||
final TextField fileNameTextField = SPUIComponentProvider.getTextField(null, "", ValoTheme.TEXTFIELD_TINY,
|
||||
false, null, null, true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
||||
fileNameTextField.setId(baseSoftwareModuleNameVersion + "/" + customFileName + "/customFileName");
|
||||
final TextField fileNameTextField = createTextField(
|
||||
baseSoftwareModuleNameVersion + "/" + customFileName + "/customFileName");
|
||||
fileNameTextField.setData(baseSoftwareModuleNameVersion + "/" + customFileName);
|
||||
fileNameTextField.setValue(customFileName);
|
||||
|
||||
@@ -615,6 +617,7 @@ public class UploadConfirmationwindow implements Button.ClickListener {
|
||||
|
||||
private void createLocalArtifact(final String itemId, final String filePath,
|
||||
final ArtifactManagement artifactManagement, final SoftwareModule baseSw) {
|
||||
|
||||
final File newFile = new File(filePath);
|
||||
final Item item = tabelContainer.getItem(itemId);
|
||||
final String sha1Checksum = ((TextField) item.getItemProperty(SHA1_CHECKSUM).getValue()).getValue();
|
||||
@@ -624,27 +627,25 @@ public class UploadConfirmationwindow implements Button.ClickListener {
|
||||
final String[] itemDet = itemId.split("/");
|
||||
final String swModuleNameVersion = itemDet[0];
|
||||
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
fis = new FileInputStream(newFile);
|
||||
try (FileInputStream fis = new FileInputStream(newFile)) {
|
||||
|
||||
artifactManagement.createLocalArtifact(fis, baseSw.getId(), providedFileName,
|
||||
HawkbitCommonUtil.trimAndNullIfEmpty(md5Checksum),
|
||||
HawkbitCommonUtil.trimAndNullIfEmpty(sha1Checksum), true, customFile.getMimeType());
|
||||
saveUploadStatus(providedFileName, swModuleNameVersion, SPUILabelDefinitions.SUCCESS, "");
|
||||
} catch (final FileNotFoundException e) {
|
||||
saveUploadStatus(providedFileName, swModuleNameVersion, SPUILabelDefinitions.FAILED, e.getMessage());
|
||||
LOG.error(ARTIFACT_UPLOAD_EXCEPTION, e);
|
||||
} catch (final ArtifactUploadFailedException e) {
|
||||
saveUploadStatus(providedFileName, swModuleNameVersion, SPUILabelDefinitions.FAILED, e.getMessage());
|
||||
LOG.error(ARTIFACT_UPLOAD_EXCEPTION, e);
|
||||
} catch (final InvalidSHA1HashException e) {
|
||||
saveUploadStatus(providedFileName, swModuleNameVersion, SPUILabelDefinitions.FAILED, e.getMessage());
|
||||
LOG.error(ARTIFACT_UPLOAD_EXCEPTION, e);
|
||||
} catch (final InvalidMD5HashException e) {
|
||||
saveUploadStatus(providedFileName, swModuleNameVersion, SPUILabelDefinitions.FAILED, e.getMessage());
|
||||
saveUploadStatus(providedFileName, swModuleNameVersion, SUCCESS, "");
|
||||
|
||||
} catch (final ArtifactUploadFailedException | InvalidSHA1HashException | InvalidMD5HashException
|
||||
| FileNotFoundException e) {
|
||||
|
||||
saveUploadStatus(providedFileName, swModuleNameVersion, FAILED, e.getMessage());
|
||||
LOG.error(ARTIFACT_UPLOAD_EXCEPTION, e);
|
||||
|
||||
} catch (final IOException ex) {
|
||||
LOG.error(ARTIFACT_UPLOAD_EXCEPTION, ex);
|
||||
} finally {
|
||||
closeFileStream(fis, newFile);
|
||||
if (newFile.exists() && !newFile.delete()) {
|
||||
LOG.error("Could not delete temporary file: {}", newFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,21 +660,6 @@ public class UploadConfirmationwindow implements Button.ClickListener {
|
||||
|
||||
}
|
||||
|
||||
private static void closeFileStream(final FileInputStream fis, final File newFile) {
|
||||
|
||||
if (fis != null) {
|
||||
try {
|
||||
fis.close();
|
||||
} catch (final IOException e) {
|
||||
LOG.error(ARTIFACT_UPLOAD_EXCEPTION, e);
|
||||
}
|
||||
}
|
||||
if (newFile.exists() && !newFile.delete()) {
|
||||
LOG.error("Could not delete temporary file: {}", newFile);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Table getUploadDetailsTable() {
|
||||
return uploadDetailsTable;
|
||||
}
|
||||
@@ -71,10 +71,10 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
||||
private transient EventBus.SessionEventBus eventBus;
|
||||
private final SoftwareModule selectedSw;
|
||||
private SoftwareModule selectedSwForUpload;
|
||||
private ArtifactUploadState artifactUploadState;
|
||||
private final ArtifactUploadState artifactUploadState;
|
||||
|
||||
UploadHandler(final String fileName, final long fileSize, final UploadLayout view, final long maxSize,
|
||||
final Upload upload, final String mimeType, SoftwareModule selectedSw) {
|
||||
final Upload upload, final String mimeType, final SoftwareModule selectedSw) {
|
||||
super();
|
||||
this.aborted = false;
|
||||
this.fileName = fileName;
|
||||
@@ -142,7 +142,11 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
||||
try {
|
||||
if (view.checkIfSoftwareModuleIsSelected() && !view.checkForDuplicate(fileName, selectedSwForUpload)) {
|
||||
view.increaseNumberOfFileUploadsExpected();
|
||||
return view.saveUploadedFileDetails(fileName, 0, mimeType, selectedSwForUpload);
|
||||
final OutputStream saveUploadedFileDetails = view.saveUploadedFileDetails(fileName, 0, mimeType,
|
||||
selectedSwForUpload);
|
||||
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.RECEIVE_UPLOAD,
|
||||
new UploadFileStatus(fileName, 0, -1, selectedSwForUpload)));
|
||||
return saveUploadedFileDetails;
|
||||
}
|
||||
} catch (final ArtifactUploadFailedException e) {
|
||||
LOG.error("Atifact upload failed {} ", e);
|
||||
@@ -163,8 +167,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
||||
@Override
|
||||
public void uploadSucceeded(final SucceededEvent event) {
|
||||
LOG.debug("Streaming finished for file :{}", event.getFilename());
|
||||
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_SUCCESSFUL, new UploadFileStatus(
|
||||
event.getFilename(), 0, event.getLength(), selectedSwForUpload)));
|
||||
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_SUCCESSFUL,
|
||||
new UploadFileStatus(event.getFilename(), 0, event.getLength(), selectedSwForUpload)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,8 +194,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
||||
@Override
|
||||
public void uploadFinished(final FinishedEvent event) {
|
||||
LOG.debug("Upload finished for file :{}", event.getFilename());
|
||||
eventBus.publish(this,
|
||||
new UploadStatusEvent(UploadStatusEventType.UPLOAD_FINISHED, new UploadFileStatus(event.getFilename())));
|
||||
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_FINISHED,
|
||||
new UploadFileStatus(event.getFilename())));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,8 +206,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
||||
@Override
|
||||
public void streamingStarted(final StreamingStartEvent event) {
|
||||
LOG.debug("Streaming started for file :{}", fileName);
|
||||
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_STARTED, new UploadFileStatus(
|
||||
fileName, 0, 0, selectedSw)));
|
||||
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_STARTED,
|
||||
new UploadFileStatus(fileName, 0, 0, selectedSw)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,8 +218,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
||||
@Override
|
||||
public void uploadStarted(final StartedEvent event) {
|
||||
uploadInterrupted = false;
|
||||
selectedSwForUpload = artifactUploadState.getSelectedBaseSoftwareModule().isPresent() ? artifactUploadState
|
||||
.getSelectedBaseSoftwareModule().get() : null;
|
||||
selectedSwForUpload = artifactUploadState.getSelectedBaseSoftwareModule().isPresent()
|
||||
? artifactUploadState.getSelectedBaseSoftwareModule().get() : null;
|
||||
|
||||
if (view.isSoftwareModuleSelected()) {
|
||||
// single file session
|
||||
@@ -223,9 +227,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
||||
LOG.debug("Upload started for file :{}", event.getFilename());
|
||||
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_STARTED,
|
||||
new UploadFileStatus(event.getFilename(), 0, 0, selectedSwForUpload)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
}
|
||||
} else {
|
||||
failureReason = i18n.get("message.upload.failed");
|
||||
upload.interruptUpload();
|
||||
// actual interrupt will happen a bit late so setting the below
|
||||
@@ -291,8 +294,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
||||
interruptFileStreaming();
|
||||
return;
|
||||
}
|
||||
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_IN_PROGRESS, new UploadFileStatus(
|
||||
fileName, event.getBytesReceived(), event.getContentLength(), selectedSw)));
|
||||
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_IN_PROGRESS,
|
||||
new UploadFileStatus(fileName, event.getBytesReceived(), event.getContentLength(), selectedSw)));
|
||||
// Logging to solve sonar issue
|
||||
LOG.trace("Streaming in progress for file :{}", event.getFileName());
|
||||
}
|
||||
@@ -332,8 +335,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
||||
if (failureReason == null) {
|
||||
failureReason = event.getReason().getMessage();
|
||||
}
|
||||
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_FAILED, new UploadFileStatus(
|
||||
fileName, failureReason, selectedSwForUpload)));
|
||||
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_FAILED,
|
||||
new UploadFileStatus(fileName, failureReason, selectedSwForUpload)));
|
||||
if (!aborted) {
|
||||
LOG.info("Upload failed for file :{}", event.getFilename());
|
||||
LOG.info("Upload failed for file :{}", event.getReason());
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
|
||||
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent.SoftwareModuleEventType;
|
||||
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
|
||||
import org.eclipse.hawkbit.ui.artifacts.event.UploadFileStatus;
|
||||
import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent;
|
||||
import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent.UploadStatusEventType;
|
||||
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
|
||||
@@ -109,7 +110,7 @@ public class UploadLayout extends VerticalLayout {
|
||||
|
||||
private Button discardBtn;
|
||||
|
||||
private UploadConfirmationwindow currentUploadConfirmationwindow;
|
||||
private UploadConfirmationWindow currentUploadConfirmationwindow;
|
||||
|
||||
private VerticalLayout dropAreaLayout;
|
||||
|
||||
@@ -273,6 +274,10 @@ public class UploadLayout extends VerticalLayout {
|
||||
private void processFile(final Html5File file, final SoftwareModule selectedSw) {
|
||||
if (!isDirectory(file)) {
|
||||
if (!checkForDuplicate(file.getFileName(), selectedSw)) {
|
||||
|
||||
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.RECEIVE_UPLOAD,
|
||||
new UploadFileStatus(file.getFileName(), 0, -1, selectedSw)));
|
||||
|
||||
artifactUploadState.getNumberOfFileUploadsExpected().incrementAndGet();
|
||||
file.setStreamVariable(createStreamVariable(file, selectedSw));
|
||||
}
|
||||
@@ -634,7 +639,7 @@ public class UploadLayout extends VerticalLayout {
|
||||
if (artifactUploadState.getFileSelected().isEmpty()) {
|
||||
uiNotification.displayValidationError(i18n.get("message.error.noFileSelected"));
|
||||
} else {
|
||||
currentUploadConfirmationwindow = new UploadConfirmationwindow(this, artifactUploadState);
|
||||
currentUploadConfirmationwindow = new UploadConfirmationWindow(this, artifactUploadState);
|
||||
UI.getCurrent().addWindow(currentUploadConfirmationwindow.getUploadConfrimationWindow());
|
||||
setConfirmationPopupHeightWidth(Page.getCurrent().getBrowserWindowWidth(),
|
||||
Page.getCurrent().getBrowserWindowHeight());
|
||||
@@ -656,7 +661,7 @@ public class UploadLayout extends VerticalLayout {
|
||||
return spInfo;
|
||||
}
|
||||
|
||||
void setCurrentUploadConfirmationwindow(final UploadConfirmationwindow currentUploadConfirmationwindow) {
|
||||
void setCurrentUploadConfirmationwindow(final UploadConfirmationWindow currentUploadConfirmationwindow) {
|
||||
this.currentUploadConfirmationwindow = currentUploadConfirmationwindow;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import javax.annotation.PreDestroy;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
|
||||
import org.eclipse.hawkbit.ui.artifacts.event.UploadFileStatus;
|
||||
import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent;
|
||||
import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent.UploadStatusEventType;
|
||||
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
|
||||
@@ -56,11 +57,7 @@ import elemental.json.JsonValue;
|
||||
|
||||
/**
|
||||
* Shows upload status during upload.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
@ViewScope
|
||||
@SpringComponent
|
||||
public class UploadStatusInfoWindow extends Window {
|
||||
@@ -135,26 +132,36 @@ public class UploadStatusInfoWindow extends Window {
|
||||
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
void onEvent(final UploadStatusEvent event) {
|
||||
if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_IN_PROGRESS) {
|
||||
UI.getCurrent().access(
|
||||
() -> updateProgress(event.getUploadStatus().getFileName(), event.getUploadStatus().getBytesRead(),
|
||||
event.getUploadStatus().getContentLength(), event.getUploadStatus().getSoftwareModule()));
|
||||
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_STARTED) {
|
||||
UI.getCurrent().access(() -> onStartOfUpload(event));
|
||||
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_STREAMING_FAILED) {
|
||||
ui.access(() -> uploadFailed(event.getUploadStatus().getFileName(), event.getUploadStatus()
|
||||
.getFailureReason(), event.getUploadStatus().getSoftwareModule()));
|
||||
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_SUCCESSFUL) {
|
||||
UI.getCurrent().access(
|
||||
() -> uploadSucceeded(event.getUploadStatus().getFileName(), event.getUploadStatus()
|
||||
.getSoftwareModule()));
|
||||
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_STREAMING_FINISHED) {
|
||||
ui.access(() -> uploadSucceeded(event.getUploadStatus().getFileName(), event.getUploadStatus()
|
||||
.getSoftwareModule()));
|
||||
|
||||
final UploadFileStatus uploadStatus = event.getUploadStatus();
|
||||
switch (event.getUploadProgressEventType()) {
|
||||
case UPLOAD_IN_PROGRESS:
|
||||
ui.access(() -> updateProgress(uploadStatus.getFileName(), uploadStatus.getBytesRead(),
|
||||
uploadStatus.getContentLength(), uploadStatus.getSoftwareModule()));
|
||||
break;
|
||||
case UPLOAD_STARTED:
|
||||
ui.access(() -> onStartOfUpload(event));
|
||||
break;
|
||||
case UPLOAD_STREAMING_FAILED:
|
||||
ui.access(() -> uploadFailed(uploadStatus.getFileName(), uploadStatus.getFailureReason(),
|
||||
uploadStatus.getSoftwareModule()));
|
||||
break;
|
||||
case UPLOAD_SUCCESSFUL:
|
||||
// fall through here
|
||||
case UPLOAD_STREAMING_FINISHED:
|
||||
ui.access(() -> uploadSucceeded(uploadStatus.getFileName(), uploadStatus.getSoftwareModule()));
|
||||
break;
|
||||
case RECEIVE_UPLOAD:
|
||||
uploadRecevied(uploadStatus.getFileName(), uploadStatus.getSoftwareModule());
|
||||
break;
|
||||
case UPLOAD_FINISHED:
|
||||
case ABORT_UPLOAD:
|
||||
case UPLOAD_FAILED:
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
private void onStartOfUpload(UploadStatusEvent event) {
|
||||
private void onStartOfUpload(final UploadStatusEvent event) {
|
||||
uploadSessionStarted();
|
||||
uploadStarted(event.getUploadStatus().getFileName(), event.getUploadStatus().getSoftwareModule());
|
||||
}
|
||||
@@ -169,19 +176,23 @@ public class UploadStatusInfoWindow extends Window {
|
||||
}
|
||||
|
||||
private void restoreState() {
|
||||
Indexed container = grid.getContainerDataSource();
|
||||
final Indexed container = grid.getContainerDataSource();
|
||||
if (container.getItemIds().isEmpty()) {
|
||||
container.removeAllItems();
|
||||
for (UploadStatusObject statusObject : artifactUploadState.getUploadedFileStatusList()) {
|
||||
Item item = container.addItem(getItemid(statusObject.getFilename(),
|
||||
statusObject.getSelectedSoftwareModule()));
|
||||
for (final UploadStatusObject statusObject : artifactUploadState.getUploadedFileStatusList()) {
|
||||
final Item item = container
|
||||
.addItem(getItemid(statusObject.getFilename(), statusObject.getSelectedSoftwareModule()));
|
||||
item.getItemProperty(REASON).setValue(statusObject.getReason() != null ? statusObject.getReason() : "");
|
||||
item.getItemProperty(STATUS).setValue(statusObject.getStatus());
|
||||
item.getItemProperty(PROGRESS).setValue(statusObject.getProgress());
|
||||
if (statusObject.getStatus() != null) {
|
||||
item.getItemProperty(STATUS).setValue(statusObject.getStatus());
|
||||
}
|
||||
if (statusObject.getProgress() != null) {
|
||||
item.getItemProperty(PROGRESS).setValue(statusObject.getProgress());
|
||||
}
|
||||
item.getItemProperty(FILE_NAME).setValue(statusObject.getFilename());
|
||||
SoftwareModule sw = statusObject.getSelectedSoftwareModule();
|
||||
item.getItemProperty(SPUILabelDefinitions.NAME_VERSION).setValue(
|
||||
HawkbitCommonUtil.getFormattedNameVersion(sw.getName(), sw.getVersion()));
|
||||
final SoftwareModule sw = statusObject.getSelectedSoftwareModule();
|
||||
item.getItemProperty(SPUILabelDefinitions.NAME_VERSION)
|
||||
.setValue(HawkbitCommonUtil.getFormattedNameVersion(sw.getName(), sw.getVersion()));
|
||||
}
|
||||
if (artifactUploadState.isUploadCompleted()) {
|
||||
minimizeButton.setEnabled(false);
|
||||
@@ -209,7 +220,7 @@ public class UploadStatusInfoWindow extends Window {
|
||||
}
|
||||
|
||||
private Grid createGrid() {
|
||||
Grid statusGrid = new Grid(uploads);
|
||||
final Grid statusGrid = new Grid(uploads);
|
||||
statusGrid.addStyleName(SPUIStyleDefinitions.UPLOAD_STATUS_GRID);
|
||||
statusGrid.setSelectionMode(SelectionMode.NONE);
|
||||
statusGrid.setHeaderVisible(true);
|
||||
@@ -219,7 +230,7 @@ public class UploadStatusInfoWindow extends Window {
|
||||
}
|
||||
|
||||
private IndexedContainer getGridContainer() {
|
||||
IndexedContainer uploadContainer = new IndexedContainer();
|
||||
final IndexedContainer uploadContainer = new IndexedContainer();
|
||||
uploadContainer.addContainerProperty(STATUS, String.class, "Active");
|
||||
uploadContainer.addContainerProperty(FILE_NAME, String.class, null);
|
||||
uploadContainer.addContainerProperty(PROGRESS, Double.class, 0D);
|
||||
@@ -321,72 +332,72 @@ public class UploadStatusInfoWindow extends Window {
|
||||
restoreState();
|
||||
}
|
||||
|
||||
void uploadStarted(final String filename, final SoftwareModule softwareModule) {
|
||||
private void uploadRecevied(final String filename, final SoftwareModule softwareModule) {
|
||||
final Item item = uploads.addItem(getItemid(filename, softwareModule));
|
||||
if (item != null) {
|
||||
item.getItemProperty(FILE_NAME).setValue(filename);
|
||||
item.getItemProperty(SPUILabelDefinitions.NAME_VERSION).setValue(
|
||||
HawkbitCommonUtil.getFormattedNameVersion(softwareModule.getName(), softwareModule.getVersion()));
|
||||
final UploadStatusObject uploadStatus = new UploadStatusObject(filename, softwareModule);
|
||||
uploadStatus.setStatus("Active");
|
||||
artifactUploadState.getUploadedFileStatusList().add(uploadStatus);
|
||||
}
|
||||
grid.scrollToEnd();
|
||||
UploadStatusObject uploadStatus = new UploadStatusObject(filename, softwareModule);
|
||||
uploadStatus.setStatus("Active");
|
||||
artifactUploadState.getUploadedFileStatusList().add(uploadStatus);
|
||||
}
|
||||
|
||||
void uploadStarted(final String filename, final SoftwareModule softwareModule) {
|
||||
grid.scrollTo(getItemid(filename, softwareModule));
|
||||
}
|
||||
|
||||
void updateProgress(final String filename, final long readBytes, final long contentLength,
|
||||
final SoftwareModule softwareModule) {
|
||||
final Item item = uploads.getItem(getItemid(filename, softwareModule));
|
||||
double progress = (double) readBytes / (double) contentLength;
|
||||
final double progress = (double) readBytes / (double) contentLength;
|
||||
if (item != null) {
|
||||
item.getItemProperty(PROGRESS).setValue(progress);
|
||||
}
|
||||
List<UploadStatusObject> uploadStatusObjectList = (List<UploadStatusObject>) artifactUploadState
|
||||
.getUploadedFileStatusList().stream().filter(e -> e.getFilename().equals(filename))
|
||||
.collect(Collectors.toList());
|
||||
final List<UploadStatusObject> uploadStatusObjectList = artifactUploadState.getUploadedFileStatusList().stream()
|
||||
.filter(e -> e.getFilename().equals(filename)).collect(Collectors.toList());
|
||||
if (!uploadStatusObjectList.isEmpty()) {
|
||||
UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0);
|
||||
final UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0);
|
||||
uploadStatusObject.setProgress(progress);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when each file upload is success.
|
||||
*
|
||||
*
|
||||
* @param filename
|
||||
* of the uploaded file.
|
||||
* @param softwareModule
|
||||
* selected software module
|
||||
*/
|
||||
public void uploadSucceeded(final String filename, SoftwareModule softwareModule) {
|
||||
public void uploadSucceeded(final String filename, final SoftwareModule softwareModule) {
|
||||
final Item item = uploads.getItem(getItemid(filename, softwareModule));
|
||||
String status = "Finished";
|
||||
final String status = "Finished";
|
||||
if (item != null) {
|
||||
item.getItemProperty(STATUS).setValue(status);
|
||||
}
|
||||
List<UploadStatusObject> uploadStatusObjectList = (List<UploadStatusObject>) artifactUploadState
|
||||
.getUploadedFileStatusList().stream().filter(e -> e.getFilename().equals(filename))
|
||||
.collect(Collectors.toList());
|
||||
final List<UploadStatusObject> uploadStatusObjectList = artifactUploadState.getUploadedFileStatusList().stream()
|
||||
.filter(e -> e.getFilename().equals(filename)).collect(Collectors.toList());
|
||||
if (!uploadStatusObjectList.isEmpty()) {
|
||||
UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0);
|
||||
final UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0);
|
||||
uploadStatusObject.setStatus(status);
|
||||
uploadStatusObject.setProgress(1d);
|
||||
}
|
||||
}
|
||||
|
||||
void uploadFailed(final String filename, final String errorReason, SoftwareModule softwareModule) {
|
||||
void uploadFailed(final String filename, final String errorReason, final SoftwareModule softwareModule) {
|
||||
errorOccured = true;
|
||||
String status = "Failed";
|
||||
final String status = "Failed";
|
||||
final Item item = uploads.getItem(getItemid(filename, softwareModule));
|
||||
if (item != null) {
|
||||
item.getItemProperty(REASON).setValue(errorReason);
|
||||
item.getItemProperty(STATUS).setValue(status);
|
||||
}
|
||||
List<UploadStatusObject> uploadStatusObjectList = (List<UploadStatusObject>) artifactUploadState
|
||||
.getUploadedFileStatusList().stream().filter(e -> e.getFilename().equals(filename))
|
||||
.collect(Collectors.toList());
|
||||
final List<UploadStatusObject> uploadStatusObjectList = artifactUploadState.getUploadedFileStatusList().stream()
|
||||
.filter(e -> e.getFilename().equals(filename)).collect(Collectors.toList());
|
||||
if (!uploadStatusObjectList.isEmpty()) {
|
||||
UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0);
|
||||
final UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0);
|
||||
uploadStatusObject.setStatus(status);
|
||||
uploadStatusObject.setReason(errorReason);
|
||||
}
|
||||
@@ -428,8 +439,8 @@ public class UploadStatusInfoWindow extends Window {
|
||||
return resizeBtn;
|
||||
}
|
||||
|
||||
private void resizeWindow(ClickEvent event) {
|
||||
if (event.getButton().getIcon() == FontAwesome.EXPAND) {
|
||||
private void resizeWindow(final ClickEvent event) {
|
||||
if (FontAwesome.EXPAND.equals(event.getButton().getIcon())) {
|
||||
event.getButton().setIcon(FontAwesome.COMPRESS);
|
||||
setWindowMode(WindowMode.MAXIMIZED);
|
||||
resetColumnWidth();
|
||||
|
||||
@@ -16,15 +16,17 @@ import javax.annotation.PostConstruct;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||
import org.eclipse.hawkbit.repository.model.NamedVersionedEntity;
|
||||
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
||||
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.components.SPUIComponentProvider;
|
||||
import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlButtonRenderer;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||
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;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.UINotification;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -48,7 +50,6 @@ import com.vaadin.ui.TextField;
|
||||
import com.vaadin.ui.UI;
|
||||
import com.vaadin.ui.VerticalLayout;
|
||||
import com.vaadin.ui.renderers.ClickableRenderer.RendererClickEvent;
|
||||
import com.vaadin.ui.themes.ValoTheme;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -115,9 +116,11 @@ public abstract class AbstractMetadataPopupLayout<E extends NamedVersionedEntity
|
||||
public CommonDialogWindow getWindow(final E entity, final M metaData) {
|
||||
selectedEntity = entity;
|
||||
final String nameVersion = HawkbitCommonUtil.getFormattedNameVersion(entity.getName(), entity.getVersion());
|
||||
metadataWindow = SPUIWindowDecorator.getWindow(getMetadataCaption(nameVersion), null,
|
||||
SPUIDefinitions.CUSTOM_METADATA_WINDOW, this, event -> 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<E extends NamedVersionedEntity
|
||||
}
|
||||
|
||||
private TextField createKeyTextField() {
|
||||
final TextField keyField = SPUIComponentProvider.getTextField(i18n.get("textfield.key"), "",
|
||||
ValoTheme.TEXTFIELD_TINY, true, "", i18n.get("textfield.key"), true, 128);
|
||||
keyField.setId(SPUIComponentIdProvider.METADATA_KEY_FIELD_ID);
|
||||
final TextField keyField = new TextFieldBuilder().caption(i18n.get("textfield.key")).required(true)
|
||||
.prompt(i18n.get("textfield.key")).immediate(true).id(SPUIComponentIdProvider.METADATA_KEY_FIELD_ID)
|
||||
.maxLengthAllowed(128).buildTextComponent();
|
||||
keyField.addTextChangeListener(event -> onKeyChange(event));
|
||||
keyField.setTextChangeEventMode(TextChangeEventMode.EAGER);
|
||||
keyField.setWidth("100%");
|
||||
@@ -214,9 +217,9 @@ public abstract class AbstractMetadataPopupLayout<E extends NamedVersionedEntity
|
||||
}
|
||||
|
||||
private TextArea createValueTextField() {
|
||||
valueTextArea = SPUIComponentProvider.getTextArea(i18n.get("textfield.value"), null, ValoTheme.TEXTAREA_TINY,
|
||||
true, null, i18n.get("textfield.value"), 4000);
|
||||
valueTextArea.setId(SPUIComponentIdProvider.METADATA_VALUE_ID);
|
||||
valueTextArea = new TextAreaBuilder().caption(i18n.get("textfield.value")).required(true)
|
||||
.prompt(i18n.get("textfield.value")).immediate(true).id(SPUIComponentIdProvider.METADATA_VALUE_ID)
|
||||
.maxLengthAllowed(4000).buildTextComponent();
|
||||
valueTextArea.setNullRepresentation("");
|
||||
valueTextArea.setSizeFull();
|
||||
valueTextArea.setHeight(100, Unit.PERCENTAGE);
|
||||
@@ -301,7 +304,7 @@ public abstract class AbstractMetadataPopupLayout<E extends NamedVersionedEntity
|
||||
}
|
||||
|
||||
private Label createHeaderCaption() {
|
||||
return SPUIComponentProvider.getLabel(i18n.get("caption.metadata"), SPUILabelDefinitions.SP_WIDGET_CAPTION);
|
||||
return new LabelBuilder().name(i18n.get("caption.metadata")).buildCaptionLabel();
|
||||
}
|
||||
|
||||
private static IndexedContainer getMetadataContainer() {
|
||||
@@ -407,9 +410,9 @@ public abstract class AbstractMetadataPopupLayout<E extends NamedVersionedEntity
|
||||
|
||||
private String getMetadataCaption(final String nameVersionStr) {
|
||||
final StringBuilder caption = new StringBuilder();
|
||||
caption.append(HawkbitCommonUtil.DIV_DESCRIPTION + i18n.get("caption.metadata.popup") + " "
|
||||
caption.append(HawkbitCommonUtil.DIV_DESCRIPTION_START + i18n.get("caption.metadata.popup") + " "
|
||||
+ HawkbitCommonUtil.getBoldHTMLText(nameVersionStr));
|
||||
caption.append(HawkbitCommonUtil.DIV_CLOSE);
|
||||
caption.append(HawkbitCommonUtil.DIV_DESCRIPTION_END);
|
||||
return caption.toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ package org.eclipse.hawkbit.ui.common;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@@ -70,7 +69,7 @@ import com.vaadin.ui.themes.ValoTheme;
|
||||
* corner and a save and cancel button at the bottom. Is not intended to reuse.
|
||||
*
|
||||
*/
|
||||
public class CommonDialogWindow extends Window implements Serializable {
|
||||
public class CommonDialogWindow extends Window {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@@ -13,10 +13,6 @@ import com.vaadin.ui.AbstractColorPicker.Coordinates2Color;
|
||||
|
||||
/**
|
||||
* Converts 2d-coordinates to a Color.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class CoordinatesToColor implements Coordinates2Color {
|
||||
|
||||
@@ -30,32 +26,31 @@ public class CoordinatesToColor implements Coordinates2Color {
|
||||
@Override
|
||||
public int[] calculate(final Color color) {
|
||||
final float[] hsv = color.getHSV();
|
||||
final int x = Math.round(hsv[0] * 220f);
|
||||
int y = 0;
|
||||
y = calculateYCoordinateOfColor(hsv);
|
||||
final int x = Math.round(hsv[0] * 220F);
|
||||
final int y = calculateYCoordinateOfColor(hsv);
|
||||
return new int[] { x, y };
|
||||
}
|
||||
|
||||
private Color calculateHSVColor(final int x, final int y) {
|
||||
final float h = x / 220f;
|
||||
float s = 1f;
|
||||
float v = 1f;
|
||||
private static Color calculateHSVColor(final int x, final int y) {
|
||||
final float h = x / 220F;
|
||||
float s = 1F;
|
||||
float v = 1F;
|
||||
if (y < 110) {
|
||||
s = y / 110f;
|
||||
s = y / 110F;
|
||||
} else if (y > 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;
|
||||
}
|
||||
|
||||
@@ -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 <E>
|
||||
* the concrete text component
|
||||
*/
|
||||
public abstract class AbstractTextFieldBuilder<E extends AbstractTextField> {
|
||||
|
||||
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<E> caption(final String caption) {
|
||||
this.caption = caption;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param style
|
||||
* the style to set * @return the builder
|
||||
* @return the builder
|
||||
*/
|
||||
public AbstractTextFieldBuilder<E> style(final String style) {
|
||||
this.style = style;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param styleName
|
||||
* the styleName to set
|
||||
* @return the builder
|
||||
*/
|
||||
public AbstractTextFieldBuilder<E> styleName(final String styleName) {
|
||||
this.styleName = styleName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param required
|
||||
* the required to set
|
||||
* @return the builder
|
||||
*/
|
||||
public AbstractTextFieldBuilder<E> required(final boolean required) {
|
||||
this.required = required;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param prompt
|
||||
* the prompt to set
|
||||
* @return the builder
|
||||
*/
|
||||
public AbstractTextFieldBuilder<E> prompt(final String prompt) {
|
||||
this.prompt = prompt;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param immediate
|
||||
* the immediate to set
|
||||
* @return the builder
|
||||
*/
|
||||
public AbstractTextFieldBuilder<E> immediate(final boolean immediate) {
|
||||
this.immediate = immediate;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param maxLengthAllowed
|
||||
* the maxLengthAllowed to set
|
||||
* @return the builder
|
||||
*/
|
||||
public AbstractTextFieldBuilder<E> maxLengthAllowed(final int maxLengthAllowed) {
|
||||
this.maxLengthAllowed = maxLengthAllowed;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id
|
||||
* the id to set
|
||||
* @return the builder
|
||||
*/
|
||||
public AbstractTextFieldBuilder<E> 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();
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<TextArea> {
|
||||
|
||||
private static final int TEXT_AREA_DEFAULT_MAX_LENGTH = 512;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public TextAreaBuilder() {
|
||||
maxLengthAllowed(TEXT_AREA_DEFAULT_MAX_LENGTH);
|
||||
styleName(ValoTheme.TEXTAREA_TINY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TextArea createTextComponent() {
|
||||
final TextArea textArea = new TextArea();
|
||||
textArea.addStyleName(ValoTheme.TEXTAREA_SMALL);
|
||||
return textArea;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.common.builder;
|
||||
|
||||
import com.vaadin.event.FieldEvents.TextChangeListener;
|
||||
import com.vaadin.server.Sizeable.Unit;
|
||||
import com.vaadin.ui.AbstractTextField.TextChangeEventMode;
|
||||
import com.vaadin.ui.TextField;
|
||||
import com.vaadin.ui.themes.ValoTheme;
|
||||
|
||||
/**
|
||||
* Textfield builder.
|
||||
*
|
||||
*/
|
||||
public class TextFieldBuilder extends AbstractTextFieldBuilder<TextField> {
|
||||
|
||||
private static final int TEXT_FIELD_DEFAULT_MAX_LENGTH = 64;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public TextFieldBuilder() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param id
|
||||
* the id
|
||||
*/
|
||||
public TextFieldBuilder(final String id) {
|
||||
maxLengthAllowed(TEXT_FIELD_DEFAULT_MAX_LENGTH);
|
||||
styleName(ValoTheme.TEXTAREA_TINY);
|
||||
id(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a search text field.
|
||||
*
|
||||
* @param textChangeListener
|
||||
* listener when text is changed.
|
||||
* @return the textfield
|
||||
*/
|
||||
public TextField createSearchField(final TextChangeListener textChangeListener) {
|
||||
final TextField textField = style("filter-box").styleName("text-style filter-box-hide").buildTextComponent();
|
||||
textField.setWidth(100.0F, Unit.PERCENTAGE);
|
||||
textField.addTextChangeListener(textChangeListener);
|
||||
textField.setTextChangeEventMode(TextChangeEventMode.LAZY);
|
||||
// 1 seconds timeout.
|
||||
textField.setTextChangeTimeout(1000);
|
||||
return textField;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TextField createTextComponent() {
|
||||
final TextField textField = new TextField();
|
||||
textField.addStyleName(ValoTheme.TEXTFIELD_SMALL);
|
||||
return textField;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
/**
|
||||
* 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.eclipse.hawkbit.ui.common.CommonDialogWindow;
|
||||
import org.eclipse.hawkbit.ui.common.CustomCommonDialogWindow;
|
||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||
|
||||
import com.vaadin.ui.AbstractLayout;
|
||||
import com.vaadin.ui.Button.ClickListener;
|
||||
import com.vaadin.ui.Component;
|
||||
import com.vaadin.ui.Window;
|
||||
|
||||
/**
|
||||
* Builder for Window.
|
||||
*/
|
||||
public class WindowBuilder {
|
||||
|
||||
private String caption;
|
||||
private Component content;
|
||||
private ClickListener saveButtonClickListener;
|
||||
private ClickListener cancelButtonClickListener;
|
||||
private String helpLink;
|
||||
private AbstractLayout layout;
|
||||
private I18N i18n;
|
||||
private final String type;
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param type
|
||||
* window type
|
||||
*/
|
||||
public WindowBuilder(final String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the caption.
|
||||
*
|
||||
* @param caption
|
||||
* the caption
|
||||
* @return the window builder
|
||||
*/
|
||||
public WindowBuilder caption(final String caption) {
|
||||
this.caption = caption;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the content.
|
||||
*
|
||||
* @param content
|
||||
* the content
|
||||
* @return the window builder
|
||||
*/
|
||||
public WindowBuilder content(final Component content) {
|
||||
this.content = content;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the saveButtonClickListener.
|
||||
*
|
||||
* @param saveButtonClickListener
|
||||
* the saveButtonClickListener
|
||||
* @return the window builder
|
||||
*/
|
||||
public WindowBuilder saveButtonClickListener(final ClickListener saveButtonClickListener) {
|
||||
this.saveButtonClickListener = saveButtonClickListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cancelButtonClickListener.
|
||||
*
|
||||
* @param cancelButtonClickListener
|
||||
* the cancelButtonClickListener
|
||||
* @return the window builder
|
||||
*/
|
||||
public WindowBuilder cancelButtonClickListener(final ClickListener cancelButtonClickListener) {
|
||||
this.cancelButtonClickListener = cancelButtonClickListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the helpLink.
|
||||
*
|
||||
* @param helpLink
|
||||
* the helpLink
|
||||
* @return the window builder
|
||||
*/
|
||||
public WindowBuilder helpLink(final String helpLink) {
|
||||
this.helpLink = helpLink;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the layout.
|
||||
*
|
||||
* @param layout
|
||||
* the layout
|
||||
* @return the window builder
|
||||
*/
|
||||
public WindowBuilder layout(final AbstractLayout layout) {
|
||||
this.layout = layout;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the i18n.
|
||||
*
|
||||
* @param i18n
|
||||
* the i18n
|
||||
* @return the window builder
|
||||
*/
|
||||
public WindowBuilder i18n(final I18N i18n) {
|
||||
this.i18n = i18n;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id
|
||||
* the id to set * @return the window builder
|
||||
*/
|
||||
public WindowBuilder id(final String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the common dialog window.
|
||||
*
|
||||
* @return the window.
|
||||
*/
|
||||
public CommonDialogWindow buildCommonDialogWindow() {
|
||||
CommonDialogWindow window;
|
||||
|
||||
if (SPUIDefinitions.CUSTOM_METADATA_WINDOW.equals(type)) {
|
||||
window = new CustomCommonDialogWindow(caption, content, helpLink, saveButtonClickListener,
|
||||
cancelButtonClickListener, layout, i18n);
|
||||
window.setDraggable(true);
|
||||
window.setClosable(true);
|
||||
return window;
|
||||
}
|
||||
window = new CommonDialogWindow(caption, content, helpLink, saveButtonClickListener, cancelButtonClickListener,
|
||||
layout, i18n);
|
||||
|
||||
decorateWindow(window);
|
||||
|
||||
return window;
|
||||
|
||||
}
|
||||
|
||||
private void decorateWindow(final Window window) {
|
||||
if (id != null) {
|
||||
window.setId(id);
|
||||
}
|
||||
|
||||
if (SPUIDefinitions.CONFIRMATION_WINDOW.equals(type)) {
|
||||
window.setDraggable(false);
|
||||
window.setClosable(true);
|
||||
window.addStyleName(SPUIStyleDefinitions.CONFIRMATION_WINDOW_CAPTION);
|
||||
|
||||
} else if (SPUIDefinitions.CREATE_UPDATE_WINDOW.equals(type)) {
|
||||
window.setDraggable(true);
|
||||
window.setClosable(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build window based on type.
|
||||
*
|
||||
* @return Window
|
||||
*/
|
||||
public Window buildWindow() {
|
||||
final Window window = new Window(caption);
|
||||
window.setContent(content);
|
||||
window.setSizeUndefined();
|
||||
window.setModal(true);
|
||||
window.setResizable(false);
|
||||
|
||||
decorateWindow(window);
|
||||
|
||||
if (SPUIDefinitions.CREATE_UPDATE_WINDOW.equals(type)) {
|
||||
window.setClosable(false);
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import java.util.Map.Entry;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||
@@ -51,6 +52,9 @@ public abstract class AbstractConfirmationWindowLayout extends VerticalLayout {
|
||||
@Autowired
|
||||
protected transient EventBus.SessionEventBus eventBus;
|
||||
|
||||
/**
|
||||
* PostConstruct.
|
||||
*/
|
||||
@PostConstruct
|
||||
public void initialize() {
|
||||
removeAllComponents();
|
||||
@@ -65,10 +69,9 @@ public abstract class AbstractConfirmationWindowLayout extends VerticalLayout {
|
||||
}
|
||||
|
||||
private void createActionMessgaeLabel() {
|
||||
actionMessage = SPUIComponentProvider.getLabel("", null);
|
||||
actionMessage = new LabelBuilder().name("").id(SPUIComponentIdProvider.ACTION_LABEL).visible(false)
|
||||
.buildLabel();
|
||||
actionMessage.addStyleName(SPUIStyleDefinitions.CONFIRM_WINDOW_INFO_BOX);
|
||||
actionMessage.setId(SPUIComponentIdProvider.ACTION_LABEL);
|
||||
actionMessage.setVisible(false);
|
||||
}
|
||||
|
||||
private void createAccordian() {
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
||||
import org.eclipse.hawkbit.repository.model.NamedEntity;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
||||
import org.eclipse.hawkbit.ui.common.table.BaseEntityEvent;
|
||||
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
|
||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||
@@ -25,7 +26,6 @@ import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.vaadin.spring.events.EventBus;
|
||||
@@ -183,7 +183,7 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
|
||||
}
|
||||
|
||||
private Label createHeaderCaption() {
|
||||
return SPUIComponentProvider.getLabel(getDefaultCaption(), SPUILabelDefinitions.SP_WIDGET_CAPTION);
|
||||
return new LabelBuilder().name(getDefaultCaption()).buildCaptionLabel();
|
||||
}
|
||||
|
||||
protected VerticalLayout getTabLayout() {
|
||||
@@ -222,7 +222,6 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
|
||||
populateLog();
|
||||
populateDescription();
|
||||
populateDetailsWidget();
|
||||
populateMetadataDetails();
|
||||
}
|
||||
|
||||
protected void populateLog() {
|
||||
|
||||
@@ -33,45 +33,44 @@ import com.vaadin.ui.UI;
|
||||
import com.vaadin.ui.themes.ValoTheme;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* DistributionSet Metadata details layout.
|
||||
*
|
||||
*/
|
||||
|
||||
@SpringComponent
|
||||
@VaadinSessionScope
|
||||
public class DistributionSetMetadatadetailslayout extends Table{
|
||||
|
||||
public class DistributionSetMetadatadetailslayout extends Table {
|
||||
|
||||
private static final long serialVersionUID = 2913758299611837718L;
|
||||
|
||||
|
||||
private DistributionSetManagement distributionSetManagement;
|
||||
|
||||
private DsMetadataPopupLayout dsMetadataPopupLayout;
|
||||
|
||||
private static final String METADATA_KEY = "Key";
|
||||
|
||||
private static final String VIEW ="view";
|
||||
|
||||
private static final String VIEW = "view";
|
||||
|
||||
private transient DistributionSetManagement distributionSetManagement;
|
||||
|
||||
private DsMetadataPopupLayout dsMetadataPopupLayout;
|
||||
|
||||
private SpPermissionChecker permissionChecker;
|
||||
|
||||
|
||||
private transient EntityFactory entityFactory;
|
||||
|
||||
private I18N i18n;
|
||||
|
||||
private Long selectedDistSetId;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param i18n
|
||||
* @param permissionChecker
|
||||
* @param distributionSetManagement
|
||||
* @param dsMetadataPopupLayout
|
||||
*/
|
||||
|
||||
private Long selectedDistSetId;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param i18n
|
||||
* @param permissionChecker
|
||||
* @param distributionSetManagement
|
||||
* @param dsMetadataPopupLayout
|
||||
* @param entityFactory
|
||||
*/
|
||||
public void init(final I18N i18n, final SpPermissionChecker permissionChecker,
|
||||
final DistributionSetManagement distributionSetManagement,
|
||||
final DsMetadataPopupLayout dsMetadataPopupLayout,
|
||||
final EntityFactory entityFactory) {
|
||||
final DistributionSetManagement distributionSetManagement,
|
||||
final DsMetadataPopupLayout dsMetadataPopupLayout, final EntityFactory entityFactory) {
|
||||
this.i18n = i18n;
|
||||
this.permissionChecker = permissionChecker;
|
||||
this.distributionSetManagement = distributionSetManagement;
|
||||
@@ -80,45 +79,24 @@ public class DistributionSetMetadatadetailslayout extends Table{
|
||||
createDSMetadataTable();
|
||||
addCustomGeneratedColumns();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Populate software module metadata.
|
||||
*
|
||||
*
|
||||
* @param distributionSet
|
||||
*/
|
||||
public void populateDSMetadata(final DistributionSet distributionSet) {
|
||||
removeAllItems();
|
||||
if (null == distributionSet) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
selectedDistSetId = distributionSet.getId();
|
||||
final List<DistributionSetMetadata> dsMetadataList = distributionSet.getMetadata();
|
||||
final List<DistributionSetMetadata> dsMetadataList = distributionSetManagement
|
||||
.findDistributionSetMetadataByDistributionSetId(selectedDistSetId);
|
||||
if (null != dsMetadataList && !dsMetadataList.isEmpty()) {
|
||||
dsMetadataList.forEach(dsMetadata -> setDSMetadataProperties(dsMetadata));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create metadata .
|
||||
*
|
||||
* @param metadataKeyName
|
||||
*/
|
||||
public void createMetadata(final String metadataKeyName){
|
||||
final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource();
|
||||
final Item item = metadataContainer.addItem(metadataKeyName);
|
||||
item.getItemProperty(METADATA_KEY).setValue(metadataKeyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete metadata.
|
||||
*
|
||||
* @param metadataKeyName
|
||||
*/
|
||||
public void deleteMetadata(final String metadataKeyName){
|
||||
final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource();
|
||||
metadataContainer.removeItem(metadataKeyName);
|
||||
|
||||
}
|
||||
|
||||
private void createDSMetadataTable() {
|
||||
@@ -131,9 +109,9 @@ public class DistributionSetMetadatadetailslayout extends Table{
|
||||
setContainerDataSource(getDistSetContainer());
|
||||
setColumnHeaderMode(ColumnHeaderMode.EXPLICIT);
|
||||
addDSMetadataTableHeader();
|
||||
setSizeFull();
|
||||
//same as height of other tabs in details tabsheet
|
||||
setHeight(116,Unit.PIXELS);
|
||||
setSizeFull();
|
||||
// same as height of other tabs in details tabsheet
|
||||
setHeight(116, Unit.PIXELS);
|
||||
}
|
||||
|
||||
private IndexedContainer getDistSetContainer() {
|
||||
@@ -141,7 +119,7 @@ public class DistributionSetMetadatadetailslayout extends Table{
|
||||
container.addContainerProperty(METADATA_KEY, String.class, "");
|
||||
setColumnExpandRatio(METADATA_KEY, 0.7f);
|
||||
setColumnAlignment(METADATA_KEY, Align.LEFT);
|
||||
|
||||
|
||||
if (permissionChecker.hasUpdateDistributionPermission()) {
|
||||
container.addContainerProperty(VIEW, Label.class, "");
|
||||
setColumnExpandRatio(VIEW, 0.2F);
|
||||
@@ -154,39 +132,36 @@ public class DistributionSetMetadatadetailslayout extends Table{
|
||||
setColumnHeader(METADATA_KEY, i18n.get("header.key"));
|
||||
}
|
||||
|
||||
|
||||
private void setDSMetadataProperties(final DistributionSetMetadata dsMetadata){
|
||||
private void setDSMetadataProperties(final DistributionSetMetadata dsMetadata) {
|
||||
final Item item = getContainerDataSource().addItem(dsMetadata.getKey());
|
||||
item.getItemProperty(METADATA_KEY).setValue(dsMetadata.getKey());
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void addCustomGeneratedColumns() {
|
||||
addGeneratedColumn(METADATA_KEY,
|
||||
(source, itemId, columnId) -> customMetadataDetailButton((String) itemId));
|
||||
|
||||
private void addCustomGeneratedColumns() {
|
||||
addGeneratedColumn(METADATA_KEY, (source, itemId, columnId) -> customMetadataDetailButton((String) itemId));
|
||||
}
|
||||
|
||||
private Button customMetadataDetailButton(final String metadataKey) {
|
||||
final Button viewIcon = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey, "View "
|
||||
+ metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class);
|
||||
final Button viewIcon = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey,
|
||||
"View " + metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class);
|
||||
viewIcon.setData(metadataKey);
|
||||
viewIcon.addStyleName(ValoTheme.BUTTON_TINY + " " + ValoTheme.BUTTON_LINK + " " + "on-focus-no-border link"
|
||||
+ " " + "text-style");
|
||||
viewIcon.addClickListener(event -> showMetadataDetails(selectedDistSetId, metadataKey));
|
||||
return viewIcon;
|
||||
}
|
||||
|
||||
|
||||
private static String getDetailLinkId(final String name) {
|
||||
return new StringBuilder(SPUIComponentIdProvider.DS_METADATA_DETAIL_LINK).append('.').append(name)
|
||||
.toString();
|
||||
return new StringBuilder(SPUIComponentIdProvider.DS_METADATA_DETAIL_LINK).append('.').append(name).toString();
|
||||
}
|
||||
|
||||
private void showMetadataDetails(final Long selectedDistSetId , final String metadataKey) {
|
||||
DistributionSet distSet = distributionSetManagement.findDistributionSetById(selectedDistSetId);
|
||||
|
||||
|
||||
private void showMetadataDetails(final Long selectedDistSetId, final String metadataKey) {
|
||||
final DistributionSet distSet = distributionSetManagement.findDistributionSetById(selectedDistSetId);
|
||||
|
||||
/* display the window */
|
||||
UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(distSet,
|
||||
entityFactory.generateDistributionSetMetadata(distSet, metadataKey, "") ));
|
||||
entityFactory.generateDistributionSetMetadata(distSet, metadataKey, "")));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -41,19 +41,19 @@ import com.vaadin.ui.themes.ValoTheme;
|
||||
@ViewScope
|
||||
public class SoftwareModuleMetadatadetailslayout extends Table {
|
||||
|
||||
private static final long serialVersionUID = 2913758299611838818L;
|
||||
private static final long serialVersionUID = 2913758299611838818L;
|
||||
|
||||
private static final String METADATA_KEY = "Key";
|
||||
private static final String METADATA_KEY = "Key";
|
||||
|
||||
private SpPermissionChecker permissionChecker;
|
||||
private SpPermissionChecker permissionChecker;
|
||||
|
||||
private transient SoftwareManagement softwareManagement;
|
||||
|
||||
private SwMetadataPopupLayout swMetadataPopupLayout;
|
||||
private SwMetadataPopupLayout swMetadataPopupLayout;
|
||||
|
||||
private I18N i18n;
|
||||
private I18N i18n;
|
||||
|
||||
private Long selectedSWModuleId;
|
||||
private Long selectedSWModuleId;
|
||||
|
||||
private transient EntityFactory entityFactory;
|
||||
|
||||
@@ -83,100 +83,102 @@ public class SoftwareModuleMetadatadetailslayout extends Table {
|
||||
addCustomGeneratedColumns();
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate software module metadata table.
|
||||
*
|
||||
* @param swModule
|
||||
*/
|
||||
public void populateSMMetadata(final SoftwareModule swModule) {
|
||||
removeAllItems();
|
||||
if (null == swModule) {
|
||||
return;
|
||||
}
|
||||
selectedSWModuleId = swModule.getId();
|
||||
final List<SoftwareModuleMetadata> swMetadataList = swModule.getMetadata();
|
||||
if (null != swMetadataList && !swMetadataList.isEmpty()) {
|
||||
swMetadataList.forEach(swMetadata -> setSWMetadataProperties(swMetadata));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Populate software module metadata table.
|
||||
*
|
||||
* @param swModule
|
||||
*/
|
||||
public void populateSMMetadata(final SoftwareModule swModule) {
|
||||
removeAllItems();
|
||||
if (null == swModule) {
|
||||
return;
|
||||
}
|
||||
selectedSWModuleId = swModule.getId();
|
||||
final List<SoftwareModuleMetadata> swMetadataList = softwareManagement.findSoftwareModuleMetadataBySoftwareModuleId(selectedSWModuleId);
|
||||
if (null != swMetadataList && !swMetadataList.isEmpty()) {
|
||||
swMetadataList.forEach(swMetadata -> setSWMetadataProperties(swMetadata));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create metadata.
|
||||
*
|
||||
* @param metadataKeyName
|
||||
*/
|
||||
public void createMetadata(final String metadataKeyName) {
|
||||
final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource();
|
||||
final Item item = metadataContainer.addItem(metadataKeyName);
|
||||
item.getItemProperty(METADATA_KEY).setValue(metadataKeyName);
|
||||
/**
|
||||
* Create metadata.
|
||||
*
|
||||
* @param metadataKeyName
|
||||
*/
|
||||
public void createMetadata(final String metadataKeyName) {
|
||||
final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource();
|
||||
final Item item = metadataContainer.addItem(metadataKeyName);
|
||||
item.getItemProperty(METADATA_KEY).setValue(metadataKeyName);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete metadata.
|
||||
*
|
||||
* @param metadataKeyName
|
||||
*/
|
||||
public void deleteMetadata(final String metadataKeyName) {
|
||||
final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource();
|
||||
metadataContainer.removeItem(metadataKeyName);
|
||||
}
|
||||
/**
|
||||
* Delete metadata.
|
||||
*
|
||||
* @param metadataKeyName
|
||||
*/
|
||||
public void deleteMetadata(final String metadataKeyName) {
|
||||
final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource();
|
||||
metadataContainer.removeItem(metadataKeyName);
|
||||
}
|
||||
|
||||
private void createSWMMetadataTable() {
|
||||
addStyleName(ValoTheme.TABLE_NO_HORIZONTAL_LINES);
|
||||
addStyleName(ValoTheme.TABLE_NO_STRIPES);
|
||||
addStyleName(SPUIStyleDefinitions.SW_MODULE_TABLE);
|
||||
setSelectable(false);
|
||||
setImmediate(true);
|
||||
setContainerDataSource(getSwModuleMetadataContainer());
|
||||
setColumnHeaderMode(ColumnHeaderMode.EXPLICIT);
|
||||
addSMMetadataTableHeader();
|
||||
setSizeFull();
|
||||
// same as height of other tabs in details tabsheet
|
||||
setHeight(116, Unit.PIXELS);
|
||||
}
|
||||
private void createSWMMetadataTable() {
|
||||
addStyleName(ValoTheme.TABLE_NO_HORIZONTAL_LINES);
|
||||
addStyleName(ValoTheme.TABLE_NO_STRIPES);
|
||||
addStyleName(SPUIStyleDefinitions.SW_MODULE_TABLE);
|
||||
setSelectable(false);
|
||||
setImmediate(true);
|
||||
setContainerDataSource(getSwModuleMetadataContainer());
|
||||
setColumnHeaderMode(ColumnHeaderMode.EXPLICIT);
|
||||
addSMMetadataTableHeader();
|
||||
setSizeFull();
|
||||
//same as height of other tabs in details tabsheet
|
||||
setHeight(116,Unit.PIXELS);
|
||||
}
|
||||
|
||||
private IndexedContainer getSwModuleMetadataContainer() {
|
||||
final IndexedContainer container = new IndexedContainer();
|
||||
container.addContainerProperty(METADATA_KEY, String.class, "");
|
||||
setColumnAlignment(METADATA_KEY, Align.LEFT);
|
||||
return container;
|
||||
}
|
||||
private IndexedContainer getSwModuleMetadataContainer() {
|
||||
final IndexedContainer container = new IndexedContainer();
|
||||
container.addContainerProperty(METADATA_KEY, String.class, "");
|
||||
setColumnAlignment(METADATA_KEY, Align.LEFT);
|
||||
return container;
|
||||
}
|
||||
|
||||
private void addSMMetadataTableHeader() {
|
||||
setColumnHeader(METADATA_KEY, i18n.get("header.key"));
|
||||
}
|
||||
private void addSMMetadataTableHeader() {
|
||||
setColumnHeader(METADATA_KEY, i18n.get("header.key"));
|
||||
}
|
||||
|
||||
private void setSWMetadataProperties(final SoftwareModuleMetadata swMetadata) {
|
||||
final Item item = getContainerDataSource().addItem(swMetadata.getKey());
|
||||
item.getItemProperty(METADATA_KEY).setValue(swMetadata.getKey());
|
||||
}
|
||||
|
||||
private void addCustomGeneratedColumns() {
|
||||
addGeneratedColumn(METADATA_KEY, (source, itemId, columnId) -> customMetadataDetailButton((String) itemId));
|
||||
}
|
||||
private void setSWMetadataProperties(final SoftwareModuleMetadata swMetadata) {
|
||||
final Item item = getContainerDataSource().addItem(swMetadata.getKey());
|
||||
item.getItemProperty(METADATA_KEY).setValue(swMetadata.getKey());
|
||||
}
|
||||
|
||||
private Button customMetadataDetailButton(final String metadataKey) {
|
||||
final Button viewLink = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey,
|
||||
"View" + metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class);
|
||||
viewLink.setData(metadataKey);
|
||||
if (permissionChecker.hasUpdateDistributionPermission()) {
|
||||
viewLink.addStyleName(ValoTheme.BUTTON_TINY + " " + ValoTheme.BUTTON_LINK + " " + "on-focus-no-border link"
|
||||
+ " " + "text-style");
|
||||
viewLink.addClickListener(event -> showMetadataDetails(selectedSWModuleId, metadataKey));
|
||||
}
|
||||
return viewLink;
|
||||
}
|
||||
private void addCustomGeneratedColumns() {
|
||||
addGeneratedColumn(METADATA_KEY, (source, itemId, columnId) -> customMetadataDetailButton((String) itemId));
|
||||
}
|
||||
|
||||
private static String getDetailLinkId(final String name) {
|
||||
return new StringBuilder(SPUIComponentIdProvider.SW_METADATA_DETAIL_LINK).append('.').append(name).toString();
|
||||
}
|
||||
private Button customMetadataDetailButton(final String metadataKey) {
|
||||
final Button viewLink = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey, "View"
|
||||
+ metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class);
|
||||
viewLink.setData(metadataKey);
|
||||
if (permissionChecker.hasUpdateDistributionPermission()) {
|
||||
viewLink.addStyleName(ValoTheme.BUTTON_TINY + " " + ValoTheme.BUTTON_LINK + " " + "on-focus-no-border link"
|
||||
+ " " + "text-style");
|
||||
viewLink.addClickListener(event -> showMetadataDetails(selectedSWModuleId, metadataKey));
|
||||
}
|
||||
return viewLink;
|
||||
}
|
||||
|
||||
private void showMetadataDetails(final Long selectedSWModuleId, final String metadataKey) {
|
||||
final SoftwareModule swmodule = softwareManagement.findSoftwareModuleById(selectedSWModuleId);
|
||||
/* display the window */
|
||||
UI.getCurrent().addWindow(swMetadataPopupLayout.getWindow(swmodule,
|
||||
entityFactory.generateSoftwareModuleMetadata(swmodule, metadataKey, "")));
|
||||
}
|
||||
private static String getDetailLinkId(final String name) {
|
||||
return new StringBuilder(SPUIComponentIdProvider.SW_METADATA_DETAIL_LINK).append('.').append(name).toString();
|
||||
}
|
||||
|
||||
private void showMetadataDetails(final Long selectedSWModuleId, final String metadataKey) {
|
||||
final SoftwareModule swmodule = softwareManagement.findSoftwareModuleById(selectedSWModuleId);
|
||||
/* display the window */
|
||||
UI.getCurrent().addWindow(
|
||||
swMetadataPopupLayout.getWindow(swmodule,
|
||||
entityFactory.generateSoftwareModuleMetadata(swmodule, metadataKey, "")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.common.filterlayout;
|
||||
|
||||
import static org.eclipse.hawkbit.ui.utils.SPUIDefinitions.NO_TAG_BUTTON_ID;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -50,7 +52,7 @@ public abstract class AbstractFilterButtons extends Table {
|
||||
|
||||
/**
|
||||
* Initialize layout of filter buttons.
|
||||
*
|
||||
*
|
||||
* @param filterButtonClickBehaviour
|
||||
* click behaviour of filter buttons.
|
||||
*/
|
||||
@@ -95,16 +97,12 @@ public abstract class AbstractFilterButtons extends Table {
|
||||
container.addContainerProperty(SPUILabelDefinitions.VAR_NAME, String.class, null, true, true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
protected void addColumn() {
|
||||
addGeneratedColumn(FILTER_BUTTON_COLUMN, (source, itemId, columnId) -> addGeneratedCell(itemId));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param itemId
|
||||
* @return
|
||||
*/
|
||||
private DragAndDropWrapper addGeneratedCell(final Object itemId) {
|
||||
|
||||
final Item item = getItem(itemId);
|
||||
final Long id = (Long) item.getItemProperty(SPUILabelDefinitions.VAR_ID).getValue();
|
||||
final String name = (String) item.getItemProperty(SPUILabelDefinitions.VAR_NAME).getValue();
|
||||
@@ -116,16 +114,18 @@ public abstract class AbstractFilterButtons extends Table {
|
||||
? item.getItemProperty(SPUILabelDefinitions.VAR_COLOR).getValue().toString() : DEFAULT_GREEN;
|
||||
final Button typeButton = createFilterButton(id, name, desc, color, itemId);
|
||||
typeButton.addClickListener(event -> filterButtonClickBehaviour.processFilterButtonClick(event));
|
||||
if (typeButton.getData().equals(SPUIDefinitions.NO_TAG_BUTTON_ID) && isNoTagSateSelected()) {
|
||||
filterButtonClickBehaviour.setDefaultClickedButton(typeButton);
|
||||
} else if (id != null && isClickedByDefault(name)) {
|
||||
|
||||
if ((NO_TAG_BUTTON_ID.equals(typeButton.getData()) && isNoTagStateSelected())
|
||||
|| (id != null && isClickedByDefault(name))) {
|
||||
|
||||
filterButtonClickBehaviour.setDefaultClickedButton(typeButton);
|
||||
}
|
||||
|
||||
return createDragAndDropWrapper(typeButton, name, id);
|
||||
}
|
||||
|
||||
protected boolean isNoTagSateSelected() {
|
||||
return Boolean.FALSE;
|
||||
protected boolean isNoTagStateSelected() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private DragAndDropWrapper createDragAndDropWrapper(final Button tagButton, final String name, final Long id) {
|
||||
@@ -195,21 +195,21 @@ public abstract class AbstractFilterButtons extends Table {
|
||||
|
||||
/**
|
||||
* Id of the buttons table to be used in test cases.
|
||||
*
|
||||
*
|
||||
* @return Id of the Button table.
|
||||
*/
|
||||
protected abstract String getButtonsTableId();
|
||||
|
||||
/**
|
||||
* create new lazyquery container to display the buttons.
|
||||
*
|
||||
*
|
||||
* @return reference of {@link LazyQueryContainer}
|
||||
*/
|
||||
protected abstract LazyQueryContainer createButtonsLazyQueryContainer();
|
||||
|
||||
/**
|
||||
* Check if button should be displayed as clicked by default.
|
||||
*
|
||||
*
|
||||
* @param buttonCaption
|
||||
* button caption
|
||||
* @return true if button is clicked
|
||||
@@ -218,7 +218,7 @@ public abstract class AbstractFilterButtons extends Table {
|
||||
|
||||
/**
|
||||
* Get filter button Id.
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
@@ -226,7 +226,7 @@ public abstract class AbstractFilterButtons extends Table {
|
||||
|
||||
/**
|
||||
* Get Drop Handler for Filter Buttons.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected abstract DropHandler getFilterButtonDropHandler();
|
||||
@@ -234,14 +234,14 @@ public abstract class AbstractFilterButtons extends Table {
|
||||
/**
|
||||
* Get prefix Id of Button Wrapper to be used for drag and drop, delete and
|
||||
* test cases.
|
||||
*
|
||||
*
|
||||
* @return prefix Id of Button Wrapper
|
||||
*/
|
||||
protected abstract String getButttonWrapperIdPrefix();
|
||||
|
||||
/**
|
||||
* Get info to be set for the button wrapper.
|
||||
*
|
||||
*
|
||||
* @return button wrapper info.
|
||||
*/
|
||||
protected abstract String getButtonWrapperData();
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package org.eclipse.hawkbit.ui.common.filterlayout;
|
||||
|
||||
import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
||||
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
||||
@@ -91,7 +92,7 @@ public abstract class AbstractFilterHeader extends VerticalLayout {
|
||||
}
|
||||
|
||||
private Label createHeaderCaption() {
|
||||
return SPUIComponentProvider.getLabel(getTitle(), SPUILabelDefinitions.SP_WIDGET_CAPTION);
|
||||
return new LabelBuilder().name(getTitle()).buildCaptionLabel();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,6 +12,7 @@ import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
||||
import org.eclipse.hawkbit.ui.common.builder.WindowBuilder;
|
||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmall;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
@@ -215,11 +216,10 @@ public abstract class AbstractDeleteActionsLayout extends VerticalLayout impleme
|
||||
if (!hasUnsavedActions()) {
|
||||
return;
|
||||
}
|
||||
unsavedActionsWindow = SPUIComponentProvider.getWindow(getUnsavedActionsWindowCaption(),
|
||||
SPUIComponentIdProvider.SAVE_ACTIONS_POPUP, SPUIDefinitions.CONFIRMATION_WINDOW);
|
||||
unsavedActionsWindow = new WindowBuilder(SPUIDefinitions.CONFIRMATION_WINDOW)
|
||||
.caption(getUnsavedActionsWindowCaption()).id(SPUIComponentIdProvider.CONFIRMATION_POPUP_ID)
|
||||
.content(getUnsavedActionsWindowContent()).buildWindow();
|
||||
unsavedActionsWindow.addCloseListener(event -> unsavedActionsWindowClosed());
|
||||
unsavedActionsWindow.setContent(getUnsavedActionsWindowContent());
|
||||
unsavedActionsWindow.setId(SPUIComponentIdProvider.CONFIRMATION_POPUP_ID);
|
||||
UI.getCurrent().addWindow(unsavedActionsWindow);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,16 +8,15 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.common.grid;
|
||||
|
||||
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
|
||||
import org.eclipse.hawkbit.ui.components.SPUIButton;
|
||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.vaadin.server.FontAwesome;
|
||||
import com.vaadin.ui.AbstractTextField.TextChangeEventMode;
|
||||
import com.vaadin.ui.Alignment;
|
||||
import com.vaadin.ui.Button;
|
||||
import com.vaadin.ui.HorizontalLayout;
|
||||
@@ -61,7 +60,7 @@ public abstract class AbstractGridHeader extends VerticalLayout {
|
||||
private void createComponents() {
|
||||
headerCaptionLayout = getHeaderCaptionLayout();
|
||||
if (isRollout()) {
|
||||
searchField = createSearchField();
|
||||
searchField = new TextFieldBuilder(getSearchBoxId()).createSearchField(event -> searchBy(event.getText()));
|
||||
searchResetIcon = createSearchResetIcon();
|
||||
addButton = createAddButton();
|
||||
}
|
||||
@@ -92,7 +91,7 @@ public abstract class AbstractGridHeader extends VerticalLayout {
|
||||
addStyleName("no-border-bottom");
|
||||
}
|
||||
|
||||
private HorizontalLayout createHeaderFilterIconLayout() {
|
||||
private static HorizontalLayout createHeaderFilterIconLayout() {
|
||||
final HorizontalLayout titleFilterIconsLayout = new HorizontalLayout();
|
||||
titleFilterIconsLayout.addStyleName(SPUIStyleDefinitions.WIDGET_TITLE);
|
||||
titleFilterIconsLayout.setSpacing(false);
|
||||
@@ -101,17 +100,6 @@ public abstract class AbstractGridHeader extends VerticalLayout {
|
||||
return titleFilterIconsLayout;
|
||||
}
|
||||
|
||||
private TextField createSearchField() {
|
||||
final TextField textField = SPUIComponentProvider.getTextField("", "filter-box", "text-style filter-box-hide",
|
||||
false, "", "", false, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
||||
textField.setId(getSearchBoxId());
|
||||
textField.setWidth(100.0f, Unit.PERCENTAGE);
|
||||
textField.addTextChangeListener(event -> searchBy(event.getText()));
|
||||
textField.setTextChangeEventMode(TextChangeEventMode.LAZY);
|
||||
textField.setTextChangeTimeout(1000);
|
||||
return textField;
|
||||
}
|
||||
|
||||
private SPUIButton createSearchResetIcon() {
|
||||
final SPUIButton button = (SPUIButton) SPUIComponentProvider.getButton(getSearchRestIconId(), "", "", null,
|
||||
false, FontAwesome.SEARCH, SPUIButtonStyleSmallNoBorder.class);
|
||||
|
||||
@@ -12,20 +12,20 @@ import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
||||
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
||||
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
|
||||
import org.eclipse.hawkbit.ui.components.SPUIButton;
|
||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.vaadin.spring.events.EventBus;
|
||||
|
||||
import com.vaadin.event.dd.DropHandler;
|
||||
import com.vaadin.server.FontAwesome;
|
||||
import com.vaadin.ui.AbstractTextField.TextChangeEventMode;
|
||||
import com.vaadin.ui.Alignment;
|
||||
import com.vaadin.ui.Button;
|
||||
import com.vaadin.ui.DragAndDropWrapper;
|
||||
@@ -86,7 +86,7 @@ public abstract class AbstractTableHeader extends VerticalLayout {
|
||||
|
||||
private void createComponents() {
|
||||
headerCaption = createHeaderCaption();
|
||||
searchField = createSearchField();
|
||||
searchField = new TextFieldBuilder(getSearchBoxId()).createSearchField(event -> searchBy(event.getText()));
|
||||
|
||||
searchResetIcon = createSearchResetIcon();
|
||||
|
||||
@@ -203,21 +203,7 @@ public abstract class AbstractTableHeader extends VerticalLayout {
|
||||
}
|
||||
|
||||
private Label createHeaderCaption() {
|
||||
final Label captionLabel = SPUIComponentProvider.getLabel(getHeaderCaption(),
|
||||
SPUILabelDefinitions.SP_WIDGET_CAPTION);
|
||||
return captionLabel;
|
||||
}
|
||||
|
||||
private TextField createSearchField() {
|
||||
final TextField textField = SPUIComponentProvider.getTextField("", "filter-box", "text-style filter-box-hide",
|
||||
false, "", "", false, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
||||
textField.setId(getSearchBoxId());
|
||||
textField.setWidth(100.0f, Unit.PERCENTAGE);
|
||||
textField.addTextChangeListener(event -> searchBy(event.getText()));
|
||||
textField.setTextChangeEventMode(TextChangeEventMode.LAZY);
|
||||
// 1 seconds timeout.
|
||||
textField.setTextChangeTimeout(1000);
|
||||
return textField;
|
||||
return new LabelBuilder().name(getHeaderCaption()).buildCaptionLabel();
|
||||
}
|
||||
|
||||
private SPUIButton createSearchResetIcon() {
|
||||
@@ -322,7 +308,7 @@ public abstract class AbstractTableHeader extends VerticalLayout {
|
||||
maxMinIcon.setData(Boolean.FALSE);
|
||||
}
|
||||
|
||||
private HorizontalLayout createHeaderFilterIconLayout() {
|
||||
private static HorizontalLayout createHeaderFilterIconLayout() {
|
||||
final HorizontalLayout titleFilterIconsLayout = new HorizontalLayout();
|
||||
titleFilterIconsLayout.addStyleName(SPUIStyleDefinitions.WIDGET_TITLE);
|
||||
titleFilterIconsLayout.setSpacing(false);
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.vaadin.ui.VerticalLayout;
|
||||
|
||||
/**
|
||||
* Attributes Vertical layout for Target.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -30,10 +30,10 @@ public class SPTargetAttributesLayout {
|
||||
|
||||
/**
|
||||
* Parametric constructor.
|
||||
*
|
||||
*
|
||||
* @param controllerAttibs
|
||||
* controller attributes
|
||||
*
|
||||
*
|
||||
*/
|
||||
public SPTargetAttributesLayout(final Map<String, String> controllerAttibs) {
|
||||
targetAttributesLayout = new VerticalLayout();
|
||||
@@ -44,7 +44,7 @@ public class SPTargetAttributesLayout {
|
||||
|
||||
/**
|
||||
* Custom Decorate.
|
||||
*
|
||||
*
|
||||
* @param controllerAttibs
|
||||
*/
|
||||
private void decorate(final Map<String, String> controllerAttibs) {
|
||||
@@ -52,7 +52,7 @@ public class SPTargetAttributesLayout {
|
||||
final Label title = new Label(i18n.get("label.target.controller.attrs"), ContentMode.HTML);
|
||||
title.addStyleName(SPUIDefinitions.TEXT_STYLE);
|
||||
targetAttributesLayout.addComponent(title);
|
||||
if (HawkbitCommonUtil.mapCheckStrings(controllerAttibs)) {
|
||||
if (HawkbitCommonUtil.isNotNullOrEmpty(controllerAttibs)) {
|
||||
for (final Map.Entry<String, String> entry : controllerAttibs.entrySet()) {
|
||||
targetAttributesLayout.addComponent(
|
||||
SPUIComponentProvider.createNameValueLabel(entry.getKey() + ": ", entry.getValue()));
|
||||
@@ -62,7 +62,7 @@ public class SPTargetAttributesLayout {
|
||||
|
||||
/**
|
||||
* GET Target Attributes Layout.
|
||||
*
|
||||
*
|
||||
* @return VerticalLayout as UI
|
||||
*/
|
||||
public VerticalLayout getTargetAttributesLayout() {
|
||||
|
||||
@@ -17,11 +17,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonDecorator;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIComboBoxDecorator;
|
||||
import org.eclipse.hawkbit.ui.decorators.HeaderLayoutDecorator;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUILabelDecorator;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUITextAreaDecorator;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUITextFieldDecorator;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIWindowDecorator;
|
||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
import org.slf4j.Logger;
|
||||
@@ -34,15 +29,11 @@ import com.vaadin.shared.ui.label.ContentMode;
|
||||
import com.vaadin.ui.Button;
|
||||
import com.vaadin.ui.CheckBox;
|
||||
import com.vaadin.ui.ComboBox;
|
||||
import com.vaadin.ui.HorizontalLayout;
|
||||
import com.vaadin.ui.Label;
|
||||
import com.vaadin.ui.Link;
|
||||
import com.vaadin.ui.Panel;
|
||||
import com.vaadin.ui.TabSheet;
|
||||
import com.vaadin.ui.TextArea;
|
||||
import com.vaadin.ui.TextField;
|
||||
import com.vaadin.ui.VerticalLayout;
|
||||
import com.vaadin.ui.Window;
|
||||
import com.vaadin.ui.themes.ValoTheme;
|
||||
|
||||
/**
|
||||
@@ -61,152 +52,9 @@ public final class SPUIComponentProvider {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param className
|
||||
* @return
|
||||
*/
|
||||
public static HorizontalLayout getHorizontalLayout(final Class<? extends HorizontalLayout> className) {
|
||||
HorizontalLayout hLayout = null;
|
||||
try {
|
||||
|
||||
hLayout = className.newInstance();
|
||||
} catch (final InstantiationException exception) {
|
||||
LOG.error("Error occured while creating HorizontalLayout-" + className, exception);
|
||||
} catch (final IllegalAccessException exception) {
|
||||
LOG.error("Error occured while acessing HorizontalLayout-" + className, exception);
|
||||
}
|
||||
|
||||
return hLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get HorizontalLayout UI component.
|
||||
*
|
||||
* @param className
|
||||
* as Layout
|
||||
* @return HorizontalLayout as UI
|
||||
*/
|
||||
public static HorizontalLayout getHorizontalLayout() {
|
||||
HorizontalLayout hLayout = null;
|
||||
try {
|
||||
hLayout = HorizontalLayout.class.newInstance();
|
||||
} catch (final InstantiationException exception) {
|
||||
LOG.error("Error occured while creating HorizontalLayout-", exception);
|
||||
} catch (final IllegalAccessException exception) {
|
||||
LOG.error("Error occured while acessing HorizontalLayout-", exception);
|
||||
}
|
||||
|
||||
return hLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param tableHeaderLayoutDecorator
|
||||
* @return
|
||||
*/
|
||||
public static HorizontalLayout getHeaderLayout(
|
||||
final Class<? extends HeaderLayoutDecorator> tableHeaderLayoutDecorator) {
|
||||
// Do we really need this???
|
||||
HorizontalLayout hLayout = getHorizontalLayout(new SPUIHorizontalLayout().getUiHorizontalLayout().getClass());
|
||||
|
||||
if (tableHeaderLayoutDecorator == null) {
|
||||
return hLayout;
|
||||
}
|
||||
|
||||
try {
|
||||
final HeaderLayoutDecorator layoutDecorator = tableHeaderLayoutDecorator.newInstance();
|
||||
hLayout = layoutDecorator.decorate(hLayout);
|
||||
|
||||
} catch (final InstantiationException | IllegalAccessException exception) {
|
||||
LOG.error("Error occured while creating horizontal decorator " + HeaderLayoutDecorator.class,
|
||||
exception);
|
||||
}
|
||||
|
||||
return hLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Label UI component.
|
||||
*
|
||||
* @param name
|
||||
* label caption
|
||||
* @param type
|
||||
* string simple|Confirm|Message
|
||||
* @return Label
|
||||
*/
|
||||
public static Label getLabel(final String name, final String type) {
|
||||
return SPUILabelDecorator.getDeocratedLabel(name, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get window component.
|
||||
*
|
||||
* @param caption
|
||||
* window caption
|
||||
* @param id
|
||||
* window id
|
||||
* @param type
|
||||
* type of window
|
||||
* @return Window
|
||||
*/
|
||||
public static Window getWindow(final String caption, final String id, final String type) {
|
||||
return SPUIWindowDecorator.getDeocratedWindow(caption, id, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Label UI component.
|
||||
*
|
||||
* @param caption
|
||||
* set the caption of the textfield
|
||||
* @param style
|
||||
* set style
|
||||
* @param styleName
|
||||
* add style
|
||||
* @param required
|
||||
* to set field as mandatory
|
||||
* @param data
|
||||
* component data
|
||||
* @param prompt
|
||||
* prompt user for input
|
||||
* @param immediate
|
||||
* set component's immediate mode specified mode
|
||||
* @param maxLengthAllowed
|
||||
* maximum characters allowed
|
||||
* @return TextField text field
|
||||
*/
|
||||
public static TextField getTextField(final String caption, final String style, final String styleName,
|
||||
final boolean required, final String data, final String prompt, final boolean immediate,
|
||||
final int maxLengthAllowed) {
|
||||
return SPUITextFieldDecorator.decorate(caption, style, styleName, required, data, prompt, immediate,
|
||||
maxLengthAllowed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Label UI component. *
|
||||
*
|
||||
* @param caption
|
||||
* set the caption of the textArea
|
||||
* @param style
|
||||
* set style
|
||||
* @param styleName
|
||||
* add style
|
||||
* @param required
|
||||
* to set field as mandatory
|
||||
* @param data
|
||||
* component data
|
||||
* @param promt
|
||||
* prompt user for input
|
||||
* @param maxLength
|
||||
* maximum characters allowed
|
||||
* @return TextArea text area
|
||||
*/
|
||||
public static TextArea getTextArea(final String caption, final String style, final String styleName,
|
||||
final boolean required, final String data, final String promt, final int maxLength) {
|
||||
return SPUITextAreaDecorator.decorate(caption, style, styleName, required, data, promt, maxLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Label UI component.
|
||||
*
|
||||
* @param caption
|
||||
* caption of the combo box
|
||||
* @param height
|
||||
@@ -252,7 +100,7 @@ public final class SPUIComponentProvider {
|
||||
|
||||
/**
|
||||
* Get Button - Factory Approach for decoration.
|
||||
*
|
||||
*
|
||||
* @param id
|
||||
* as string
|
||||
* @param buttonName
|
||||
@@ -289,7 +137,7 @@ public final class SPUIComponentProvider {
|
||||
|
||||
/**
|
||||
* Get the style required.
|
||||
*
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public static String getPinButtonStyle() {
|
||||
@@ -305,7 +153,7 @@ public final class SPUIComponentProvider {
|
||||
|
||||
/**
|
||||
* Get DistributionSet Info Panel.
|
||||
*
|
||||
*
|
||||
* @param distributionSet
|
||||
* as DistributionSet
|
||||
* @param caption
|
||||
@@ -323,7 +171,7 @@ public final class SPUIComponentProvider {
|
||||
|
||||
/**
|
||||
* Method to CreateName value labels.
|
||||
*
|
||||
*
|
||||
* @param label
|
||||
* as string
|
||||
* @param values
|
||||
@@ -356,7 +204,7 @@ public final class SPUIComponentProvider {
|
||||
/**
|
||||
* Create label which represents the {@link BaseEntity#getCreatedBy()} by
|
||||
* user name
|
||||
*
|
||||
*
|
||||
* @param i18n
|
||||
* the i18n
|
||||
* @param baseEntity
|
||||
@@ -371,7 +219,7 @@ public final class SPUIComponentProvider {
|
||||
/**
|
||||
* Create label which represents the
|
||||
* {@link BaseEntity#getLastModifiedBy()()} by user name
|
||||
*
|
||||
*
|
||||
* @param i18n
|
||||
* the i18n
|
||||
* @param baseEntity
|
||||
@@ -385,7 +233,7 @@ public final class SPUIComponentProvider {
|
||||
|
||||
/**
|
||||
* Get Bold Text.
|
||||
*
|
||||
*
|
||||
* @param text
|
||||
* as String
|
||||
* @return String as bold
|
||||
@@ -396,7 +244,7 @@ public final class SPUIComponentProvider {
|
||||
|
||||
/**
|
||||
* Get the layout for Target:Controller Attributes.
|
||||
*
|
||||
*
|
||||
* @param controllerAttibs
|
||||
* as Map
|
||||
* @return VerticalLayout
|
||||
@@ -407,7 +255,7 @@ public final class SPUIComponentProvider {
|
||||
|
||||
/**
|
||||
* Get Tabsheet.
|
||||
*
|
||||
*
|
||||
* @return SPUITabSheet
|
||||
*/
|
||||
public static TabSheet getDetailsTabSheet() {
|
||||
@@ -416,7 +264,7 @@ public final class SPUIComponentProvider {
|
||||
|
||||
/**
|
||||
* Layout of tabs in detail tabsheet.
|
||||
*
|
||||
*
|
||||
* @return VerticalLayout
|
||||
*/
|
||||
public static VerticalLayout getDetailTabLayout() {
|
||||
@@ -429,7 +277,7 @@ public final class SPUIComponentProvider {
|
||||
|
||||
/**
|
||||
* Method to create a link.
|
||||
*
|
||||
*
|
||||
* @param id
|
||||
* of the link
|
||||
* @param name
|
||||
@@ -465,10 +313,10 @@ public final class SPUIComponentProvider {
|
||||
|
||||
/**
|
||||
* Generates help/documentation links from within management UI.
|
||||
*
|
||||
*
|
||||
* @param uri
|
||||
* to documentation site
|
||||
*
|
||||
*
|
||||
* @return generated link
|
||||
*/
|
||||
public static Link getHelpLink(final String uri) {
|
||||
|
||||
@@ -1,49 +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.ui.components;
|
||||
|
||||
import com.vaadin.ui.HorizontalLayout;
|
||||
|
||||
/**
|
||||
* Plain Horizontal Layout.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
public class SPUIHorizontalLayout {
|
||||
private final HorizontalLayout uiHorizontalLayout;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public SPUIHorizontalLayout() {
|
||||
uiHorizontalLayout = new HorizontalLayout();
|
||||
decorate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decorate.
|
||||
*/
|
||||
private void decorate() {
|
||||
uiHorizontalLayout.setImmediate(false);
|
||||
uiHorizontalLayout.setMargin(false);
|
||||
uiHorizontalLayout.setSpacing(true);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get HorizontalLayout.
|
||||
*
|
||||
* @return HorizontalLayout as UI
|
||||
*/
|
||||
public HorizontalLayout getUiHorizontalLayout() {
|
||||
return uiHorizontalLayout;
|
||||
}
|
||||
}
|
||||
@@ -17,21 +17,22 @@ import com.vaadin.client.renderers.ClickableRenderer.RendererClickHandler;
|
||||
import com.vaadin.shared.ui.Connect;
|
||||
|
||||
import elemental.json.JsonObject;
|
||||
|
||||
/**
|
||||
* A connector for {@link CustomObjectRenderer }.
|
||||
*
|
||||
*/
|
||||
@Connect(org.eclipse.hawkbit.ui.customrenderers.renderers.RolloutRenderer.class)
|
||||
public class RolloutRendererConnector extends ClickableRendererConnector<RolloutRendererData> {
|
||||
private static final long serialVersionUID = 7734682321931830566L;
|
||||
private static final long serialVersionUID = 7734682321931830566L;
|
||||
|
||||
public org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRenderer getRenderer() {
|
||||
return (org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRenderer) super.getRenderer();
|
||||
}
|
||||
@Override
|
||||
public org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRenderer getRenderer() {
|
||||
return (org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRenderer) super.getRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HandlerRegistration addClickHandler(
|
||||
RendererClickHandler<JsonObject> handler) {
|
||||
@Override
|
||||
protected HandlerRegistration addClickHandler(final RendererClickHandler<JsonObject> handler) {
|
||||
return getRenderer().addClickHandler(handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,52 +11,49 @@ package org.eclipse.hawkbit.ui.customrenderers.client.renderers;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* RendererData class with Name and Status.
|
||||
*
|
||||
* RendererData class with name and status.
|
||||
*/
|
||||
|
||||
public class RolloutRendererData implements Serializable {
|
||||
private static final long serialVersionUID = -5018181529953620263L;
|
||||
|
||||
private String name;
|
||||
private static final long serialVersionUID = -5018181529953620263L;
|
||||
|
||||
private String status;
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Initialize the RendererData.
|
||||
*/
|
||||
public RolloutRendererData() {
|
||||
private String status;
|
||||
|
||||
}
|
||||
/**
|
||||
* Initialize the RendererData empty.
|
||||
*/
|
||||
public RolloutRendererData() {
|
||||
// Needed by Vaadin for compiling the widget set.
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the RendererData.
|
||||
*
|
||||
* @param name
|
||||
* Name of the Rollout.
|
||||
* @param status
|
||||
* Status of Rollout.
|
||||
*/
|
||||
public RolloutRendererData(String name, String status) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.status = status;
|
||||
}
|
||||
/**
|
||||
* Initialize the RendererData.
|
||||
*
|
||||
* @param name
|
||||
* Name of the Rollout.
|
||||
* @param status
|
||||
* Status of Rollout.
|
||||
*/
|
||||
public RolloutRendererData(final String name, final String status) {
|
||||
this.name = name;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(final String status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,46 +16,44 @@ import com.vaadin.ui.renderers.ClickableRenderer;
|
||||
import elemental.json.JsonValue;
|
||||
|
||||
/**
|
||||
* Renders button with provided CustomObject.
|
||||
* Used to display button with link.
|
||||
*
|
||||
* Renders button with provided CustomObject. Used to display button with link.
|
||||
*/
|
||||
|
||||
public class RolloutRenderer extends ClickableRenderer<RolloutRendererData> {
|
||||
|
||||
private static final long serialVersionUID = -8754180585906263554L;
|
||||
private static final long serialVersionUID = -8754180585906263554L;
|
||||
|
||||
/**
|
||||
* Creates a new custom object renderer.
|
||||
*/
|
||||
public RolloutRenderer() {
|
||||
super(RolloutRendererData.class, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize custom object renderer with {@link Class<CustomObject>}
|
||||
*
|
||||
* @param presentationType
|
||||
* Class<CustomObject>
|
||||
*/
|
||||
/**
|
||||
* Creates a new custom object renderer.
|
||||
*/
|
||||
public RolloutRenderer() {
|
||||
super(RolloutRendererData.class, null);
|
||||
}
|
||||
|
||||
public RolloutRenderer(Class<RolloutRendererData> presentationType) {
|
||||
super(presentationType);
|
||||
}
|
||||
/**
|
||||
* Initialize custom object renderer with the given type.
|
||||
*
|
||||
* @param presentationType
|
||||
* Class<CustomObject>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new custom object renderer and adds the given click listener to it.
|
||||
*
|
||||
* @param listener
|
||||
* the click listener to register
|
||||
*/
|
||||
public RolloutRenderer(RendererClickListener listener) {
|
||||
this();
|
||||
addClickListener(listener);
|
||||
}
|
||||
public RolloutRenderer(final Class<RolloutRendererData> presentationType) {
|
||||
super(presentationType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonValue encode(RolloutRendererData resource) {
|
||||
return super.encode(resource, RolloutRendererData.class);
|
||||
}
|
||||
/**
|
||||
* Creates a new custom object renderer and adds the given click listener to
|
||||
* it.
|
||||
*
|
||||
* @param listener
|
||||
* the click listener to register
|
||||
*/
|
||||
public RolloutRenderer(final RendererClickListener listener) {
|
||||
this();
|
||||
addClickListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonValue encode(final RolloutRendererData resource) {
|
||||
return super.encode(resource, RolloutRendererData.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,65 +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.ui.decorators;
|
||||
|
||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
||||
|
||||
import com.vaadin.shared.ui.label.ContentMode;
|
||||
import com.vaadin.ui.Label;
|
||||
import com.vaadin.ui.themes.ValoTheme;
|
||||
|
||||
/**
|
||||
* Simple Decorator for the label.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class SPUILabelDecorator {
|
||||
|
||||
/**
|
||||
* Private Constructor.
|
||||
*/
|
||||
private SPUILabelDecorator() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple decorator.
|
||||
*
|
||||
* @param name
|
||||
* as String
|
||||
* @param type
|
||||
* as String
|
||||
* @return Label
|
||||
*/
|
||||
public static Label getDeocratedLabel(final String name, final String type) {
|
||||
final Label spUILabel = new Label(name);
|
||||
// Set style.
|
||||
final StringBuilder style = new StringBuilder(ValoTheme.LABEL_SMALL);
|
||||
style.append(' ');
|
||||
style.append(ValoTheme.LABEL_BOLD);
|
||||
spUILabel.addStyleName(style.toString());
|
||||
if (SPUILabelDefinitions.SP_WIDGET_CAPTION.equalsIgnoreCase(type)) {
|
||||
spUILabel.setValue(name);
|
||||
spUILabel.addStyleName("header-caption");
|
||||
} else if (SPUILabelDefinitions.SP_LABEL_MESSAGE.equalsIgnoreCase(type)) {
|
||||
spUILabel.setContentMode(ContentMode.HTML);
|
||||
spUILabel.addStyleName(SPUILabelDefinitions.SP_LABEL_MESSAGE_STYLE);
|
||||
} else {
|
||||
spUILabel.setImmediate(false);
|
||||
spUILabel.setWidth("-1px");
|
||||
spUILabel.setHeight("-1px");
|
||||
}
|
||||
|
||||
return spUILabel;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,81 +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.ui.decorators;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.vaadin.ui.TextArea;
|
||||
import com.vaadin.ui.themes.ValoTheme;
|
||||
|
||||
/**
|
||||
* TextArea with required style.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class SPUITextAreaDecorator {
|
||||
|
||||
/**
|
||||
* Private Constrcutor.
|
||||
*/
|
||||
private SPUITextAreaDecorator() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Decorate.
|
||||
*
|
||||
* @param style
|
||||
* set style
|
||||
* @param styleName
|
||||
* add style
|
||||
* @param required
|
||||
* to set field as mandatory
|
||||
* @param data
|
||||
* component data
|
||||
* @param prompt
|
||||
* as user for input
|
||||
* @param maxLength
|
||||
* maximum characters allowed
|
||||
* @return TextArea as comp
|
||||
*/
|
||||
public static TextArea decorate(final String caption, final String style, final String styleName,
|
||||
final boolean required, final String data, final String prompt, final int maxLength) {
|
||||
final TextArea spUITxtArea = new TextArea();
|
||||
// Default settings
|
||||
spUITxtArea.setRequired(false);
|
||||
spUITxtArea.addStyleName(ValoTheme.TEXTAREA_SMALL);
|
||||
if (StringUtils.isNotEmpty(caption)) {
|
||||
spUITxtArea.setCaption(caption);
|
||||
}
|
||||
if (required) {
|
||||
spUITxtArea.setRequired(true);
|
||||
}
|
||||
// Add style
|
||||
if (StringUtils.isNotEmpty(style)) {
|
||||
spUITxtArea.setStyleName(style);
|
||||
}
|
||||
// Add style Name
|
||||
if (StringUtils.isNotEmpty(styleName)) {
|
||||
spUITxtArea.addStyleName(styleName);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(prompt)) {
|
||||
spUITxtArea.setInputPrompt(prompt);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(data)) {
|
||||
spUITxtArea.setData(data);
|
||||
}
|
||||
|
||||
if (maxLength > 0) {
|
||||
spUITxtArea.setMaxLength(maxLength);
|
||||
}
|
||||
return spUITxtArea;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,88 +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.ui.decorators;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.vaadin.ui.TextField;
|
||||
import com.vaadin.ui.themes.ValoTheme;
|
||||
|
||||
/**
|
||||
* Decorate TextField with required style.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class SPUITextFieldDecorator {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
private SPUITextFieldDecorator() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param caption
|
||||
* set the caption of the textfield
|
||||
* @param style
|
||||
* set style
|
||||
* @param styleName
|
||||
* add style
|
||||
* @param required
|
||||
* to set field as mandatory
|
||||
* @param data
|
||||
* component data
|
||||
* @param prompt
|
||||
* prompt user for input
|
||||
* @param immediate
|
||||
* as for display
|
||||
* @param maxLengthAllowed
|
||||
* maximum characters allowed
|
||||
* @return Text field as decorated
|
||||
*/
|
||||
public static TextField decorate(final String caption, final String style, final String styleName,
|
||||
final boolean required, final String data, final String prompt, final boolean immediate,
|
||||
final int maxLengthAllowed) {
|
||||
final TextField spUITxtFld = new TextField();
|
||||
if (StringUtils.isNotEmpty(caption)) {
|
||||
spUITxtFld.setCaption(caption);
|
||||
}
|
||||
// Default settings
|
||||
spUITxtFld.setRequired(false);
|
||||
spUITxtFld.addStyleName(ValoTheme.TEXTFIELD_SMALL);
|
||||
if (required) {
|
||||
spUITxtFld.setRequired(true);
|
||||
}
|
||||
if (immediate) {
|
||||
spUITxtFld.setImmediate(true);
|
||||
}
|
||||
// Add style
|
||||
if (StringUtils.isNotEmpty(style)) {
|
||||
spUITxtFld.setStyleName(style);
|
||||
}
|
||||
// Add style Name
|
||||
if (StringUtils.isNotEmpty(styleName)) {
|
||||
spUITxtFld.addStyleName(styleName);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(prompt)) {
|
||||
spUITxtFld.setInputPrompt(prompt);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(data)) {
|
||||
spUITxtFld.setData(data);
|
||||
}
|
||||
if (maxLengthAllowed > 0) {
|
||||
spUITxtFld.setMaxLength(maxLengthAllowed);
|
||||
}
|
||||
|
||||
return spUITxtFld;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.decorators;
|
||||
|
||||
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
|
||||
import org.eclipse.hawkbit.ui.common.CustomCommonDialogWindow;
|
||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||
|
||||
import com.vaadin.ui.AbstractLayout;
|
||||
import com.vaadin.ui.Button.ClickListener;
|
||||
import com.vaadin.ui.Component;
|
||||
import com.vaadin.ui.Window;
|
||||
|
||||
/**
|
||||
* Decorator for Window.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class SPUIWindowDecorator {
|
||||
|
||||
/**
|
||||
* Private Constructor.
|
||||
*/
|
||||
private SPUIWindowDecorator() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Decorates window based on type.
|
||||
*
|
||||
* @param caption
|
||||
* window caption
|
||||
* @param id
|
||||
* window id
|
||||
* @param type
|
||||
* window type
|
||||
* @return Window
|
||||
*/
|
||||
public static CommonDialogWindow getWindow(final String caption, final String id, final String type,
|
||||
final Component content, final ClickListener saveButtonClickListener,
|
||||
final ClickListener cancelButtonClickListener, final String helpLink, final AbstractLayout layout,
|
||||
final I18N i18n) {
|
||||
CommonDialogWindow window = null;
|
||||
if (SPUIDefinitions.CUSTOM_METADATA_WINDOW.equals(type)) {
|
||||
window = new CustomCommonDialogWindow(caption, content, helpLink, saveButtonClickListener,
|
||||
cancelButtonClickListener, layout, i18n);
|
||||
window.setDraggable(true);
|
||||
window.setClosable(true);
|
||||
} else {
|
||||
window = new CommonDialogWindow(caption, content, helpLink, saveButtonClickListener,
|
||||
cancelButtonClickListener, layout, i18n);
|
||||
if (null != id) {
|
||||
window.setId(id);
|
||||
}
|
||||
if (SPUIDefinitions.CONFIRMATION_WINDOW.equals(type)) {
|
||||
window.setDraggable(false);
|
||||
window.setClosable(true);
|
||||
window.addStyleName(SPUIStyleDefinitions.CONFIRMATION_WINDOW_CAPTION);
|
||||
|
||||
} else if (SPUIDefinitions.CREATE_UPDATE_WINDOW.equals(type)) {
|
||||
window.setDraggable(true);
|
||||
window.setClosable(true);
|
||||
}
|
||||
}
|
||||
return window;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decorates window based on type.
|
||||
*
|
||||
* @param caption
|
||||
* window caption
|
||||
* @param id
|
||||
* window id
|
||||
* @param type
|
||||
* window type
|
||||
* @return Window
|
||||
*/
|
||||
public static Window getDeocratedWindow(final String caption, final String id, final String type) {
|
||||
final Window window = new Window(caption);
|
||||
window.setSizeUndefined();
|
||||
window.setModal(true);
|
||||
window.setResizable(false);
|
||||
if (null != id) {
|
||||
window.setId(id);
|
||||
}
|
||||
if (SPUIDefinitions.CONFIRMATION_WINDOW.equals(type)) {
|
||||
window.setDraggable(false);
|
||||
window.setClosable(true);
|
||||
window.addStyleName(SPUIStyleDefinitions.CONFIRMATION_WINDOW_CAPTION);
|
||||
|
||||
} else if (SPUIDefinitions.CREATE_UPDATE_WINDOW.equals(type)) {
|
||||
window.setDraggable(true);
|
||||
window.setClosable(false);
|
||||
}
|
||||
return window;
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,8 @@ import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
|
||||
import org.eclipse.hawkbit.ui.common.DistributionSetTypeBeanQuery;
|
||||
import org.eclipse.hawkbit.ui.common.builder.TextAreaBuilder;
|
||||
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
|
||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||
import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTypeEvent;
|
||||
@@ -45,6 +47,7 @@ import com.vaadin.ui.CheckBox;
|
||||
import com.vaadin.ui.Component;
|
||||
import com.vaadin.ui.HorizontalLayout;
|
||||
import com.vaadin.ui.Table;
|
||||
import com.vaadin.ui.TextField;
|
||||
import com.vaadin.ui.VerticalLayout;
|
||||
import com.vaadin.ui.themes.ValoTheme;
|
||||
|
||||
@@ -84,24 +87,24 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout {
|
||||
|
||||
super.createRequiredComponents();
|
||||
|
||||
tagName = SPUIComponentProvider.getTextField(i18n.get("textfield.name"), "",
|
||||
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.DIST_SET_TYPE_NAME, true, "",
|
||||
i18n.get("textfield.name"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
||||
tagName.setId(SPUIDefinitions.NEW_DISTRIBUTION_TYPE_NAME);
|
||||
tagName = createTextField("textfield.name", SPUIDefinitions.DIST_SET_TYPE_NAME,
|
||||
SPUIDefinitions.NEW_DISTRIBUTION_TYPE_NAME);
|
||||
|
||||
typeKey = SPUIComponentProvider.getTextField(i18n.get("textfield.key"), "",
|
||||
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.DIST_SET_TYPE_KEY, true, "", i18n.get("textfield.key"),
|
||||
true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
||||
typeKey.setId(SPUIDefinitions.NEW_DISTRIBUTION_TYPE_KEY);
|
||||
typeKey = createTextField("textfield.key", SPUIDefinitions.DIST_SET_TYPE_KEY,
|
||||
SPUIDefinitions.NEW_DISTRIBUTION_TYPE_KEY);
|
||||
|
||||
tagDesc = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "",
|
||||
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.DIST_SET_TYPE_DESC, false, "",
|
||||
i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
|
||||
tagDesc.setId(SPUIDefinitions.NEW_DISTRIBUTION_TYPE_DESC);
|
||||
tagDesc.setImmediate(true);
|
||||
tagDesc = new TextAreaBuilder().caption(i18n.get("textfield.description"))
|
||||
.styleName(ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.DIST_SET_TYPE_DESC)
|
||||
.prompt(i18n.get("textfield.description")).immediate(true)
|
||||
.id(SPUIDefinitions.NEW_DISTRIBUTION_TYPE_DESC).buildTextComponent();
|
||||
tagDesc.setNullRepresentation("");
|
||||
}
|
||||
|
||||
private TextField createTextField(final String in18Key, final String styleName, final String id) {
|
||||
return new TextFieldBuilder().caption(i18n.get(in18Key)).styleName(ValoTheme.TEXTFIELD_TINY + " " + styleName)
|
||||
.required(true).prompt(i18n.get(in18Key)).immediate(true).id(id).buildTextComponent();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildLayout() {
|
||||
|
||||
|
||||
@@ -117,5 +117,4 @@ public class DSTypeFilterButtons extends AbstractFilterButtons {
|
||||
private void refreshTypeTable() {
|
||||
setContainerDataSource(createButtonsLazyQueryContainer());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.EntityFactory;
|
||||
import org.eclipse.hawkbit.repository.SoftwareManagement;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleIdName;
|
||||
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
|
||||
@@ -29,7 +28,6 @@ import org.eclipse.hawkbit.ui.common.detailslayout.SoftwareModuleDetailsTable;
|
||||
import org.eclipse.hawkbit.ui.common.tagdetails.DistributionTagToken;
|
||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||
import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent;
|
||||
import org.eclipse.hawkbit.ui.distributions.event.SaveActionWindowEvent;
|
||||
import org.eclipse.hawkbit.ui.distributions.event.SoftwareModuleAssignmentDiscardEvent;
|
||||
import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState;
|
||||
@@ -97,21 +95,6 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet
|
||||
|
||||
private final Map<String, StringBuilder> assignedSWModule = new HashMap<>();
|
||||
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
void onEvent(final MetadataEvent event) {
|
||||
UI.getCurrent().access(() -> {
|
||||
final DistributionSetMetadata dsMetadata = event.getDistributionSetMetadata();
|
||||
if (dsMetadata != null && isDistributionSetSelected(dsMetadata.getDistributionSet())) {
|
||||
if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.CREATE_DISTRIBUTION_SET_METADATA) {
|
||||
dsMetadataTable.createMetadata(event.getDistributionSetMetadata().getKey());
|
||||
} else if (event
|
||||
.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.DELETE_DISTRIBUTION_SET_METADATA) {
|
||||
dsMetadataTable.deleteMetadata(event.getDistributionSetMetadata().getKey());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* softwareLayout Initialize the component.
|
||||
*/
|
||||
|
||||
@@ -21,6 +21,9 @@ import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.SoftwareManagement;
|
||||
import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetUpdateEvent;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleIdName;
|
||||
@@ -119,6 +122,33 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
|
||||
}
|
||||
}
|
||||
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
void onEvents(final DistributionSetUpdateEvent event) {
|
||||
final DistributionSet ds = event.getEntity();
|
||||
final DistributionSetIdName lastSelectedDsIdName = manageDistUIState.getLastSelectedDistribution().isPresent()
|
||||
? manageDistUIState.getLastSelectedDistribution().get() : null;
|
||||
final List<DistributionSetIdName> visibleItemIds = (List<DistributionSetIdName>) getVisibleItemIds();
|
||||
|
||||
// refresh the details tabs only if selected ds is updated
|
||||
if (lastSelectedDsIdName != null && lastSelectedDsIdName.getId().equals(ds.getId())) {
|
||||
// update table row+details layout
|
||||
eventBus.publish(this, new DistributionTableEvent(BaseEntityEventType.SELECTED_ENTITY, ds));
|
||||
} else if (visibleItemIds.stream().filter(e -> e.getId().equals(ds.getId())).findFirst().isPresent()) {
|
||||
// update the name/version details visible in table
|
||||
UI.getCurrent().access(() -> updateDistributionInTable(event.getEntity()));
|
||||
}
|
||||
}
|
||||
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
void onEvents(final List<?> events) {
|
||||
final Object firstEvent = events.get(0);
|
||||
if (DistributionCreatedEvent.class.isInstance(firstEvent)) {
|
||||
refreshDistributions();
|
||||
} else if (DistributionDeletedEvent.class.isInstance(firstEvent)) {
|
||||
onDistributionDeleteEvent((List<DistributionDeletedEvent>) events);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTableId() {
|
||||
return SPUIComponentIdProvider.DIST_TABLE_ID;
|
||||
@@ -414,6 +444,10 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
void onEvent(final DistributionTableEvent event) {
|
||||
onBaseEntityEvent(event);
|
||||
if (BaseEntityEventType.UPDATED_ENTITY != event.getEventType()) {
|
||||
return;
|
||||
}
|
||||
UI.getCurrent().access(() -> updateDistributionInTable(event.getEntity()));
|
||||
}
|
||||
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
@@ -459,6 +493,7 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
|
||||
@Override
|
||||
protected void setDataAvailable(final boolean available) {
|
||||
manageDistUIState.setNoDataAvailableDist(!available);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -495,7 +530,7 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
|
||||
return manageMetadataBtn;
|
||||
}
|
||||
|
||||
private void showMetadataDetails(final Long itemId) {
|
||||
private void showMetadataDetails(final Long itemId) {
|
||||
final DistributionSet ds = distributionSetManagement.findDistributionSetByIdWithDetails(itemId);
|
||||
UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(ds, null));
|
||||
}
|
||||
@@ -507,4 +542,73 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
|
||||
return name + "." + version;
|
||||
}
|
||||
|
||||
private void refreshDistributions() {
|
||||
final LazyQueryContainer dsContainer = (LazyQueryContainer) getContainerDataSource();
|
||||
final int size = dsContainer.size();
|
||||
if (size < SPUIDefinitions.MAX_TABLE_ENTRIES) {
|
||||
refreshTablecontainer();
|
||||
}
|
||||
if (size != 0) {
|
||||
setData(SPUIDefinitions.DATA_AVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshTablecontainer() {
|
||||
final LazyQueryContainer dsContainer = (LazyQueryContainer) getContainerDataSource();
|
||||
dsContainer.refresh();
|
||||
selectRow();
|
||||
}
|
||||
|
||||
private void updateDistributionInTable(final DistributionSet editedDs) {
|
||||
final Item item = getContainerDataSource()
|
||||
.getItem(new DistributionSetIdName(editedDs.getId(), editedDs.getName(), editedDs.getVersion()));
|
||||
updateEntity(editedDs, item);
|
||||
}
|
||||
|
||||
private void onDistributionDeleteEvent(final List<DistributionDeletedEvent> events) {
|
||||
final LazyQueryContainer dsContainer = (LazyQueryContainer) getContainerDataSource();
|
||||
final List<Object> visibleItemIds = (List<Object>) getVisibleItemIds();
|
||||
boolean shouldRefreshDs = false;
|
||||
for (final DistributionDeletedEvent deletedEvent : events) {
|
||||
final Long distributionSetId = deletedEvent.getDistributionSetId();
|
||||
final DistributionSetIdName targetIdName = new DistributionSetIdName(distributionSetId, null, null);
|
||||
if (visibleItemIds.contains(targetIdName)) {
|
||||
dsContainer.removeItem(targetIdName);
|
||||
} else {
|
||||
shouldRefreshDs = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldRefreshDs) {
|
||||
refreshOnDelete();
|
||||
} else {
|
||||
dsContainer.commit();
|
||||
}
|
||||
reSelectItemsAfterDeletionEvent();
|
||||
}
|
||||
|
||||
private void refreshOnDelete() {
|
||||
final LazyQueryContainer dsContainer = (LazyQueryContainer) getContainerDataSource();
|
||||
final int size = dsContainer.size();
|
||||
refreshTablecontainer();
|
||||
if (size != 0) {
|
||||
setData(SPUIDefinitions.DATA_AVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void reSelectItemsAfterDeletionEvent() {
|
||||
Set<Object> values = new HashSet<>();
|
||||
if (isMultiSelect()) {
|
||||
values = new HashSet<>((Set<?>) getValue());
|
||||
} else {
|
||||
values.add(getValue());
|
||||
}
|
||||
setValue(null);
|
||||
|
||||
for (final Object value : values) {
|
||||
if (getVisibleItemIds().contains(value)) {
|
||||
select(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@ import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.ui.common.AbstractMetadataPopupLayout;
|
||||
import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent;
|
||||
import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent.MetadataUIEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.vaadin.spring.annotation.SpringComponent;
|
||||
@@ -55,7 +53,6 @@ public class DsMetadataPopupLayout extends AbstractMetadataPopupLayout<Distribut
|
||||
final DistributionSetMetadata dsMetaData = distributionSetManagement
|
||||
.createDistributionSetMetadata(entityFactory.generateDistributionSetMetadata(entity, key, value));
|
||||
setSelectedEntity(dsMetaData.getDistributionSet());
|
||||
eventBus.publish(this, new MetadataEvent(MetadataUIEvent.CREATE_DISTRIBUTION_SET_METADATA, dsMetaData));
|
||||
return dsMetaData;
|
||||
}
|
||||
|
||||
@@ -84,7 +81,6 @@ public class DsMetadataPopupLayout extends AbstractMetadataPopupLayout<Distribut
|
||||
protected void deleteMetadata(final DistributionSet entity, final String key, final String value) {
|
||||
final DistributionSetMetadata dsMetaData = entityFactory.generateDistributionSetMetadata(entity, key, value);
|
||||
distributionSetManagement.deleteDistributionSetMetadata(entity, key);
|
||||
eventBus.publish(this, new MetadataEvent(MetadataUIEvent.DELETE_DISTRIBUTION_SET_METADATA, dsMetaData));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -42,7 +42,7 @@ import com.google.common.base.Strings;
|
||||
public class ManageDistBeanQuery extends AbstractBeanQuery<ProxyDistribution> {
|
||||
|
||||
private static final long serialVersionUID = 5176481314404662215L;
|
||||
private Sort sort = new Sort(Direction.ASC, "name", "version");
|
||||
private Sort sort = new Sort(Direction.ASC, "createdAt");
|
||||
private String searchText = null;
|
||||
private transient DistributionSetManagement distributionSetManagement;
|
||||
private transient Page<DistributionSet> firstPageDistributionSets = null;
|
||||
@@ -50,7 +50,7 @@ public class ManageDistBeanQuery extends AbstractBeanQuery<ProxyDistribution> {
|
||||
private DistributionSetType distributionSetType = null;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param definition
|
||||
* @param queryConfig
|
||||
* @param sortPropertyIds
|
||||
@@ -60,7 +60,7 @@ public class ManageDistBeanQuery extends AbstractBeanQuery<ProxyDistribution> {
|
||||
final Object[] sortPropertyIds, final boolean[] sortStates) {
|
||||
super(definition, queryConfig, sortPropertyIds, sortStates);
|
||||
|
||||
if (HawkbitCommonUtil.mapCheckStrKey(queryConfig)) {
|
||||
if (HawkbitCommonUtil.isNotNullOrEmpty(queryConfig)) {
|
||||
searchText = (String) queryConfig.get(SPUIDefinitions.FILTER_BY_TEXT);
|
||||
if (!Strings.isNullOrEmpty(searchText)) {
|
||||
searchText = String.format("%%%s%%", searchText);
|
||||
|
||||
@@ -10,6 +10,7 @@ package org.eclipse.hawkbit.ui.distributions.event;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
|
||||
|
||||
/**
|
||||
*
|
||||
* Metadata Events.
|
||||
@@ -18,21 +19,21 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
|
||||
public class MetadataEvent {
|
||||
|
||||
public enum MetadataUIEvent {
|
||||
CREATE_DISTRIBUTION_SET_METADATA, DELETE_DISTRIBUTION_SET_METADATA, DELETE_SOFTWARE_MODULE_METADATA, CREATE_SOFTWARE_MODULE_METADATA;
|
||||
DELETE_SOFTWARE_MODULE_METADATA, CREATE_SOFTWARE_MODULE_METADATA;
|
||||
}
|
||||
|
||||
private MetadataUIEvent metadataUIEvent;
|
||||
private final MetadataUIEvent metadataUIEvent;
|
||||
|
||||
private DistributionSetMetadata distributionSetMetadata;
|
||||
|
||||
private SoftwareModuleMetadata softwareModuleMetadata;
|
||||
|
||||
public MetadataEvent(MetadataUIEvent metadataUIEvent, final DistributionSetMetadata distributionSetMetadata) {
|
||||
public MetadataEvent(final MetadataUIEvent metadataUIEvent, final DistributionSetMetadata distributionSetMetadata) {
|
||||
this.metadataUIEvent = metadataUIEvent;
|
||||
this.distributionSetMetadata = distributionSetMetadata;
|
||||
}
|
||||
|
||||
public MetadataEvent(MetadataUIEvent metadataUIEvent, final SoftwareModuleMetadata softwareModuleMetadata) {
|
||||
public MetadataEvent(final MetadataUIEvent metadataUIEvent, final SoftwareModuleMetadata softwareModuleMetadata) {
|
||||
this.metadataUIEvent = metadataUIEvent;
|
||||
this.softwareModuleMetadata = softwareModuleMetadata;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user