Merge branch 'master' into feature_ui_metadata

Conflicts:
	hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/CommonDialogWindow.java
	hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetDetails.java
	hawkbit-ui/src/main/resources/messages_en.properties
	
Resolved the conflicts.
This commit is contained in:
gah6kor
2016-07-15 14:40:55 +02:00
83 changed files with 2020 additions and 1717 deletions

View File

@@ -10,8 +10,6 @@ package org.eclipse.hawkbit.simulator;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.security.DigestOutputStream; import java.security.DigestOutputStream;
import java.security.KeyManagementException; import java.security.KeyManagementException;
@@ -34,6 +32,7 @@ import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.client.HttpClients;
import org.eclipse.hawkbit.dmf.json.model.Artifact; import org.eclipse.hawkbit.dmf.json.model.Artifact;
import org.eclipse.hawkbit.dmf.json.model.Artifact.UrlProtocol;
import org.eclipse.hawkbit.dmf.json.model.SoftwareModule; import org.eclipse.hawkbit.dmf.json.model.SoftwareModule;
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol; import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus; import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus;
@@ -59,7 +58,7 @@ import com.google.common.io.ByteStreams;
public class DeviceSimulatorUpdater { public class DeviceSimulatorUpdater {
private static final Logger LOGGER = LoggerFactory.getLogger(DeviceSimulatorUpdater.class); private static final Logger LOGGER = LoggerFactory.getLogger(DeviceSimulatorUpdater.class);
private static final ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(4); private static final ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(8);
@Autowired @Autowired
private SpSenderService spSenderService; private SpSenderService spSenderService;
@@ -99,7 +98,8 @@ public class DeviceSimulatorUpdater {
// plug and play - non existing device will be auto created // plug and play - non existing device will be auto created
if (device == null) { if (device == null) {
device = repository.add(deviceFactory.createSimulatedDevice(id, tenant, Protocol.DMF_AMQP, -1, null, null)); device = repository
.add(deviceFactory.createSimulatedDevice(id, tenant, Protocol.DMF_AMQP, 1800, null, null));
} }
device.setProgress(0.0); device.setProgress(0.0);
@@ -197,18 +197,14 @@ public class DeviceSimulatorUpdater {
private static void handleArtifacts(final String targetToken, final List<UpdateStatus> status, private static void handleArtifacts(final String targetToken, final List<UpdateStatus> status,
final Artifact artifact) { final Artifact artifact) {
artifact.getUrls().entrySet().forEach(entry -> {
switch (entry.getKey()) { if (artifact.getUrls().containsKey(UrlProtocol.HTTPS)) {
case HTTP: status.add(downloadUrl(artifact.getUrls().get(UrlProtocol.HTTPS), targetToken,
case HTTPS: artifact.getHashes().getSha1(), artifact.getSize()));
status.add(downloadUrl(entry.getValue(), targetToken, artifact.getHashes().getSha1(), } else if (artifact.getUrls().containsKey(UrlProtocol.HTTP)) {
artifact.getSize())); status.add(downloadUrl(artifact.getUrls().get(UrlProtocol.HTTP), targetToken,
break; artifact.getHashes().getSha1(), artifact.getSize()));
default: }
// not supported yet
break;
}
});
} }
private static UpdateStatus downloadUrl(final String url, final String targetToken, final String sha1Hash, private static UpdateStatus downloadUrl(final String url, final String targetToken, final String sha1Hash,
@@ -235,22 +231,15 @@ public class DeviceSimulatorUpdater {
return new UpdateStatus(ResponseStatus.ERROR, message); return new UpdateStatus(ResponseStatus.ERROR, message);
} }
final File tempFile = File.createTempFile("uploadFile", null);
// Exception squid:S2070 - not used for hashing sensitive // Exception squid:S2070 - not used for hashing sensitive
// data // data
@SuppressWarnings("squid:S2070") @SuppressWarnings("squid:S2070")
final MessageDigest md = MessageDigest.getInstance("SHA-1"); final MessageDigest md = MessageDigest.getInstance("SHA-1");
try (final DigestOutputStream dos = new DigestOutputStream(new FileOutputStream(tempFile), md)) { try (final BufferedOutputStream bdos = new BufferedOutputStream(
try (final BufferedOutputStream bdos = new BufferedOutputStream(dos)) { new DigestOutputStream(ByteStreams.nullOutputStream(), md))) {
try (BufferedInputStream bis = new BufferedInputStream(response.getEntity().getContent())) { try (BufferedInputStream bis = new BufferedInputStream(response.getEntity().getContent())) {
overallread = ByteStreams.copy(bis, bdos); overallread = ByteStreams.copy(bis, bdos);
}
}
} finally {
if (tempFile != null && !tempFile.delete()) {
LOGGER.error("Could not delete temporary file: {}", tempFile);
} }
} }

View File

@@ -45,7 +45,7 @@ public class SimulatedDeviceFactory {
*/ */
public AbstractSimulatedDevice createSimulatedDevice(final String id, final String tenant, public AbstractSimulatedDevice createSimulatedDevice(final String id, final String tenant,
final Protocol protocol) { final Protocol protocol) {
return createSimulatedDevice(id, tenant, protocol, 30, null, null); return createSimulatedDevice(id, tenant, protocol, 1800, null, null);
} }
/** /**

View File

@@ -86,10 +86,6 @@ public class SimulationController {
final String deviceId = name + i; final String deviceId = name + i;
repository.add(deviceFactory.createSimulatedDevice(deviceId, tenant, protocol, pollDelay, new URL(endpoint), repository.add(deviceFactory.createSimulatedDevice(deviceId, tenant, protocol, pollDelay, new URL(endpoint),
gatewayToken)); gatewayToken));
if (protocol == Protocol.DMF_AMQP) {
spSenderService.createOrUpdateThing(tenant, deviceId);
}
} }
return ResponseEntity.ok("Updated " + amount + " DMF connected targets!"); return ResponseEntity.ok("Updated " + amount + " DMF connected targets!");

View File

@@ -11,7 +11,6 @@ package org.eclipse.hawkbit.simulator;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
import org.eclipse.hawkbit.simulator.amqp.SpSenderService; import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -54,10 +53,6 @@ public class SimulatorStartup implements ApplicationListener<ContextRefreshedEve
} catch (final MalformedURLException e) { } catch (final MalformedURLException e) {
LOGGER.error("Creation of simulated device at startup failed.", e); LOGGER.error("Creation of simulated device at startup failed.", e);
} }
if (autostart.getApi() == Protocol.DMF_AMQP) {
spSenderService.createOrUpdateThing(autostart.getTenant(), deviceId);
}
} }
}); });
} }

View File

@@ -122,8 +122,8 @@ public class AmqpConfiguration {
final Map<String, Object> arguments = getDeadLetterExchangeArgs(); final Map<String, Object> arguments = getDeadLetterExchangeArgs();
arguments.putAll(getTTLMaxArgs()); arguments.putAll(getTTLMaxArgs());
return QueueBuilder.nonDurable(amqpProperties.getReceiverConnectorQueueFromSp()).withArguments(arguments) return QueueBuilder.nonDurable(amqpProperties.getReceiverConnectorQueueFromSp()).autoDelete()
.build(); .withArguments(arguments).build();
} }
/** /**
@@ -133,12 +133,12 @@ public class AmqpConfiguration {
*/ */
@Bean @Bean
public FanoutExchange exchangeQueueToConnector() { public FanoutExchange exchangeQueueToConnector() {
return new FanoutExchange(amqpProperties.getSenderForSpExchange()); return new FanoutExchange(amqpProperties.getSenderForSpExchange(), false, true);
} }
/** /**
* Create the Binding * Create the Binding
* {@link AmqpConfiguration#receiverConnectorQueueFromSp()} to * {@link AmqpConfiguration#receiverConnectorQueueFromHawkBit()} to
* {@link AmqpConfiguration#exchangeQueueToConnector()}. * {@link AmqpConfiguration#exchangeQueueToConnector()}.
* *
* @return the binding and create the queue and exchange * @return the binding and create the queue and exchange
@@ -165,7 +165,7 @@ public class AmqpConfiguration {
*/ */
@Bean @Bean
public FanoutExchange exchangeDeadLetter() { public FanoutExchange exchangeDeadLetter() {
return new FanoutExchange(amqpProperties.getDeadLetterExchange()); return new FanoutExchange(amqpProperties.getDeadLetterExchange(), false, true);
} }
/** /**

View File

@@ -32,6 +32,11 @@ public class AsyncConfigurerThreadpoolProperties {
*/ */
private Integer maxthreads = 20; private Integer maxthreads = 20;
/**
* Core processing threads for scheduled event executor.
*/
private Integer schedulerThreads = 3;
/** /**
* When the number of threads is greater than the core, this is the maximum * When the number of threads is greater than the core, this is the maximum
* time that excess idle threads will wait for new tasks before terminating. * time that excess idle threads will wait for new tasks before terminating.
@@ -70,4 +75,12 @@ public class AsyncConfigurerThreadpoolProperties {
this.idletimeout = idletimeout; this.idletimeout = idletimeout;
} }
public Integer getSchedulerThreads() {
return schedulerThreads;
}
public void setSchedulerThreads(final Integer schedulerThreads) {
this.schedulerThreads = schedulerThreads;
}
} }

View File

@@ -11,6 +11,8 @@ package org.eclipse.hawkbit.autoconfigure.scheduling;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy; import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
@@ -24,9 +26,12 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor; import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor; import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler;
import org.springframework.security.concurrent.DelegatingSecurityContextExecutor; import org.springframework.security.concurrent.DelegatingSecurityContextExecutor;
import org.springframework.security.concurrent.DelegatingSecurityContextExecutorService;
import org.springframework.security.concurrent.DelegatingSecurityContextScheduledExecutorService;
import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.common.util.concurrent.ThreadFactoryBuilder;
@@ -45,20 +50,28 @@ public class ExecutorAutoConfiguration {
/** /**
* @return ExecutorService with security context availability in thread * @return ExecutorService with security context availability in thread
* execution.. * execution.
*/
@Bean(destroyMethod = "shutdown")
@ConditionalOnMissingBean
public ExecutorService asyncExecutor() {
return new DelegatingSecurityContextExecutorService(threadPoolExecutor());
}
/**
* @return {@link TaskExecutor} for task execution
*/ */
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public Executor asyncExecutor() { public TaskExecutor taskExecutor() {
return new DelegatingSecurityContextExecutor(threadPoolExecutor()); return new ConcurrentTaskExecutor(asyncExecutor());
} }
/** /**
* @return central ThreadPoolExecutor for general purpose multi threaded * @return central ThreadPoolExecutor for general purpose multi threaded
* operations. Tries an orderly shutdown when destroyed. * operations. Tries an orderly shutdown when destroyed.
*/ */
@Bean(destroyMethod = "shutdown") private ThreadPoolExecutor threadPoolExecutor() {
public ThreadPoolExecutor threadPoolExecutor() {
final BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>( final BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>(
asyncConfigurerProperties.getQueuesize()); asyncConfigurerProperties.getQueuesize());
return new ThreadPoolExecutor(asyncConfigurerProperties.getCorethreads(), return new ThreadPoolExecutor(asyncConfigurerProperties.getCorethreads(),
@@ -92,31 +105,24 @@ public class ExecutorAutoConfiguration {
} }
/** /**
* @return {@link TaskExecutor} for task execution * @return {@link ScheduledExecutorService} with security context
* availability in thread execution.
*/ */
@Bean @Bean(destroyMethod = "shutdown")
@ConditionalOnMissingBean
public TaskExecutor taskExecutor() {
return new ConcurrentTaskExecutor(asyncExecutor());
}
/**
* @return {@link ScheduledExecutorService} based on
* {@link #threadPoolTaskScheduler()}.
*/
@Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public ScheduledExecutorService scheduledExecutorService() { public ScheduledExecutorService scheduledExecutorService() {
return threadPoolTaskScheduler().getScheduledExecutor(); return new DelegatingSecurityContextScheduledExecutorService(
Executors.newScheduledThreadPool(asyncConfigurerProperties.getSchedulerThreads(),
new ThreadFactoryBuilder().setNameFormat("central-scheduled-executor-pool-%d").build()));
} }
/** /**
* @return {@link ThreadPoolTaskScheduler} for scheduled operations. * @return {@link TaskScheduler} for task execution
*/ */
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() { public TaskScheduler taskScheduler() {
return new ThreadPoolTaskScheduler(); return new ConcurrentTaskScheduler(scheduledExecutorService());
} }
} }

View File

@@ -42,3 +42,4 @@ hawkbit.controller.minPollingTime=00:00:30
hawkbit.dmf.rabbitmq.deadLetterQueue=dmf_connector_deadletter_ttl hawkbit.dmf.rabbitmq.deadLetterQueue=dmf_connector_deadletter_ttl
hawkbit.dmf.rabbitmq.deadLetterExchange=dmf.connector.deadletter hawkbit.dmf.rabbitmq.deadLetterExchange=dmf.connector.deadletter
hawkbit.dmf.rabbitmq.receiverQueue=dmf_receiver hawkbit.dmf.rabbitmq.receiverQueue=dmf_receiver
hawkbit.dmf.rabbitmq.authenticationReceiverQueue=authentication_receiver

View File

@@ -87,10 +87,6 @@ public enum SpServerError {
*/ */
SP_DS_CREATION_FAILED_MISSING_MODULE("hawkbit.server.error.distributionset.creationFailed.missingModule", "Creation if Distribution Set failed as module is missing that is configured as mandatory."), SP_DS_CREATION_FAILED_MISSING_MODULE("hawkbit.server.error.distributionset.creationFailed.missingModule", "Creation if Distribution Set failed as module is missing that is configured as mandatory."),
/**
*
*/
SP_ARTIFACT_UPLOAD_FILE_LIMIT_EXCEEDED("hawkbit.server.error.artifact.uploadFailed.sizelimitexceeded", "Upload of artifact failed as the file exceeds its maximum permitted size"),
/** /**
* *
*/ */

View File

@@ -81,7 +81,7 @@ public final class DataConversionHelper {
final List<DdiArtifact> files = new ArrayList<>(); final List<DdiArtifact> files = new ArrayList<>();
module.getLocalArtifacts() module.getLocalArtifacts()
.forEach(artifact -> files.add(createArtifact(targetid, artifactUrlHandler, artifact))); .forEach(artifact -> files.add(createArtifact(targetid, artifactUrlHandler, artifact)));
return files; return files;
} }
@@ -125,7 +125,7 @@ public final class DataConversionHelper {
// response because of eTags. // response because of eTags.
result.add(linkTo(methodOn(DdiRootController.class, tenantAware.getCurrentTenant()) result.add(linkTo(methodOn(DdiRootController.class, tenantAware.getCurrentTenant())
.getControllerBasedeploymentAction(target.getControllerId(), action.getId(), .getControllerBasedeploymentAction(target.getControllerId(), action.getId(),
actions.hashCode())).withRel(DdiRestConstants.DEPLOYMENT_BASE_ACTION)); calculateEtag(action))).withRel(DdiRestConstants.DEPLOYMENT_BASE_ACTION));
addedUpdate = true; addedUpdate = true;
} else if (action.isCancelingOrCanceled() && !addedCancel) { } else if (action.isCancelingOrCanceled() && !addedCancel) {
result.add(linkTo(methodOn(DdiRootController.class, tenantAware.getCurrentTenant()) result.add(linkTo(methodOn(DdiRootController.class, tenantAware.getCurrentTenant())
@@ -142,6 +142,22 @@ public final class DataConversionHelper {
return result; return result;
} }
/**
* Calculates an etag for the given {@link Action} based on the entities
* hashcode and the {@link Action#isHitAutoForceTime(long)} to reflect a
* force switch.
*
* @param action
* to calculate the etag for
* @return the etag
*/
private static int calculateEtag(final Action action) {
final int prime = 31;
int result = action.hashCode();
result = prime * result + (action.isHitAutoForceTime(System.currentTimeMillis()) ? 1231 : 1237);
return result;
}
static void writeMD5FileResponse(final String fileName, final HttpServletResponse response, static void writeMD5FileResponse(final String fileName, final HttpServletResponse response,
final LocalArtifact artifact) throws IOException { final LocalArtifact artifact) throws IOException {
final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();

View File

@@ -23,15 +23,17 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.RandomUtils; import org.apache.commons.lang3.RandomUtils;
import org.eclipse.hawkbit.repository.DistributionSetAssignmentResult;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.RepositoryModelConstants;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.LocalArtifact; import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.RepositoryModelConstants;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB; import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB;
@@ -43,6 +45,9 @@ import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.Direction;
import org.springframework.hateoas.MediaTypes; import org.springframework.hateoas.MediaTypes;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MvcResult;
import com.jayway.jsonpath.JsonPath;
import ru.yandex.qatools.allure.annotations.Description; import ru.yandex.qatools.allure.annotations.Description;
import ru.yandex.qatools.allure.annotations.Features; import ru.yandex.qatools.allure.annotations.Features;
@@ -229,6 +234,45 @@ public class DdiDeploymentBaseTest extends AbstractRestIntegrationTestWithMongoD
assertThat(actionStatusMessage.getStatus()).isEqualTo(Status.RETRIEVED); assertThat(actionStatusMessage.getStatus()).isEqualTo(Status.RETRIEVED);
} }
@Test
@Description("Checks that the deployementBase URL changes when the action is switched from soft to forced in TIMEFORCED case.")
public void changeEtagIfActionSwitchesFromSoftToForced() throws Exception {
// Prepare test data
final Target target = targetManagement.createTarget(entityFactory.generateTarget("4712"));
final DistributionSet ds = testdataFactory.createDistributionSet("", true);
final DistributionSetAssignmentResult result = deploymentManagement.assignDistributionSet(ds.getId(),
ActionType.TIMEFORCED, System.currentTimeMillis() + 1_000, target.getControllerId());
final Action action = deploymentManagement.findActiveActionsByTarget(result.getAssignedEntity().get(0)).get(0);
MvcResult mvcResult = mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)).andReturn();
final String urlBeforeSwitch = JsonPath.compile("_links.deploymentBase.href")
.read(mvcResult.getResponse().getContentAsString()).toString();
// Time is not yet over, so we should see the same URL
mvcResult = mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)).andReturn();
assertThat(JsonPath.compile("_links.deploymentBase.href").read(mvcResult.getResponse().getContentAsString())
.toString()).isEqualTo(urlBeforeSwitch)
.startsWith("http://localhost/" + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/deploymentBase/" + action.getId());
// After the time is over we should see a new etag
TimeUnit.MILLISECONDS.sleep(1_000);
mvcResult = mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)).andReturn();
assertThat(JsonPath.compile("_links.deploymentBase.href").read(mvcResult.getResponse().getContentAsString())
.toString()).isNotEqualTo(urlBeforeSwitch);
}
@Test @Test
@Description("Attempt/soft deployment to a controller. Checks if the resource reponse payload for a given deployment is as expected.") @Description("Attempt/soft deployment to a controller. Checks if the resource reponse payload for a given deployment is as expected.")
public void deplomentAttemptAction() throws Exception { public void deplomentAttemptAction() throws Exception {

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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
-->
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<!-- <Logger name="org.eclipse.hawkbit.rest.util.MockMvcResultPrinter" level="DEBUG" /> -->
<Root level="INFO">
<AppenderRef ref="Console" />
</Root>
</configuration>

View File

@@ -8,8 +8,11 @@
*/ */
package org.eclipse.hawkbit.amqp; package org.eclipse.hawkbit.amqp;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import org.eclipse.hawkbit.dmf.amqp.api.AmqpSettings; import org.eclipse.hawkbit.dmf.amqp.api.AmqpSettings;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -18,11 +21,12 @@ import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder; import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange; import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue; import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory; import org.springframework.amqp.core.QueueBuilder;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin; import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -51,10 +55,6 @@ public class AmqpConfiguration {
@Autowired @Autowired
private AmqpDeadletterProperties amqpDeadletterProperties; private AmqpDeadletterProperties amqpDeadletterProperties;
@Autowired
@Qualifier("threadPoolExecutor")
private ThreadPoolExecutor threadPoolExecutor;
@Autowired @Autowired
private ConnectionFactory rabbitConnectionFactory; private ConnectionFactory rabbitConnectionFactory;
@@ -66,8 +66,8 @@ public class AmqpConfiguration {
private AmqpProperties amqpProperties; private AmqpProperties amqpProperties;
@Autowired @Autowired
@Qualifier("threadPoolExecutor") @Qualifier("asyncExecutor")
private ThreadPoolExecutor threadPoolExecutor; private Executor threadPoolExecutor;
@Autowired @Autowired
private ScheduledExecutorService scheduledExecutorService; private ScheduledExecutorService scheduledExecutorService;
@@ -145,26 +145,71 @@ public class AmqpConfiguration {
} }
/** /**
* Create the sp receiver queue. * Create the DMF API receiver queue for retrieving DMF messages.
* *
* @return the receiver queue * @return the receiver queue
*/ */
@Bean @Bean
public Queue receiverQueue() { public Queue dmfReceiverQueue() {
return new Queue(amqpProperties.getReceiverQueue(), true, false, false, return new Queue(amqpProperties.getReceiverQueue(), true, false, false,
amqpDeadletterProperties.getDeadLetterExchangeArgs(amqpProperties.getDeadLetterExchange())); amqpDeadletterProperties.getDeadLetterExchangeArgs(amqpProperties.getDeadLetterExchange()));
} }
/** /**
* Create the dead letter fanout exchange. * Create the DMF API receiver queue for authentication requests called by
* 3rd party artifact storages for download authorization by devices.
*
* @return the receiver queue
*/
@Bean
public Queue authenticationReceiverQueue() {
return QueueBuilder.nonDurable(amqpProperties.getAuthenticationReceiverQueue()).autoDelete()
.withArguments(getTTLMaxArgsAuthenticationQueue()).build();
}
/**
* Create DMF exchange.
* *
* @return the fanout exchange * @return the fanout exchange
*/ */
@Bean @Bean
public FanoutExchange senderExchange() { public FanoutExchange dmfSenderExchange() {
return new FanoutExchange(AmqpSettings.DMF_EXCHANGE); return new FanoutExchange(AmqpSettings.DMF_EXCHANGE);
} }
/**
* Create the Binding {@link AmqpConfiguration#dmfReceiverQueue()} to
* {@link AmqpConfiguration#dmfSenderExchange()}.
*
* @return the binding and create the queue and exchange
*/
@Bean
public Binding bindDmfSenderExchangeToDmfQueue() {
return BindingBuilder.bind(dmfReceiverQueue()).to(dmfSenderExchange());
}
/**
* Create authentication exchange.
*
* @return the fanout exchange
*/
@Bean
public FanoutExchange authenticationExchange() {
return new FanoutExchange(AmqpSettings.AUTHENTICATION_EXCHANGE, false, true);
}
/**
* Create the Binding
* {@link AmqpConfiguration#authenticationReceiverQueue()} to
* {@link AmqpConfiguration#authenticationExchange()}.
*
* @return the binding and create the queue and exchange
*/
@Bean
public Binding bindAuthenticationSenderExchangeToAuthenticationQueue() {
return BindingBuilder.bind(authenticationReceiverQueue()).to(authenticationExchange());
}
/** /**
* Create dead letter queue. * Create dead letter queue.
* *
@@ -181,29 +226,18 @@ public class AmqpConfiguration {
* @return the fanout exchange * @return the fanout exchange
*/ */
@Bean @Bean
public FanoutExchange exchangeDeadLetter() { public FanoutExchange deadLetterExchange() {
return new FanoutExchange(amqpProperties.getDeadLetterExchange()); return new FanoutExchange(amqpProperties.getDeadLetterExchange());
} }
/** /**
* Create the Binding deadLetterQueue to exchangeDeadLetter. * Create the Binding deadLetterQueue to deadLetterExchange.
* *
* @return the binding * @return the binding
*/ */
@Bean @Bean
public Binding bindDeadLetterQueueToLwm2mExchange() { public Binding bindDeadLetterQueueToDeadLetterExchange() {
return BindingBuilder.bind(deadLetterQueue()).to(exchangeDeadLetter()); return BindingBuilder.bind(deadLetterQueue()).to(deadLetterExchange());
}
/**
* Create the Binding {@link AmqpConfiguration#receiverQueue()} to
* {@link AmqpConfiguration#senderExchange()}.
*
* @return the binding and create the queue and exchange
*/
@Bean
public Binding bindSenderExchangeToSpQueue() {
return BindingBuilder.bind(receiverQueue()).to(senderExchange());
} }
/** /**
@@ -234,15 +268,15 @@ public class AmqpConfiguration {
* AMQP messages * AMQP messages
*/ */
@Bean(name = { "listenerContainerFactory" }) @Bean(name = { "listenerContainerFactory" })
public SimpleRabbitListenerContainerFactory listenerContainerFactory() { public RabbitListenerContainerFactory<SimpleMessageListenerContainer> listenerContainerFactory() {
final SimpleRabbitListenerContainerFactory containerFactory = new SimpleRabbitListenerContainerFactory(); return new ConfigurableRabbitListenerContainerFactory(amqpProperties, rabbitConnectionFactory);
containerFactory.setDefaultRequeueRejected(true); }
containerFactory.setConnectionFactory(rabbitConnectionFactory);
containerFactory.setMissingQueuesFatal(amqpProperties.isMissingQueuesFatal()); private static Map<String, Object> getTTLMaxArgsAuthenticationQueue() {
containerFactory.setConcurrentConsumers(amqpProperties.getInitialConcurrentConsumers()); final Map<String, Object> args = new HashMap<>();
containerFactory.setMaxConcurrentConsumers(amqpProperties.getMaxConcurrentConsumers()); args.put("x-message-ttl", Duration.ofSeconds(30).toMillis());
containerFactory.setPrefetchCount(amqpProperties.getPrefetchCount()); args.put("x-max-length", 1_000);
return containerFactory; return args;
} }
} }

View File

@@ -47,6 +47,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.LocalArtifact; import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.util.IpUtil; import org.eclipse.hawkbit.util.IpUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -105,6 +106,9 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
@Autowired @Autowired
private EntityFactory entityFactory; private EntityFactory entityFactory;
@Autowired
private SystemSecurityContext systemSecurityContext;
/** /**
* Constructor. * Constructor.
* *
@@ -116,7 +120,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
} }
/** /**
* Method to handle all incoming amqp messages. * Method to handle all incoming DMF amqp messages.
* *
* @param message * @param message
* incoming message * incoming message
@@ -133,6 +137,21 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
return onMessage(message, type, tenant, getRabbitTemplate().getConnectionFactory().getVirtualHost()); return onMessage(message, type, tenant, getRabbitTemplate().getConnectionFactory().getVirtualHost());
} }
@RabbitListener(queues = "${hawkbit.dmf.rabbitmq.authenticationReceiverQueue}", containerFactory = "listenerContainerFactory")
public Message onAuthenticationRequest(final Message message) {
checkContentTypeJson(message);
final SecurityContext oldContext = SecurityContextHolder.getContext();
try {
return handleAuthentifiactionMessage(message);
} catch (final IllegalArgumentException ex) {
throw new AmqpRejectAndDontRequeueException("Invalid message!", ex);
} catch (final TenantNotExistException teex) {
throw new AmqpRejectAndDontRequeueException(teex);
} finally {
SecurityContextHolder.setContext(oldContext);
}
}
public Message onMessage(final Message message, final String type, final String tenant, final String virtualHost) { public Message onMessage(final Message message, final String type, final String tenant, final String virtualHost) {
checkContentTypeJson(message); checkContentTypeJson(message);
final SecurityContext oldContext = SecurityContextHolder.getContext(); final SecurityContext oldContext = SecurityContextHolder.getContext();
@@ -149,8 +168,6 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
final EventTopic eventTopic = EventTopic.valueOf(topicValue); final EventTopic eventTopic = EventTopic.valueOf(topicValue);
handleIncomingEvent(message, eventTopic); handleIncomingEvent(message, eventTopic);
break; break;
case AUTHENTIFICATION:
return handleAuthentifiactionMessage(message);
default: default:
logAndThrowMessageError(message, "No handle method was found for the given message type."); logAndThrowMessageError(message, "No handle method was found for the given message type.");
} }
@@ -313,9 +330,10 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
final DistributionSet distributionSet = action.getDistributionSet(); final DistributionSet distributionSet = action.getDistributionSet();
final List<SoftwareModule> softwareModuleList = controllerManagement final List<SoftwareModule> softwareModuleList = controllerManagement
.findSoftwareModulesByDistributionSet(distributionSet); .findSoftwareModulesByDistributionSet(distributionSet);
final String targetSecurityToken = systemSecurityContext.runAsSystem(() -> target.getSecurityToken());
eventBus.post(new TargetAssignDistributionSetEvent(target.getOptLockRevision(), target.getTenant(), eventBus.post(new TargetAssignDistributionSetEvent(target.getOptLockRevision(), target.getTenant(),
target.getControllerId(), action.getId(), softwareModuleList, target.getTargetInfo().getAddress(), target.getControllerId(), action.getId(), softwareModuleList, target.getTargetInfo().getAddress(),
target.getSecurityToken())); targetSecurityToken));
} }
@@ -390,7 +408,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
if (ArrayUtils.isNotEmpty(message.getMessageProperties().getCorrelationId())) { if (ArrayUtils.isNotEmpty(message.getMessageProperties().getCorrelationId())) {
actionStatus.addMessage(RepositoryConstants.SERVER_MESSAGE_PREFIX + "DMF message correlation-id " actionStatus.addMessage(RepositoryConstants.SERVER_MESSAGE_PREFIX + "DMF message correlation-id "
+ message.getMessageProperties().getCorrelationId()); + convertCorrelationId(message));
} }
actionStatus.setAction(action); actionStatus.setAction(action);
@@ -398,6 +416,10 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
return actionStatus; return actionStatus;
} }
private static String convertCorrelationId(final Message message) {
return new String(message.getMessageProperties().getCorrelationId());
}
private Action getUpdateActionStatus(final ActionStatus actionStatus) { private Action getUpdateActionStatus(final ActionStatus actionStatus) {
if (actionStatus.getStatus().equals(Status.CANCELED)) { if (actionStatus.getStatus().equals(Status.CANCELED)) {
return controllerManagement.addCancelActionStatus(actionStatus); return controllerManagement.addCancelActionStatus(actionStatus);
@@ -442,7 +464,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
if (messageProperties.getContentType() != null && messageProperties.getContentType().contains("json")) { if (messageProperties.getContentType() != null && messageProperties.getContentType().contains("json")) {
return; return;
} }
throw new IllegalArgumentException("Content-Type is not JSON compatible"); throw new AmqpRejectAndDontRequeueException("Content-Type is not JSON compatible");
} }
void setControllerManagement(final ControllerManagement controllerManagement) { void setControllerManagement(final ControllerManagement controllerManagement) {
@@ -473,4 +495,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
this.entityFactory = entityFactory; this.entityFactory = entityFactory;
} }
void setSystemSecurityContext(final SystemSecurityContext systemSecurityContext) {
this.systemSecurityContext = systemSecurityContext;
}
} }

View File

@@ -31,10 +31,16 @@ public class AmqpProperties {
private String deadLetterExchange = "dmf.connector.deadletter"; private String deadLetterExchange = "dmf.connector.deadletter";
/** /**
* DMF API receiving queue. * DMF API receiving queue for EVENT or THING_CREATED message.
*/ */
private String receiverQueue = "dmf_receiver"; private String receiverQueue = "dmf_receiver";
/**
* Authentication request called by 3rd party artifact storages for download
* authorizations.
*/
private String authenticationReceiverQueue = "authentication_receiver";
/** /**
* Missing queue fatal. * Missing queue fatal.
*/ */
@@ -62,6 +68,37 @@ public class AmqpProperties {
*/ */
private int initialConcurrentConsumers = 3; private int initialConcurrentConsumers = 3;
/**
* The number of retry attempts when passive queue declaration fails.
* Passive queue declaration occurs when the consumer starts or, when
* consuming from multiple queues, when not all queues were available during
* initialization.
*/
private int declarationRetries = 50;
/**
* @return the declarationRetries
*/
public int getDeclarationRetries() {
return declarationRetries;
}
/**
* @param declarationRetries
* the declarationRetries to set
*/
public void setDeclarationRetries(final int declarationRetries) {
this.declarationRetries = declarationRetries;
}
public String getAuthenticationReceiverQueue() {
return authenticationReceiverQueue;
}
public void setAuthenticationReceiverQueue(final String authenticationReceiverQueue) {
this.authenticationReceiverQueue = authenticationReceiverQueue;
}
public int getPrefetchCount() { public int getPrefetchCount() {
return prefetchCount; return prefetchCount;
} }
@@ -147,10 +184,6 @@ public class AmqpProperties {
return receiverQueue; return receiverQueue;
} }
public void setReceiverQueue(final String receiverQueue) {
this.receiverQueue = receiverQueue;
}
public int getRequestedHeartBeat() { public int getRequestedHeartBeat() {
return requestedHeartBeat; return requestedHeartBeat;
} }
@@ -159,4 +192,8 @@ public class AmqpProperties {
this.requestedHeartBeat = requestedHeartBeat; this.requestedHeartBeat = requestedHeartBeat;
} }
public void setReceiverQueue(final String receiverQueue) {
this.receiverQueue = receiverQueue;
}
} }

View File

@@ -0,0 +1,52 @@
/**
* 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.amqp;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
/**
* {@link RabbitListenerContainerFactory} that can be configured through
* hawkBit's {@link AmqpProperties}.
*
*/
public class ConfigurableRabbitListenerContainerFactory extends SimpleRabbitListenerContainerFactory {
private final AmqpProperties amqpProperties;
/**
* Constructor.
*
* @param rabbitConnectionFactory
* for the container factory
* @param amqpProperties
* to configure the container factory
*/
public ConfigurableRabbitListenerContainerFactory(final AmqpProperties amqpProperties,
final ConnectionFactory rabbitConnectionFactory) {
this.amqpProperties = amqpProperties;
setDefaultRequeueRejected(true);
setConnectionFactory(rabbitConnectionFactory);
setMissingQueuesFatal(amqpProperties.isMissingQueuesFatal());
setConcurrentConsumers(amqpProperties.getInitialConcurrentConsumers());
setMaxConcurrentConsumers(amqpProperties.getMaxConcurrentConsumers());
setPrefetchCount(amqpProperties.getPrefetchCount());
}
@Override
// Exception squid:UnusedProtectedMethod - called by
// AbstractRabbitListenerContainerFactory
@SuppressWarnings("squid:UnusedProtectedMethod")
protected void initializeContainer(final SimpleMessageListenerContainer instance) {
super.initializeContainer(instance);
instance.setDeclarationRetries(amqpProperties.getDeclarationRetries());
}
}

View File

@@ -31,7 +31,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor; import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor; import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.security.concurrent.DelegatingSecurityContextExecutor; import org.springframework.security.concurrent.DelegatingSecurityContextExecutorService;
import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.common.util.concurrent.ThreadFactoryBuilder;
@@ -78,18 +78,17 @@ public class AmqpTestConfiguration {
* @return ExecutorService with security context availability in thread * @return ExecutorService with security context availability in thread
* execution.. * execution..
*/ */
@Bean @Bean(destroyMethod = "shutdown")
@ConditionalOnMissingBean @ConditionalOnMissingBean
public Executor asyncExecutor() { public Executor asyncExecutor() {
return new DelegatingSecurityContextExecutor(threadPoolExecutor()); return new DelegatingSecurityContextExecutorService(threadPoolExecutor());
} }
/** /**
* @return central ThreadPoolExecutor for general purpose multi threaded * @return central ThreadPoolExecutor for general purpose multi threaded
* operations. Tries an orderly shutdown when destroyed. * operations. Tries an orderly shutdown when destroyed.
*/ */
@Bean(destroyMethod = "shutdown") private ThreadPoolExecutor threadPoolExecutor() {
public ThreadPoolExecutor threadPoolExecutor() {
final BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>(10); final BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>(10);
final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 10, 1000, TimeUnit.MILLISECONDS, final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 10, 1000, TimeUnit.MILLISECONDS,
blockingQueue, new ThreadFactoryBuilder().setNameFormat("central-executor-pool-%d").build()); blockingQueue, new ThreadFactoryBuilder().setNameFormat("central-executor-pool-%d").build());

View File

@@ -158,7 +158,7 @@ public class AmqpControllerAuthenticationTest {
@Test @Test
@Description("Tests authentication message without principal") @Description("Tests authentication message without principal")
public void testAuthenticationMessageBadCredantialsWithoutPricipal() { public void testAuthenticationMessageBadCredantialsWithoutPricipal() {
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION); final MessageProperties messageProperties = createMessageProperties(null);
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID, final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
FileResource.sha1("12345")); FileResource.sha1("12345"));
@@ -166,8 +166,7 @@ public class AmqpControllerAuthenticationTest {
messageProperties); messageProperties);
// test // test
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(), final Message onMessage = amqpMessageHandlerService.onAuthenticationRequest(message);
TENANT, "vHost");
// verify // verify
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage); final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
@@ -178,7 +177,7 @@ public class AmqpControllerAuthenticationTest {
@Test @Test
@Description("Tests authentication message without wrong credential") @Description("Tests authentication message without wrong credential")
public void testAuthenticationMessageBadCredantialsWithWrongCredential() { public void testAuthenticationMessageBadCredantialsWithWrongCredential() {
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION); final MessageProperties messageProperties = createMessageProperties(null);
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID, final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
FileResource.sha1("12345")); FileResource.sha1("12345"));
when(tenantConfigurationManagement.getConfigurationValue( when(tenantConfigurationManagement.getConfigurationValue(
@@ -189,8 +188,7 @@ public class AmqpControllerAuthenticationTest {
messageProperties); messageProperties);
// test // test
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(), final Message onMessage = amqpMessageHandlerService.onAuthenticationRequest(message);
TENANT, "vHost");
// verify // verify
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage); final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
@@ -201,7 +199,7 @@ public class AmqpControllerAuthenticationTest {
@Test @Test
@Description("Tests authentication message successfull") @Description("Tests authentication message successfull")
public void testSuccessfullMessageAuthentication() { public void testSuccessfullMessageAuthentication() {
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION); final MessageProperties messageProperties = createMessageProperties(null);
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID, final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
FileResource.sha1("12345")); FileResource.sha1("12345"));
when(tenantConfigurationManagement.getConfigurationValue( when(tenantConfigurationManagement.getConfigurationValue(
@@ -212,8 +210,7 @@ public class AmqpControllerAuthenticationTest {
messageProperties); messageProperties);
// test // test
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(), final Message onMessage = amqpMessageHandlerService.onAuthenticationRequest(message);
TENANT, "vHost");
// verify // verify
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage); final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
@@ -232,7 +229,9 @@ public class AmqpControllerAuthenticationTest {
private MessageProperties createMessageProperties(final MessageType type, final String replyTo) { private MessageProperties createMessageProperties(final MessageType type, final String replyTo) {
final MessageProperties messageProperties = new MessageProperties(); final MessageProperties messageProperties = new MessageProperties();
messageProperties.setHeader(MessageHeaderKey.TYPE, type.name()); if (type != null) {
messageProperties.setHeader(MessageHeaderKey.TYPE, type.name());
}
messageProperties.setHeader(MessageHeaderKey.TENANT, TENANT); messageProperties.setHeader(MessageHeaderKey.TENANT, TENANT);
messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON); messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON);
messageProperties.setReplyTo(replyTo); messageProperties.setReplyTo(replyTo);

View File

@@ -52,6 +52,7 @@ import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.TargetInfo; import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.eclipse.hawkbit.security.SecurityTokenGenerator; import org.eclipse.hawkbit.security.SecurityTokenGenerator;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -112,6 +113,9 @@ public class AmqpMessageHandlerServiceTest {
@Mock @Mock
private RabbitTemplate rabbitTemplate; private RabbitTemplate rabbitTemplate;
@Mock
private SystemSecurityContext systemSecurityContextMock;
@Before @Before
public void before() throws Exception { public void before() throws Exception {
messageConverter = new Jackson2JsonMessageConverter(); messageConverter = new Jackson2JsonMessageConverter();
@@ -124,6 +128,7 @@ public class AmqpMessageHandlerServiceTest {
amqpMessageHandlerService.setHostnameResolver(hostnameResolverMock); amqpMessageHandlerService.setHostnameResolver(hostnameResolverMock);
amqpMessageHandlerService.setEventBus(eventBus); amqpMessageHandlerService.setEventBus(eventBus);
amqpMessageHandlerService.setEntityFactory(entityFactoryMock); amqpMessageHandlerService.setEntityFactory(entityFactoryMock);
amqpMessageHandlerService.setSystemSecurityContext(systemSecurityContextMock);
} }
@@ -135,8 +140,8 @@ public class AmqpMessageHandlerServiceTest {
final Message message = new Message(new byte[0], messageProperties); final Message message = new Message(new byte[0], messageProperties);
try { try {
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost"); amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost");
fail("IllegalArgumentException was excepeted due to worng content type"); fail("AmqpRejectAndDontRequeueException was excepeted due to worng content type");
} catch (final IllegalArgumentException e) { } catch (final AmqpRejectAndDontRequeueException e) {
} }
} }
@@ -170,7 +175,7 @@ public class AmqpMessageHandlerServiceTest {
try { try {
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost"); amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost");
fail("IllegalArgumentException was excepeted since no replyTo header was set"); fail("AmqpRejectAndDontRequeueException was excepeted since no replyTo header was set");
} catch (final AmqpRejectAndDontRequeueException exception) { } catch (final AmqpRejectAndDontRequeueException exception) {
// test ok - exception was excepted // test ok - exception was excepted
} }
@@ -184,7 +189,7 @@ public class AmqpMessageHandlerServiceTest {
final Message message = messageConverter.toMessage(new byte[0], messageProperties); final Message message = messageConverter.toMessage(new byte[0], messageProperties);
try { try {
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost"); amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost");
fail("IllegalArgumentException was excepeted since no thingID was set"); fail("AmqpRejectAndDontRequeueException was excepeted since no thingID was set");
} catch (final AmqpRejectAndDontRequeueException exception) { } catch (final AmqpRejectAndDontRequeueException exception) {
// test ok - exception was excepted // test ok - exception was excepted
} }
@@ -200,7 +205,7 @@ public class AmqpMessageHandlerServiceTest {
try { try {
amqpMessageHandlerService.onMessage(message, type, TENANT, "vHost"); amqpMessageHandlerService.onMessage(message, type, TENANT, "vHost");
fail("IllegalArgumentException was excepeted due to unknown message type"); fail("AmqpRejectAndDontRequeueException was excepeted due to unknown message type");
} catch (final AmqpRejectAndDontRequeueException exception) { } catch (final AmqpRejectAndDontRequeueException exception) {
// test ok - exception was excepted // test ok - exception was excepted
} }
@@ -213,21 +218,21 @@ public class AmqpMessageHandlerServiceTest {
final Message message = new Message(new byte[0], messageProperties); final Message message = new Message(new byte[0], messageProperties);
try { try {
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost"); amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
fail("IllegalArgumentException was excepeted due to unknown message type"); fail("AmqpRejectAndDontRequeueException was excepeted due to unknown message type");
} catch (final AmqpRejectAndDontRequeueException e) { } catch (final AmqpRejectAndDontRequeueException e) {
} }
try { try {
messageProperties.setHeader(MessageHeaderKey.TOPIC, "wrongTopic"); messageProperties.setHeader(MessageHeaderKey.TOPIC, "wrongTopic");
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost"); amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
fail("IllegalArgumentException was excepeted due to unknown topic"); fail("AmqpRejectAndDontRequeueException was excepeted due to unknown topic");
} catch (final AmqpRejectAndDontRequeueException e) { } catch (final AmqpRejectAndDontRequeueException e) {
} }
messageProperties.setHeader(MessageHeaderKey.TOPIC, EventTopic.CANCEL_DOWNLOAD.name()); messageProperties.setHeader(MessageHeaderKey.TOPIC, EventTopic.CANCEL_DOWNLOAD.name());
try { try {
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost"); amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
fail("IllegalArgumentException was excepeted because there was no event topic"); fail("AmqpRejectAndDontRequeueException was excepeted because there was no event topic");
} catch (final AmqpRejectAndDontRequeueException exception) { } catch (final AmqpRejectAndDontRequeueException exception) {
// test ok - exception was excepted // test ok - exception was excepted
} }
@@ -246,7 +251,7 @@ public class AmqpMessageHandlerServiceTest {
try { try {
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost"); amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
fail("IllegalArgumentException was excepeted since no action id was set"); fail("AmqpRejectAndDontRequeueException was excepeted since no action id was set");
} catch (final AmqpRejectAndDontRequeueException exception) { } catch (final AmqpRejectAndDontRequeueException exception) {
// test ok - exception was excepted // test ok - exception was excepted
} }
@@ -263,7 +268,7 @@ public class AmqpMessageHandlerServiceTest {
try { try {
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost"); amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
fail("IllegalArgumentException was excepeted since no action id was set"); fail("AmqpRejectAndDontRequeueException was excepeted since no action id was set");
} catch (final AmqpRejectAndDontRequeueException exception) { } catch (final AmqpRejectAndDontRequeueException exception) {
// test ok - exception was excepted // test ok - exception was excepted
} }
@@ -273,14 +278,13 @@ public class AmqpMessageHandlerServiceTest {
@Test @Test
@Description("Tests that an download request is denied for an artifact which does not exists") @Description("Tests that an download request is denied for an artifact which does not exists")
public void authenticationRequestDeniedForArtifactWhichDoesNotExists() { public void authenticationRequestDeniedForArtifactWhichDoesNotExists() {
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION); final MessageProperties messageProperties = createMessageProperties(null);
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.sha1("12345")); final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.sha1("12345"));
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken, final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
messageProperties); messageProperties);
// test // test
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(), final Message onMessage = amqpMessageHandlerService.onAuthenticationRequest(message);
TENANT, "vHost");
// verify // verify
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage); final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
@@ -292,7 +296,7 @@ public class AmqpMessageHandlerServiceTest {
@Test @Test
@Description("Tests that an download request is denied for an artifact which is not assigned to the requested target") @Description("Tests that an download request is denied for an artifact which is not assigned to the requested target")
public void authenticationRequestDeniedForArtifactWhichIsNotAssignedToTarget() { public void authenticationRequestDeniedForArtifactWhichIsNotAssignedToTarget() {
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION); final MessageProperties messageProperties = createMessageProperties(null);
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.sha1("12345")); final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.sha1("12345"));
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken, final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
messageProperties); messageProperties);
@@ -303,8 +307,7 @@ public class AmqpMessageHandlerServiceTest {
.thenThrow(EntityNotFoundException.class); .thenThrow(EntityNotFoundException.class);
// test // test
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(), final Message onMessage = amqpMessageHandlerService.onAuthenticationRequest(message);
TENANT, "vHost");
// verify // verify
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage); final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
@@ -316,7 +319,7 @@ public class AmqpMessageHandlerServiceTest {
@Test @Test
@Description("Tests that an download request is allowed for an artifact which exists and assigned to the requested target") @Description("Tests that an download request is allowed for an artifact which exists and assigned to the requested target")
public void authenticationRequestAllowedForArtifactWhichExistsAndAssignedToTarget() throws MalformedURLException { public void authenticationRequestAllowedForArtifactWhichExistsAndAssignedToTarget() throws MalformedURLException {
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION); final MessageProperties messageProperties = createMessageProperties(null);
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.sha1("12345")); final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.sha1("12345"));
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken, final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
messageProperties); messageProperties);
@@ -334,8 +337,7 @@ public class AmqpMessageHandlerServiceTest {
when(hostnameResolverMock.resolveHostname()).thenReturn(new URL("http://localhost")); when(hostnameResolverMock.resolveHostname()).thenReturn(new URL("http://localhost"));
// test // test
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(), final Message onMessage = amqpMessageHandlerService.onAuthenticationRequest(message);
TENANT, "vHost");
// verify // verify
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage); final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
@@ -367,6 +369,8 @@ public class AmqpMessageHandlerServiceTest {
when(controllerManagementMock.findSoftwareModulesByDistributionSet(Matchers.any())) when(controllerManagementMock.findSoftwareModulesByDistributionSet(Matchers.any()))
.thenReturn(softwareModuleList); .thenReturn(softwareModuleList);
when(systemSecurityContextMock.runAsSystem(anyObject())).thenReturn("securityToken");
final MessageProperties messageProperties = createMessageProperties(MessageType.EVENT); final MessageProperties messageProperties = createMessageProperties(MessageType.EVENT);
messageProperties.setHeader(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ACTION_STATUS.name()); messageProperties.setHeader(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ACTION_STATUS.name());
final ActionUpdateStatus actionUpdateStatus = createActionUpdateStatus(ActionStatus.FINISHED, 23L); final ActionUpdateStatus actionUpdateStatus = createActionUpdateStatus(ActionStatus.FINISHED, 23L);
@@ -411,7 +415,9 @@ public class AmqpMessageHandlerServiceTest {
private MessageProperties createMessageProperties(final MessageType type, final String replyTo) { private MessageProperties createMessageProperties(final MessageType type, final String replyTo) {
final MessageProperties messageProperties = new MessageProperties(); final MessageProperties messageProperties = new MessageProperties();
messageProperties.setHeader(MessageHeaderKey.TYPE, type.name()); if (type != null) {
messageProperties.setHeader(MessageHeaderKey.TYPE, type.name());
}
messageProperties.setHeader(MessageHeaderKey.TENANT, TENANT); messageProperties.setHeader(MessageHeaderKey.TENANT, TENANT);
messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON); messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON);
messageProperties.setReplyTo(replyTo); messageProperties.setReplyTo(replyTo);

View File

@@ -18,6 +18,8 @@ public final class AmqpSettings {
public static final String DMF_EXCHANGE = "dmf.exchange"; public static final String DMF_EXCHANGE = "dmf.exchange";
public static final String AUTHENTICATION_EXCHANGE = "authentication.exchange";
private AmqpSettings() { private AmqpSettings() {
} }

View File

@@ -26,9 +26,4 @@ public enum MessageType {
*/ */
THING_CREATED, THING_CREATED,
/**
* The authentication type.
*/
AUTHENTIFICATION,
} }

View File

@@ -21,6 +21,17 @@ public class MgmtTargetRequestBody {
@JsonProperty @JsonProperty
private String address; private String address;
@JsonProperty
private String securityToken;
public String getSecurityToken() {
return securityToken;
}
public void setSecurityToken(final String securityToken) {
this.securityToken = securityToken;
}
/** /**
* @return the name * @return the name
*/ */

View File

@@ -68,28 +68,24 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi {
@RequestParam(value = "md5sum", required = false) final String md5Sum, @RequestParam(value = "md5sum", required = false) final String md5Sum,
@RequestParam(value = "sha1sum", required = false) final String sha1Sum) { @RequestParam(value = "sha1sum", required = false) final String sha1Sum) {
Artifact result; if (file.isEmpty()) {
if (!file.isEmpty()) {
String fileName = optionalFileName;
if (null == fileName) {
fileName = file.getOriginalFilename();
}
try {
result = artifactManagement.createLocalArtifact(file.getInputStream(), softwareModuleId, fileName,
md5Sum == null ? null : md5Sum.toLowerCase(), sha1Sum == null ? null : sha1Sum.toLowerCase(),
false, file.getContentType());
} catch (final IOException e) {
LOG.error("Failed to store artifact", e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
} else {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST); return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
} }
String fileName = optionalFileName;
return new ResponseEntity<>(MgmtSoftwareModuleMapper.toResponse(result), HttpStatus.CREATED); if (fileName == null) {
fileName = file.getOriginalFilename();
}
try {
final Artifact result = artifactManagement.createLocalArtifact(file.getInputStream(), softwareModuleId,
fileName, md5Sum == null ? null : md5Sum.toLowerCase(),
sha1Sum == null ? null : sha1Sum.toLowerCase(), false, file.getContentType());
return new ResponseEntity<>(MgmtSoftwareModuleMapper.toResponse(result), HttpStatus.CREATED);
} catch (final IOException e) {
LOG.error("Failed to store artifact", e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
} }
@Override @Override

View File

@@ -182,10 +182,11 @@ public final class MgmtTargetMapper {
} }
static Target fromRequest(final EntityFactory entityFactory, final MgmtTargetRequestBody targetRest) { static Target fromRequest(final EntityFactory entityFactory, final MgmtTargetRequestBody targetRest) {
final Target target = entityFactory.generateTarget(targetRest.getControllerId()); final Target target = entityFactory.generateTarget(targetRest.getControllerId(), targetRest.getSecurityToken());
target.setDescription(targetRest.getDescription()); target.setDescription(targetRest.getDescription());
target.setName(targetRest.getName()); target.setName(targetRest.getName());
target.getTargetInfo().setAddress(targetRest.getAddress()); target.getTargetInfo().setAddress(targetRest.getAddress());
return target; return target;
} }

View File

@@ -125,6 +125,13 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
if (targetRest.getName() != null) { if (targetRest.getName() != null) {
existingTarget.setName(targetRest.getName()); existingTarget.setName(targetRest.getName());
} }
if (targetRest.getAddress() != null) {
existingTarget.getTargetInfo().setAddress(targetRest.getAddress());
}
if (targetRest.getSecurityToken() != null) {
existingTarget.setSecurityToken(targetRest.getSecurityToken());
}
final Target updateTarget = this.targetManagement.updateTarget(existingTarget); final Target updateTarget = this.targetManagement.updateTarget(existingTarget);
return new ResponseEntity<>(MgmtTargetMapper.toResponse(updateTarget), HttpStatus.OK); return new ResponseEntity<>(MgmtTargetMapper.toResponse(updateTarget), HttpStatus.OK);

View File

@@ -355,6 +355,54 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
assertThat(findTargetByControllerID.getName()).isEqualTo(knownNameNotModiy); assertThat(findTargetByControllerID.getName()).isEqualTo(knownNameNotModiy);
} }
@Test
@Description("Ensures that target update request is reflected by repository.")
public void updateTargetSecurityToken() throws Exception {
final String knownControllerId = "123";
final String knownNewToken = "6567576565";
final String knownNameNotModiy = "nameNotModiy";
final String body = new JSONObject().put("securityToken", knownNewToken).toString();
// prepare
final Target t = entityFactory.generateTarget(knownControllerId);
t.setName(knownNameNotModiy);
targetManagement.createTarget(t);
mvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId).content(body)
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("$.controllerId", equalTo(knownControllerId)))
.andExpect(jsonPath("$.securityToken", equalTo(knownNewToken)))
.andExpect(jsonPath("$.name", equalTo(knownNameNotModiy)));
final Target findTargetByControllerID = targetManagement.findTargetByControllerID(knownControllerId);
assertThat(findTargetByControllerID.getSecurityToken()).isEqualTo(knownNewToken);
assertThat(findTargetByControllerID.getName()).isEqualTo(knownNameNotModiy);
}
@Test
@Description("Ensures that target update request is reflected by repository.")
public void updateTargetAddress() throws Exception {
final String knownControllerId = "123";
final String knownNewAddress = "amqp://test123/foobar";
final String knownNameNotModiy = "nameNotModiy";
final String body = new JSONObject().put("address", knownNewAddress).toString();
// prepare
final Target t = entityFactory.generateTarget(knownControllerId);
t.setName(knownNameNotModiy);
targetManagement.createTarget(t);
mvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId).content(body)
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("$.controllerId", equalTo(knownControllerId)))
.andExpect(jsonPath("$.address", equalTo(knownNewAddress)))
.andExpect(jsonPath("$.name", equalTo(knownNameNotModiy)));
final Target findTargetByControllerID = targetManagement.findTargetByControllerID(knownControllerId);
assertThat(findTargetByControllerID.getTargetInfo().getAddress().toString()).isEqualTo(knownNewAddress);
assertThat(findTargetByControllerID.getName()).isEqualTo(knownNameNotModiy);
}
@Test @Test
@Description("Ensures that target query returns list of targets in defined format.") @Description("Ensures that target query returns list of targets in defined format.")
public void getTargetWithoutAddtionalRequestParameters() throws Exception { public void getTargetWithoutAddtionalRequestParameters() throws Exception {
@@ -679,7 +727,7 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
@Test @Test
public void createTargetsListReturnsSuccessful() throws Exception { public void createTargetsListReturnsSuccessful() throws Exception {
final Target test1 = entityFactory.generateTarget("id1"); final Target test1 = entityFactory.generateTarget("id1", "token");
test1.setDescription("testid1"); test1.setDescription("testid1");
test1.setName("testname1"); test1.setName("testname1");
test1.getTargetInfo().setAddress("amqp://test123/foobar"); test1.getTargetInfo().setAddress("amqp://test123/foobar");
@@ -696,7 +744,7 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
targets.add(test3); targets.add(test3);
final MvcResult mvcResult = mvc final MvcResult mvcResult = mvc
.perform(post("/rest/v1/targets/").content(JsonBuilder.targets(targets)) .perform(post("/rest/v1/targets/").content(JsonBuilder.targets(targets, true))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) .andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
.andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().contentType(MediaType.APPLICATION_JSON))
@@ -705,6 +753,7 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
.andExpect(jsonPath("[0].description", equalTo("testid1"))) .andExpect(jsonPath("[0].description", equalTo("testid1")))
.andExpect(jsonPath("[0].createdAt", not(equalTo(0)))) .andExpect(jsonPath("[0].createdAt", not(equalTo(0))))
.andExpect(jsonPath("[0].createdBy", equalTo("bumlux"))) .andExpect(jsonPath("[0].createdBy", equalTo("bumlux")))
.andExpect(jsonPath("[0].securityToken", equalTo("token")))
.andExpect(jsonPath("[0].address", equalTo("amqp://test123/foobar"))) .andExpect(jsonPath("[0].address", equalTo("amqp://test123/foobar")))
.andExpect(jsonPath("[1].name", equalTo("testname2"))) .andExpect(jsonPath("[1].name", equalTo("testname2")))
.andExpect(jsonPath("[1].createdBy", equalTo("bumlux"))) .andExpect(jsonPath("[1].createdBy", equalTo("bumlux")))
@@ -731,6 +780,9 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
assertThat(targetManagement.findTargetByControllerID("id1")).isNotNull(); assertThat(targetManagement.findTargetByControllerID("id1")).isNotNull();
assertThat(targetManagement.findTargetByControllerID("id1").getName()).isEqualTo("testname1"); assertThat(targetManagement.findTargetByControllerID("id1").getName()).isEqualTo("testname1");
assertThat(targetManagement.findTargetByControllerID("id1").getDescription()).isEqualTo("testid1"); assertThat(targetManagement.findTargetByControllerID("id1").getDescription()).isEqualTo("testid1");
assertThat(targetManagement.findTargetByControllerID("id1").getSecurityToken()).isEqualTo("token");
assertThat(targetManagement.findTargetByControllerID("id1").getTargetInfo().getAddress().toString())
.isEqualTo("amqp://test123/foobar");
assertThat(targetManagement.findTargetByControllerID("id2")).isNotNull(); assertThat(targetManagement.findTargetByControllerID("id2")).isNotNull();
assertThat(targetManagement.findTargetByControllerID("id2").getName()).isEqualTo("testname2"); assertThat(targetManagement.findTargetByControllerID("id2").getName()).isEqualTo("testname2");
assertThat(targetManagement.findTargetByControllerID("id2").getDescription()).isEqualTo("testid2"); assertThat(targetManagement.findTargetByControllerID("id2").getDescription()).isEqualTo("testid2");

View File

@@ -269,8 +269,7 @@ public interface DeploymentManagement {
* @return the actions referring a specific rollout and a specific parent * @return the actions referring a specific rollout and a specific parent
* rollout group in a specific status * rollout group in a specific status
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
List<Action> findActionsByRolloutGroupParentAndStatus(@NotNull Rollout rollout, List<Action> findActionsByRolloutGroupParentAndStatus(@NotNull Rollout rollout,
@NotNull RolloutGroup rolloutGroupParent, @NotNull Action.Status actionStatus); @NotNull RolloutGroup rolloutGroupParent, @NotNull Action.Status actionStatus);
@@ -496,8 +495,7 @@ public interface DeploymentManagement {
* the action to start now. * the action to start now.
* @return the action which has been started * @return the action which has been started
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
Action startScheduledAction(@NotNull Action action); Action startScheduledAction(@NotNull Action action);
/** /**

View File

@@ -287,6 +287,7 @@ public interface EntityFactory {
/** /**
* Generates an empty {@link Target} without persisting it. * Generates an empty {@link Target} without persisting it.
* {@link Target#getSecurityToken()} is generated.
* *
* @param controllerID * @param controllerID
* of the {@link Target} * of the {@link Target}
@@ -295,6 +296,19 @@ public interface EntityFactory {
*/ */
Target generateTarget(@NotEmpty String controllerID); Target generateTarget(@NotEmpty String controllerID);
/**
* Generates an empty {@link Target} without persisting it.
*
* @param controllerID
* of the {@link Target}
* @param securityToken
* of the {@link Target} for authentication if enabled on tenant.
* Generates one if empty or <code>null</code>.
*
* @return {@link Target} object
*/
Target generateTarget(@NotEmpty String controllerID, @NotEmpty String securityToken);
/** /**
* Generates an empty {@link TargetFilterQuery} without persisting it. * Generates an empty {@link TargetFilterQuery} without persisting it.
* *

View File

@@ -61,8 +61,7 @@ public interface RolloutManagement {
* this check. This check is only applied if the last check is * this check. This check is only applied if the last check is
* less than (lastcheck-delay). * less than (lastcheck-delay).
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
void checkRunningRollouts(long delayBetweenChecks); void checkRunningRollouts(long delayBetweenChecks);
/** /**
@@ -266,8 +265,7 @@ public interface RolloutManagement {
* if given rollout is not in {@link RolloutStatus#RUNNING}. * if given rollout is not in {@link RolloutStatus#RUNNING}.
* Only running rollouts can be paused. * Only running rollouts can be paused.
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
void pauseRollout(@NotNull Rollout rollout); void pauseRollout(@NotNull Rollout rollout);
/** /**
@@ -281,8 +279,7 @@ public interface RolloutManagement {
* if given rollout is not in {@link RolloutStatus#PAUSED}. Only * if given rollout is not in {@link RolloutStatus#PAUSED}. Only
* paused rollouts can be resumed. * paused rollouts can be resumed.
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
void resumeRollout(@NotNull Rollout rollout); void resumeRollout(@NotNull Rollout rollout);
/** /**
@@ -303,8 +300,7 @@ public interface RolloutManagement {
* if given rollout is not in {@link RolloutStatus#READY}. Only * if given rollout is not in {@link RolloutStatus#READY}. Only
* ready rollouts can be started. * ready rollouts can be started.
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
Rollout startRollout(@NotNull Rollout rollout); Rollout startRollout(@NotNull Rollout rollout);
/** /**
@@ -326,8 +322,7 @@ public interface RolloutManagement {
* if given rollout is not in {@link RolloutStatus#READY}. Only * if given rollout is not in {@link RolloutStatus#READY}. Only
* ready rollouts can be started. * ready rollouts can be started.
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
Rollout startRolloutAsync(@NotNull Rollout rollout); Rollout startRolloutAsync(@NotNull Rollout rollout);
/** /**

View File

@@ -39,16 +39,14 @@ public interface SystemManagement {
* @param tenant * @param tenant
* to delete * to delete
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_SYSTEM_ADMIN + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_SYSTEM_ADMIN)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
void deleteTenant(@NotNull String tenant); void deleteTenant(@NotNull String tenant);
/** /**
* *
* @return list of all tenant names in the system. * @return list of all tenant names in the system.
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_SYSTEM_ADMIN + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_SYSTEM_ADMIN)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
List<String> findTenants(); List<String> findTenants();
/** /**
@@ -68,8 +66,8 @@ public interface SystemManagement {
/** /**
* Returns {@link TenantMetaData} of given and current tenant. Creates for * Returns {@link TenantMetaData} of given and current tenant. Creates for
* new tenants also two {@link SoftwareModuleType} (os and app) and * new tenants also two {@link SoftwareModuleType} (os and app) and
* {@link RepositoryConstants#DEFAULT_DS_TYPES_IN_TENANT} {@link DistributionSetType}s * {@link RepositoryConstants#DEFAULT_DS_TYPES_IN_TENANT}
* (os and os_app). * {@link DistributionSetType}s (os and os_app).
* *
* DISCLAIMER: this variant is used during initial login (where the tenant * DISCLAIMER: this variant is used during initial login (where the tenant
* is not yet in the session). Please user {@link #getTenantMetadata()} for * is not yet in the session). Please user {@link #getTenantMetadata()} for

View File

@@ -54,8 +54,7 @@ public interface TenantConfigurationManagement {
* @return <null> if no default value is set and no database value available * @return <null> if no default value is set and no database value available
* or returns the tenant configuration value * or returns the tenant configuration value
*/ */
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
<T> TenantConfigurationValue<T> buildTenantConfigurationValueByKey(TenantConfigurationKey configurationKey, <T> TenantConfigurationValue<T> buildTenantConfigurationValueByKey(TenantConfigurationKey configurationKey,
Class<T> propertyType, TenantConfiguration tenantConfiguration); Class<T> propertyType, TenantConfiguration tenantConfiguration);
@@ -87,8 +86,7 @@ public interface TenantConfigurationManagement {
* if the property cannot be converted to the given * if the property cannot be converted to the given
* {@code propertyType} * {@code propertyType}
*/ */
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
<T> TenantConfigurationValue<T> getConfigurationValue(TenantConfigurationKey configurationKey); <T> TenantConfigurationValue<T> getConfigurationValue(TenantConfigurationKey configurationKey);
/** /**
@@ -114,8 +112,7 @@ public interface TenantConfigurationManagement {
* if the property cannot be converted to the given * if the property cannot be converted to the given
* {@code propertyType} * {@code propertyType}
*/ */
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
<T> TenantConfigurationValue<T> getConfigurationValue(TenantConfigurationKey configurationKey, <T> TenantConfigurationValue<T> getConfigurationValue(TenantConfigurationKey configurationKey,
Class<T> propertyType); Class<T> propertyType);
@@ -139,7 +136,6 @@ public interface TenantConfigurationManagement {
* if the property cannot be converted to the given * if the property cannot be converted to the given
* {@code propertyType} * {@code propertyType}
*/ */
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
<T> T getGlobalConfigurationValue(TenantConfigurationKey configurationKey, Class<T> propertyType); <T> T getGlobalConfigurationValue(TenantConfigurationKey configurationKey, Class<T> propertyType);
} }

View File

@@ -0,0 +1,30 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.exception;
import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.exception.SpServerRtException;
/**
* Thrown if a multi part exception occurred.
*
*/
public final class MultiPartFileUploadException extends SpServerRtException {
private static final long serialVersionUID = 1L;
/**
* @param cause
* for the exception
*/
public MultiPartFileUploadException(final Throwable cause) {
super(cause.getMessage(), SpServerError.SP_ARTIFACT_UPLOAD_FAILED, cause);
}
}

View File

@@ -58,4 +58,10 @@ public interface Target extends NamedEntity {
*/ */
String getSecurityToken(); String getSecurityToken();
/**
* @param token
* new securityToken
*/
void setSecurityToken(String token);
} }

View File

@@ -10,6 +10,7 @@ package org.eclipse.hawkbit.repository.jpa;
import java.util.Collection; import java.util.Collection;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus; import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
@@ -87,6 +88,14 @@ public class JpaEntityFactory implements EntityFactory {
return new JpaTarget(controllerId); return new JpaTarget(controllerId);
} }
@Override
public Target generateTarget(final String controllerId, final String securityToken) {
if (StringUtils.isEmpty(securityToken)) {
return new JpaTarget(controllerId);
}
return new JpaTarget(controllerId, securityToken);
}
@Override @Override
public TargetTag generateTargetTag() { public TargetTag generateTargetTag() {
return new JpaTargetTag(); return new JpaTargetTag();

View File

@@ -132,7 +132,7 @@ public class JpaSoftwareManagement implements SoftwareManagement {
final JpaSoftwareModuleType type = softwareModuleTypeRepository.findOne(sm.getId()); final JpaSoftwareModuleType type = softwareModuleTypeRepository.findOne(sm.getId());
boolean updated = false; boolean updated = false;
if (sm.getDescription() != null && !sm.getDescription().equals(type.getDescription())) { if (sm.getDescription() == null || !sm.getDescription().equals(type.getDescription())) {
type.setDescription(sm.getDescription()); type.setDescription(sm.getDescription());
updated = true; updated = true;
} }

View File

@@ -115,9 +115,21 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Lon
* controller ID of the {@link Target} * controller ID of the {@link Target}
*/ */
public JpaTarget(final String controllerId) { public JpaTarget(final String controllerId) {
this(controllerId, SecurityTokenGeneratorHolder.getInstance().generateToken());
}
/**
* Constructor.
*
* @param controllerId
* controller ID of the {@link Target}
* @param securityToken
* for target authentication if enabled
*/
public JpaTarget(final String controllerId, final String securityToken) {
this.controllerId = controllerId; this.controllerId = controllerId;
setName(controllerId); setName(controllerId);
securityToken = SecurityTokenGeneratorHolder.getInstance().generateToken(); this.securityToken = securityToken;
targetInfo = new JpaTargetInfo(this); targetInfo = new JpaTargetInfo(this);
} }

View File

@@ -38,13 +38,13 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Tag; import org.eclipse.hawkbit.repository.model.Tag;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetIdName; import org.eclipse.hawkbit.repository.model.TargetIdName;
import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.junit.Test; import org.junit.Test;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
@@ -61,7 +61,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Ensures that retrieving the target security is only permitted with the necessary permissions.") @Description("Ensures that retrieving the target security is only permitted with the necessary permissions.")
public void getTargetSecurityTokenOnlyWithCorrectPermission() throws Exception { public void getTargetSecurityTokenOnlyWithCorrectPermission() throws Exception {
final Target createdTarget = targetManagement.createTarget(new JpaTarget("targetWithSecurityToken")); final Target createdTarget = targetManagement.createTarget(new JpaTarget("targetWithSecurityToken", "token"));
// retrieve security token only with READ_TARGET_SEC_TOKEN permission // retrieve security token only with READ_TARGET_SEC_TOKEN permission
final String securityTokenWithReadPermission = securityRule.runAs(WithSpringAuthorityRule final String securityTokenWithReadPermission = securityRule.runAs(WithSpringAuthorityRule
@@ -80,7 +80,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
return createdTarget.getSecurityToken(); return createdTarget.getSecurityToken();
}); });
assertThat(createdTarget.getSecurityToken()).isNotNull(); assertThat(createdTarget.getSecurityToken()).isEqualTo("token");
assertThat(securityTokenWithReadPermission).isNotNull(); assertThat(securityTokenWithReadPermission).isNotNull();
assertThat(securityTokenAsSystemCode).isNotNull(); assertThat(securityTokenAsSystemCode).isNotNull();

View File

@@ -31,7 +31,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile; import org.springframework.context.annotation.Profile;
import org.springframework.data.domain.AuditorAware; import org.springframework.data.domain.AuditorAware;
import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.security.concurrent.DelegatingSecurityContextExecutor; import org.springframework.security.concurrent.DelegatingSecurityContextExecutorService;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import com.google.common.eventbus.AsyncEventBus; import com.google.common.eventbus.AsyncEventBus;
@@ -99,7 +99,7 @@ public class TestConfiguration implements AsyncConfigurer {
@Bean @Bean
public Executor asyncExecutor() { public Executor asyncExecutor() {
return new DelegatingSecurityContextExecutor(Executors.newSingleThreadExecutor()); return new DelegatingSecurityContextExecutorService(Executors.newSingleThreadExecutor());
} }
@Bean @Bean

View File

@@ -9,13 +9,15 @@
package org.eclipse.hawkbit.rest.exception; package org.eclipse.hawkbit.rest.exception;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.apache.tomcat.util.http.fileupload.FileUploadBase.FileSizeLimitExceededException; import org.apache.commons.lang3.exception.ExceptionUtils;
import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.exception.SpServerRtException; import org.eclipse.hawkbit.exception.SpServerRtException;
import org.eclipse.hawkbit.repository.exception.MultiPartFileUploadException;
import org.eclipse.hawkbit.rest.json.model.ExceptionInfo; import org.eclipse.hawkbit.rest.json.model.ExceptionInfo;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -26,12 +28,10 @@ import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.multipart.MultipartException; import org.springframework.web.multipart.MultipartException;
import com.google.common.collect.Iterables;
/** /**
* General controller advice for exception handling. * General controller advice for exception handling.
*
*
*
*
*/ */
@ControllerAdvice @ControllerAdvice
public class ResponseExceptionHandler { public class ResponseExceptionHandler {
@@ -89,14 +89,11 @@ public class ResponseExceptionHandler {
@ExceptionHandler(SpServerRtException.class) @ExceptionHandler(SpServerRtException.class)
public ResponseEntity<ExceptionInfo> handleSpServerRtExceptions(final HttpServletRequest request, public ResponseEntity<ExceptionInfo> handleSpServerRtExceptions(final HttpServletRequest request,
final Exception ex) { final Exception ex) {
LOG.debug("Handling exception of request {}", request.getRequestURL()); logRequest(request, ex);
final ExceptionInfo response = new ExceptionInfo(); final ExceptionInfo response = createExceptionInfo(ex);
final HttpStatus responseStatus; final HttpStatus responseStatus;
response.setMessage(ex.getMessage());
response.setExceptionClass(ex.getClass().getName());
if (ex instanceof SpServerRtException) { if (ex instanceof SpServerRtException) {
responseStatus = getStatusOrDefault(((SpServerRtException) ex).getError()); responseStatus = getStatusOrDefault(((SpServerRtException) ex).getError());
response.setErrorCode(((SpServerRtException) ex).getError().getKey());
} else { } else {
responseStatus = DEFAULT_RESPONSE_STATUS; responseStatus = DEFAULT_RESPONSE_STATUS;
} }
@@ -118,11 +115,8 @@ public class ResponseExceptionHandler {
@ExceptionHandler(HttpMessageNotReadableException.class) @ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity<ExceptionInfo> handleHttpMessageNotReadableException(final HttpServletRequest request, public ResponseEntity<ExceptionInfo> handleHttpMessageNotReadableException(final HttpServletRequest request,
final Exception ex) { final Exception ex) {
LOG.debug("Handling exception {} of request {}", ex.getClass().getName(), request.getRequestURL()); logRequest(request, ex);
final ExceptionInfo response = new ExceptionInfo(); final ExceptionInfo response = createExceptionInfo(new MessageNotReadableException());
response.setErrorCode(SpServerError.SP_REST_BODY_NOT_READABLE.getKey());
response.setMessage(SpServerError.SP_REST_BODY_NOT_READABLE.getMessage());
response.setExceptionClass(MessageNotReadableException.class.getName());
return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
} }
@@ -139,35 +133,30 @@ public class ResponseExceptionHandler {
* as entity. * as entity.
*/ */
@ExceptionHandler(MultipartException.class) @ExceptionHandler(MultipartException.class)
public ResponseEntity<ExceptionInfo> handleFileLimitExceededException(final HttpServletRequest request, public ResponseEntity<ExceptionInfo> handleMultipartException(final HttpServletRequest request,
final Exception ex) { final Exception ex) {
LOG.debug("Handling exception {} of request {}", ex.getClass().getName(), request.getRequestURL());
final ExceptionInfo response = new ExceptionInfo(); logRequest(request, ex);
if (searchForCause(ex, FileSizeLimitExceededException.class)) {
response.setErrorCode(SpServerError.SP_ARTIFACT_UPLOAD_FILE_LIMIT_EXCEEDED.getKey());
response.setMessage(SpServerError.SP_ARTIFACT_UPLOAD_FILE_LIMIT_EXCEEDED.getMessage());
response.setExceptionClass(FileSizeLimitExceededException.class.getName());
} else {
response.setErrorCode(SpServerError.SP_ARTIFACT_UPLOAD_FAILED.getKey());
response.setMessage(SpServerError.SP_ARTIFACT_UPLOAD_FAILED.getMessage());
response.setExceptionClass(MultipartException.class.getName());
}
final List<Throwable> throwables = ExceptionUtils.getThrowableList(ex);
final Throwable responseCause = Iterables.getLast(throwables);
final ExceptionInfo response = createExceptionInfo(new MultiPartFileUploadException(responseCause));
return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
} }
private static boolean searchForCause(final Throwable t, final Class<?> lookFor) { private void logRequest(final HttpServletRequest request, final Exception ex) {
if (t != null && t.getCause() != null) { LOG.debug("Handling exception {} of request {}", ex.getClass().getName(), request.getRequestURL());
if (t.getCause().getClass().isAssignableFrom(lookFor)) { }
return true;
} else { private ExceptionInfo createExceptionInfo(final Exception ex) {
return searchForCause(t.getCause(), lookFor); final ExceptionInfo response = new ExceptionInfo();
} response.setMessage(ex.getMessage());
response.setExceptionClass(ex.getClass().getName());
if (ex instanceof SpServerRtException) {
response.setErrorCode(((SpServerRtException) ex).getError().getKey());
} }
return false; return response;
} }
} }

View File

@@ -367,11 +367,7 @@ public abstract class JsonBuilder {
} }
/** public static String targets(final List<Target> targets, final boolean withToken) {
* @param targets
* @return
*/
public static String targets(final List<Target> targets) {
final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();
builder.append("["); builder.append("[");
@@ -381,10 +377,12 @@ public abstract class JsonBuilder {
final String address = target.getTargetInfo().getAddress() != null final String address = target.getTargetInfo().getAddress() != null
? target.getTargetInfo().getAddress().toString() : null; ? target.getTargetInfo().getAddress().toString() : null;
final String token = withToken ? target.getSecurityToken() : null;
builder.append(new JSONObject().put("controllerId", target.getControllerId()) builder.append(new JSONObject().put("controllerId", target.getControllerId())
.put("description", target.getDescription()).put("name", target.getName()).put("createdAt", "0") .put("description", target.getDescription()).put("name", target.getName()).put("createdAt", "0")
.put("updatedAt", "0").put("createdBy", "fghdfkjghdfkjh").put("updatedBy", "fghdfkjghdfkjh") .put("updatedAt", "0").put("createdBy", "fghdfkjghdfkjh").put("updatedBy", "fghdfkjghdfkjh")
.put("address", address).toString()); .put("address", address).put("securityToken", token).toString());
} catch (final Exception e) { } catch (final Exception e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@@ -224,8 +224,10 @@ public final class SpPermission {
/* /*
* Spring security eval expressions. * Spring security eval expressions.
*/ */
private static final String HAS_AUTH_PREFIX = "hasAuthority('"; private static final String BRACKET_OPEN = "(";
private static final String HAS_AUTH_SUFFIX = "')"; private static final String BRACKET_CLOSE = ")";
private static final String HAS_AUTH_PREFIX = "hasAuthority" + BRACKET_OPEN + "'";
private static final String HAS_AUTH_SUFFIX = "'" + BRACKET_CLOSE;
private static final String HAS_AUTH_AND = " and "; private static final String HAS_AUTH_AND = " and ";
/** /**
@@ -257,99 +259,6 @@ public final class SpPermission {
*/ */
public static final String HAS_AUTH_OR = " or "; public static final String HAS_AUTH_OR = " or ";
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#UPDATE_TARGET}.
*/
public static final String HAS_AUTH_UPDATE_TARGET = HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#SYSTEM_ADMIN}.
*/
public static final String HAS_AUTH_SYSTEM_ADMIN = HAS_AUTH_PREFIX + SYSTEM_ADMIN + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_TARGET}.
*/
public static final String HAS_AUTH_READ_TARGET = HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_TARGET}.
*/
public static final String HAS_AUTH_CREATE_TARGET = HAS_AUTH_PREFIX + CREATE_TARGET + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DELETE_TARGET}.
*/
public static final String HAS_AUTH_DELETE_TARGET = HAS_AUTH_PREFIX + DELETE_TARGET + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} and
* {@link SpPermission#UPDATE_TARGET}.
*/
public static final String HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET = HAS_AUTH_PREFIX + READ_REPOSITORY
+ HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_REPOSITORY}.
*/
public static final String HAS_AUTH_CREATE_REPOSITORY = HAS_AUTH_PREFIX + CREATE_REPOSITORY + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DELETE_REPOSITORY}.
*/
public static final String HAS_AUTH_DELETE_REPOSITORY = HAS_AUTH_PREFIX + DELETE_REPOSITORY + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY}.
*/
public static final String HAS_AUTH_READ_REPOSITORY = HAS_AUTH_PREFIX + READ_REPOSITORY + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#UPDATE_REPOSITORY}.
*/
public static final String HAS_AUTH_UPDATE_REPOSITORY = HAS_AUTH_PREFIX + UPDATE_REPOSITORY + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} and
* {@link SpPermission#READ_TARGET}.
*/
public static final String HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET = HAS_AUTH_PREFIX + READ_REPOSITORY
+ HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DOWNLOAD_REPOSITORY_ARTIFACT}.
*/
public static final String HAS_AUTH_DOWNLOAD_ARTIFACT = HAS_AUTH_PREFIX + DOWNLOAD_REPOSITORY_ARTIFACT
+ HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAnyRole expression to check if the spring
* context contains the anoynmous role or the controller specific role
* {@link SpPermission#CONTROLLER_ROLE}.
*/
public static final String IS_CONTROLLER = "hasAnyRole('" + CONTROLLER_ROLE_ANONYMOUS + "', '" + CONTROLLER_ROLE
+ "')";
/**
* Spring security eval hasAuthority expression to check if the spring
* context contains the role to allow controllers to download specific
* role {@link SpPermission#CONTROLLER_DOWNLOAD_ROLE}.
*/
public static final String HAS_CONTROLLER_DOWNLOAD = HAS_AUTH_PREFIX + CONTROLLER_DOWNLOAD_ROLE
+ HAS_AUTH_SUFFIX;
/** /**
* Spring security eval hasAnyRole expression to check if the spring * Spring security eval hasAnyRole expression to check if the spring
* context contains system code role * context contains system code role
@@ -359,48 +268,168 @@ public final class SpPermission {
/** /**
* Spring security eval hasAuthority expression to check if spring * Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_REPOSITORY} and * context contains {@link SpPermission#UPDATE_TARGET} or
* {@link SpPermission#CREATE_TARGET}. * {@link #IS_SYSTEM_CODE}.
*/ */
public static final String HAS_AUTH_CREATE_REPOSITORY_AND_CREATE_TARGET = HAS_AUTH_PREFIX + CREATE_REPOSITORY public static final String HAS_AUTH_UPDATE_TARGET = HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX
+ HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + CREATE_TARGET + HAS_AUTH_SUFFIX; + HAS_AUTH_OR + IS_SYSTEM_CODE;
/** /**
* Spring security eval hasAuthority expression to check if spring * Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#ROLLOUT_MANAGEMENT} * context contains {@link SpPermission#SYSTEM_ADMIN} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_SYSTEM_ADMIN = HAS_AUTH_PREFIX + SYSTEM_ADMIN + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_TARGET} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_TARGET = HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX + HAS_AUTH_OR
+ IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_TARGET} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_CREATE_TARGET = HAS_AUTH_PREFIX + CREATE_TARGET + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DELETE_TARGET} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_DELETE_TARGET = HAS_AUTH_PREFIX + DELETE_TARGET + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} and
* {@link SpPermission#UPDATE_TARGET} or {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET = BRACKET_OPEN + HAS_AUTH_PREFIX
+ READ_REPOSITORY + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX
+ BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_REPOSITORY} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_CREATE_REPOSITORY = HAS_AUTH_PREFIX + CREATE_REPOSITORY + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DELETE_REPOSITORY} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_DELETE_REPOSITORY = HAS_AUTH_PREFIX + DELETE_REPOSITORY + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_REPOSITORY = HAS_AUTH_PREFIX + READ_REPOSITORY + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#UPDATE_REPOSITORY} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_UPDATE_REPOSITORY = HAS_AUTH_PREFIX + UPDATE_REPOSITORY + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} and
* {@link SpPermission#READ_TARGET} or {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET = BRACKET_OPEN + HAS_AUTH_PREFIX
+ READ_REPOSITORY + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX
+ BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DOWNLOAD_REPOSITORY_ARTIFACT} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_DOWNLOAD_ARTIFACT = HAS_AUTH_PREFIX + DOWNLOAD_REPOSITORY_ARTIFACT
+ HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAnyRole expression to check if the spring
* context contains the anoynmous role or the controller specific role
* {@link SpringEvalExpressions#CONTROLLER_ROLE}.
*/
public static final String IS_CONTROLLER = "hasAnyRole('" + CONTROLLER_ROLE_ANONYMOUS + "', '" + CONTROLLER_ROLE
+ "')";
/**
* Spring security eval hasAuthority expression to check if the spring
* context contains the role to allow controllers to download specific
* role {@link SpringEvalExpressions#CONTROLLER_DOWNLOAD_ROLE}
*/
public static final String HAS_CONTROLLER_DOWNLOAD = HAS_AUTH_PREFIX + CONTROLLER_DOWNLOAD_ROLE
+ HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_REPOSITORY} and
* {@link SpPermission#CREATE_TARGET} or {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_CREATE_REPOSITORY_AND_CREATE_TARGET = BRACKET_OPEN + HAS_AUTH_PREFIX
+ CREATE_REPOSITORY + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + CREATE_TARGET + HAS_AUTH_SUFFIX
+ BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#ROLLOUT_MANAGEMENT} or
* {@link #IS_SYSTEM_CODE}.
*/ */
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_READ = HAS_AUTH_PREFIX + ROLLOUT_MANAGEMENT public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_READ = HAS_AUTH_PREFIX + ROLLOUT_MANAGEMENT
+ HAS_AUTH_SUFFIX; + HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
/** /**
* Spring security eval hasAuthority expression to check if spring * Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#ROLLOUT_MANAGEMENT} and * context contains {@link SpPermission#ROLLOUT_MANAGEMENT} and
* {@link SpPermission#READ_TARGET} * {@link SpPermission#READ_TARGET} or {@link #IS_SYSTEM_CODE}.
*/ */
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ = HAS_AUTH_PREFIX public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ = BRACKET_OPEN + HAS_AUTH_PREFIX
+ ROLLOUT_MANAGEMENT + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + READ_TARGET + ROLLOUT_MANAGEMENT + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX
+ HAS_AUTH_SUFFIX;; + BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/** /**
* Spring security eval hasAuthority expression to check if spring * Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#ROLLOUT_MANAGEMENT} and * context contains {@link SpPermission#ROLLOUT_MANAGEMENT} and
* {@link SpPermission#UPDATE_TARGET}. * {@link SpPermission#UPDATE_TARGET} or {@link #IS_SYSTEM_CODE}.
*/ */
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE = HAS_AUTH_PREFIX + ROLLOUT_MANAGEMENT public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE = BRACKET_OPEN + HAS_AUTH_PREFIX
+ HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX; + ROLLOUT_MANAGEMENT + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + UPDATE_TARGET
+ HAS_AUTH_SUFFIX + BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/** /**
* Spring security eval hasAuthority expression to check if spring * Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#TENANT_CONFIGURATION} * context contains {@link SpPermission#TENANT_CONFIGURATION} or
* {@link #IS_SYSTEM_CODE}.
*/ */
public static final String HAS_AUTH_TENANT_CONFIGURATION = HAS_AUTH_PREFIX + TENANT_CONFIGURATION public static final String HAS_AUTH_TENANT_CONFIGURATION = HAS_AUTH_PREFIX + TENANT_CONFIGURATION
+ HAS_AUTH_SUFFIX; + HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
/** /**
* Spring security eval hasAuthority expression to check if spring * Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#SYSTEM_MONITOR} * context contains {@link SpPermission#SYSTEM_MONITOR} or
* {@link #IS_SYSTEM_CODE}.
*/ */
public static final String HAS_AUTH_SYSTEM_MONITOR = HAS_AUTH_PREFIX + SYSTEM_MONITOR + HAS_AUTH_SUFFIX; public static final String HAS_AUTH_SYSTEM_MONITOR = HAS_AUTH_PREFIX + SYSTEM_MONITOR + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
private SpringEvalExpressions() { private SpringEvalExpressions() {
// utility class // utility class

View File

@@ -8,13 +8,15 @@
*/ */
package org.eclipse.hawkbit.security; package org.eclipse.hawkbit.security;
import java.util.concurrent.atomic.AtomicInteger; import java.util.Collection;
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails; import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
/** /**
* A {@link TenantAware} implemenation which retrieves the ID of the tenant from * A {@link TenantAware} implemenation which retrieves the ID of the tenant from
@@ -22,15 +24,9 @@ import org.springframework.security.core.context.SecurityContextHolder;
* {@link Authentication#getDetails()} which holds the * {@link Authentication#getDetails()} which holds the
* {@link TenantAwareAuthenticationDetails} object. * {@link TenantAwareAuthenticationDetails} object.
* *
*
*
*
*/ */
public class SecurityContextTenantAware implements TenantAware { public class SecurityContextTenantAware implements TenantAware {
private static final ThreadLocal<String> TENANT_THREAD_LOCAL = new ThreadLocal<>();
private static final ThreadLocal<AtomicInteger> RUN_AS_DEPTH = new ThreadLocal<>();
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
@@ -38,9 +34,6 @@ public class SecurityContextTenantAware implements TenantAware {
*/ */
@Override @Override
public String getCurrentTenant() { public String getCurrentTenant() {
if (TENANT_THREAD_LOCAL.get() != null) {
return TENANT_THREAD_LOCAL.get();
}
final SecurityContext context = SecurityContextHolder.getContext(); final SecurityContext context = SecurityContextHolder.getContext();
if (context.getAuthentication() != null) { if (context.getAuthentication() != null) {
final Object authDetails = context.getAuthentication().getDetails(); final Object authDetails = context.getAuthentication().getDetails();
@@ -51,29 +44,88 @@ public class SecurityContextTenantAware implements TenantAware {
return null; return null;
} }
/*
* (non-Javadoc)
*
* @see hawkbit.server.tenancy.TenantAware#runAsTenant(java.lang.String,
* java.util.concurrent.Callable)
*/
@Override @Override
public <T> T runAsTenant(final String tenant, final TenantRunner<T> callable) { public <T> T runAsTenant(final String tenant, final TenantRunner<T> callable) {
AtomicInteger runAsDepth = RUN_AS_DEPTH.get(); final SecurityContext originalContext = SecurityContextHolder.getContext();
if (runAsDepth == null) {
runAsDepth = new AtomicInteger(1);
RUN_AS_DEPTH.set(runAsDepth);
} else {
runAsDepth.incrementAndGet();
}
TENANT_THREAD_LOCAL.set(tenant);
try { try {
SecurityContextHolder.setContext(buildSecurityContext(tenant));
return callable.run(); return callable.run();
} finally { } finally {
if (runAsDepth.decrementAndGet() <= 0) { SecurityContextHolder.setContext(originalContext);
RUN_AS_DEPTH.remove(); }
TENANT_THREAD_LOCAL.remove(); }
}
private SecurityContext buildSecurityContext(final String tenant) {
final SecurityContextImpl securityContext = new SecurityContextImpl();
securityContext.setAuthentication(
new AuthenticationDelegate(SecurityContextHolder.getContext().getAuthentication(), tenant));
return securityContext;
}
/**
* An {@link Authentication} implementation to delegate to an existing
* {@link Authentication} object except setting the details specifically for
* a specific tenant.
*/
private class AuthenticationDelegate implements Authentication {
private static final long serialVersionUID = 1L;
private final Authentication delegate;
private final TenantAwareAuthenticationDetails tenantAwareAuthenticationDetails;
private AuthenticationDelegate(final Authentication delegate, final String tenant) {
this.delegate = delegate;
tenantAwareAuthenticationDetails = new TenantAwareAuthenticationDetails(tenant, false);
}
@Override
public boolean equals(final Object another) {
return delegate.equals(another);
}
@Override
public String toString() {
return delegate.toString();
}
@Override
public int hashCode() {
return delegate.hashCode();
}
@Override
public String getName() {
return delegate.getName();
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return delegate.getAuthorities();
}
@Override
public Object getCredentials() {
return delegate.getCredentials();
}
@Override
public Object getDetails() {
return tenantAwareAuthenticationDetails;
}
@Override
public Object getPrincipal() {
return delegate.getPrincipal();
}
@Override
public boolean isAuthenticated() {
return delegate.isAuthenticated();
}
@Override
public void setAuthenticated(final boolean isAuthenticated) throws IllegalArgumentException {
delegate.setAuthenticated(isAuthenticated);
} }
} }
} }

View File

@@ -72,7 +72,7 @@ public class SystemSecurityContext {
logger.debug("entering system code execution"); logger.debug("entering system code execution");
return tenantAware.runAsTenant(tenantAware.getCurrentTenant(), () -> { return tenantAware.runAsTenant(tenantAware.getCurrentTenant(), () -> {
try { try {
setSystemContext(); setSystemContext(oldContext);
return callable.call(); return callable.call();
} catch (final Exception e) { } catch (final Exception e) {
throw Throwables.propagate(e); throw Throwables.propagate(e);
@@ -93,9 +93,10 @@ public class SystemSecurityContext {
return SecurityContextHolder.getContext().getAuthentication() instanceof SystemCodeAuthentication; return SecurityContextHolder.getContext().getAuthentication() instanceof SystemCodeAuthentication;
} }
private static void setSystemContext() { private static void setSystemContext(final SecurityContext oldContext) {
final Authentication oldAuthentication = oldContext.getAuthentication();
final SecurityContextImpl securityContextImpl = new SecurityContextImpl(); final SecurityContextImpl securityContextImpl = new SecurityContextImpl();
securityContextImpl.setAuthentication(new SystemCodeAuthentication()); securityContextImpl.setAuthentication(new SystemCodeAuthentication(oldAuthentication));
SecurityContextHolder.setContext(securityContextImpl); SecurityContextHolder.setContext(securityContextImpl);
} }
@@ -104,6 +105,11 @@ public class SystemSecurityContext {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final List<SimpleGrantedAuthority> AUTHORITIES = Collections private static final List<SimpleGrantedAuthority> AUTHORITIES = Collections
.singletonList(new SimpleGrantedAuthority(SpringEvalExpressions.SYSTEM_ROLE)); .singletonList(new SimpleGrantedAuthority(SpringEvalExpressions.SYSTEM_ROLE));
private final Authentication oldAuthentication;
private SystemCodeAuthentication(final Authentication oldAuthentication) {
this.oldAuthentication = oldAuthentication;
}
@Override @Override
public String getName() { public String getName() {
@@ -117,17 +123,17 @@ public class SystemSecurityContext {
@Override @Override
public Object getCredentials() { public Object getCredentials() {
return null; return oldAuthentication != null ? oldAuthentication.getCredentials() : null;
} }
@Override @Override
public Object getDetails() { public Object getDetails() {
return null; return oldAuthentication != null ? oldAuthentication.getDetails() : null;
} }
@Override @Override
public Object getPrincipal() { public Object getPrincipal() {
return null; return oldAuthentication != null ? oldAuthentication.getPrincipal() : null;
} }
@Override @Override

View File

@@ -200,6 +200,10 @@
<groupId>org.springframework.security</groupId> <groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId> <artifactId>spring-security-web</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.vaadin</groupId> <groupId>com.vaadin</groupId>

View File

@@ -10,6 +10,8 @@ package org.eclipse.hawkbit.ui.artifacts.smtable;
import java.io.Serializable; import java.io.Serializable;
import javax.annotation.PostConstruct;
import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareManagement; import org.eclipse.hawkbit.repository.SoftwareManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
@@ -18,18 +20,17 @@ import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery; import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; 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.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.I18N; import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions; import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UINotification; import org.eclipse.hawkbit.ui.utils.UINotification;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory; import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
import org.vaadin.spring.events.EventBus; import org.vaadin.spring.events.EventBus;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope; import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.ComboBox; import com.vaadin.ui.ComboBox;
@@ -38,8 +39,6 @@ import com.vaadin.ui.FormLayout;
import com.vaadin.ui.Label; import com.vaadin.ui.Label;
import com.vaadin.ui.TextArea; import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField; import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.Window;
import com.vaadin.ui.themes.ValoTheme; import com.vaadin.ui.themes.ValoTheme;
/** /**
@@ -66,8 +65,6 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
@Autowired @Autowired
private transient EntityFactory entityFactory; private transient EntityFactory entityFactory;
private Label mandatoryLabel;
private TextField nameTextField; private TextField nameTextField;
private TextField versionTextField; private TextField versionTextField;
@@ -80,14 +77,20 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
private CommonDialogWindow window; private CommonDialogWindow window;
private String oldDescriptionValue;
private String oldVendorValue;
private Boolean editSwModule = Boolean.FALSE; private Boolean editSwModule = Boolean.FALSE;
private Long baseSwModuleId; private Long baseSwModuleId;
private FormLayout formLayout;
/**
* Initialize Distribution Add and Edit Window.
*/
@PostConstruct
void init() {
createRequiredComponents();
}
/** /**
* Create window for new software module. * Create window for new software module.
* *
@@ -95,11 +98,7 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
* module. * module.
*/ */
public CommonDialogWindow createAddSoftwareModuleWindow() { public CommonDialogWindow createAddSoftwareModuleWindow() {
return createUpdateSoftwareModuleWindow(null);
editSwModule = Boolean.FALSE;
createRequiredComponents();
createWindow();
return window;
} }
/** /**
@@ -110,17 +109,11 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
* @return reference of {@link com.vaadin.ui.Window} to update software * @return reference of {@link com.vaadin.ui.Window} to update software
* module. * module.
*/ */
public Window createUpdateSoftwareModuleWindow(final Long baseSwModuleId) { public CommonDialogWindow createUpdateSoftwareModuleWindow(final Long baseSwModuleId) {
editSwModule = Boolean.TRUE;
this.baseSwModuleId = baseSwModuleId; this.baseSwModuleId = baseSwModuleId;
createRequiredComponents(); resetComponents();
createWindow();
/* populate selected target values to edit. */
populateValuesOfSwModule(); populateValuesOfSwModule();
nameTextField.setEnabled(false); createWindow();
versionTextField.setEnabled(false);
typeComboBox.setEnabled(false);
return window; return window;
} }
@@ -145,13 +138,6 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
ValoTheme.TEXTAREA_TINY, false, null, i18n.get("textfield.description"), ValoTheme.TEXTAREA_TINY, false, null, i18n.get("textfield.description"),
SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH); SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
descTextArea.setId(SPUIComponentIdProvider.ADD_SW_MODULE_DESCRIPTION); descTextArea.setId(SPUIComponentIdProvider.ADD_SW_MODULE_DESCRIPTION);
addDescriptionTextChangeListener();
addVendorTextChangeListener();
/* Label for mandatory symbol */
mandatoryLabel = new Label(i18n.get("label.mandatory.field"));
mandatoryLabel.setStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR);
mandatoryLabel.addStyleName(ValoTheme.LABEL_SMALL);
typeComboBox = SPUIComponentProvider.getComboBox(i18n.get("upload.swmodule.type"), "", "", null, null, true, typeComboBox = SPUIComponentProvider.getComboBox(i18n.get("upload.swmodule.type"), "", "", null, null, true,
null, i18n.get("upload.swmodule.type")); null, i18n.get("upload.swmodule.type"));
@@ -159,46 +145,34 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
typeComboBox.setStyleName(SPUIDefinitions.COMBO_BOX_SPECIFIC_STYLE + " " + ValoTheme.COMBOBOX_TINY); typeComboBox.setStyleName(SPUIDefinitions.COMBO_BOX_SPECIFIC_STYLE + " " + ValoTheme.COMBOBOX_TINY);
typeComboBox.setNewItemsAllowed(Boolean.FALSE); typeComboBox.setNewItemsAllowed(Boolean.FALSE);
typeComboBox.setImmediate(Boolean.TRUE); typeComboBox.setImmediate(Boolean.TRUE);
populateTypeNameCombo(); populateTypeNameCombo();
resetOldValues();
} }
/**
*
*/
private void populateTypeNameCombo() { private void populateTypeNameCombo() {
typeComboBox.setContainerDataSource(HawkbitCommonUtil.createLazyQueryContainer( typeComboBox.setContainerDataSource(HawkbitCommonUtil.createLazyQueryContainer(
new BeanQueryFactory<SoftwareModuleTypeBeanQuery>(SoftwareModuleTypeBeanQuery.class))); new BeanQueryFactory<SoftwareModuleTypeBeanQuery>(SoftwareModuleTypeBeanQuery.class)));
typeComboBox.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME); typeComboBox.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME);
} }
private void resetOldValues() { private void resetComponents() {
oldDescriptionValue = null;
oldVendorValue = null; vendorTextField.clear();
nameTextField.clear();
versionTextField.clear();
descTextArea.clear();
typeComboBox.clear();
editSwModule = Boolean.FALSE;
} }
/**
* Build the window content and get an instance of customDialogWindow
*
*/
private void createWindow() { private void createWindow() {
final Label madatoryStarLabel = new Label("*"); final Label madatoryStarLabel = new Label("*");
madatoryStarLabel.setStyleName("v-caption v-required-field-indicator"); madatoryStarLabel.setStyleName("v-caption v-required-field-indicator");
madatoryStarLabel.setWidth(null); madatoryStarLabel.setWidth(null);
/*
* The main layout of the window contains mandatory info, textboxes
* (controller Id, name & description) and action buttons layout
*/
addStyleName("lay-color"); addStyleName("lay-color");
setSizeUndefined(); setSizeUndefined();
final FormLayout formLayout = new FormLayout(); formLayout = new FormLayout();
formLayout.addComponent(mandatoryLabel); formLayout.setCaption(null);
formLayout.addComponent(typeComboBox); formLayout.addComponent(typeComboBox);
formLayout.addComponent(nameTextField); formLayout.addComponent(nameTextField);
formLayout.addComponent(versionTextField); formLayout.addComponent(versionTextField);
@@ -207,24 +181,17 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
setCompositionRoot(formLayout); setCompositionRoot(formLayout);
/* add main layout to the window */ window = SPUIWindowDecorator.getWindow(i18n.get("upload.caption.add.new.swmodule"), null,
window = SPUIComponentProvider.getWindow(i18n.get("upload.caption.add.new.swmodule"), null, SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> saveOrUpdate(), null, null, formLayout, i18n);
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> saveOrUpdate(), event -> closeThisWindow(), null);
window.getButtonsLayout().removeStyleName("actionButtonsMargin"); window.getButtonsLayout().removeStyleName("actionButtonsMargin");
nameTextField.focus();
nameTextField.setEnabled(!editSwModule);
versionTextField.setEnabled(!editSwModule);
typeComboBox.setEnabled(!editSwModule);
typeComboBox.focus();
} }
private void addDescriptionTextChangeListener() {
descTextArea.addTextChangeListener(event -> window.setSaveButtonEnabled(hasDescriptionChanged(event)));
}
private void addVendorTextChangeListener() {
vendorTextField.addTextChangeListener(event -> window.setSaveButtonEnabled(hasVendorChanged(event)));
}
/**
* Add new SW module.
*/
private void addNewBaseSoftware() { private void addNewBaseSoftware() {
final String name = HawkbitCommonUtil.trimAndNullIfEmpty(nameTextField.getValue()); final String name = HawkbitCommonUtil.trimAndNullIfEmpty(nameTextField.getValue());
final String version = HawkbitCommonUtil.trimAndNullIfEmpty(versionTextField.getValue()); final String version = HawkbitCommonUtil.trimAndNullIfEmpty(versionTextField.getValue());
@@ -232,10 +199,6 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
final String description = HawkbitCommonUtil.trimAndNullIfEmpty(descTextArea.getValue()); final String description = HawkbitCommonUtil.trimAndNullIfEmpty(descTextArea.getValue());
final String type = typeComboBox.getValue() != null ? typeComboBox.getValue().toString() : null; final String type = typeComboBox.getValue() != null ? typeComboBox.getValue().toString() : null;
if (!mandatoryCheck(name, version, type)) {
return;
}
if (HawkbitCommonUtil.isDuplicate(name, version, type)) { if (HawkbitCommonUtil.isDuplicate(name, version, type)) {
uiNotifcation.displayValidationError( uiNotifcation.displayValidationError(
i18n.get("message.duplicate.softwaremodule", new Object[] { name, version })); i18n.get("message.duplicate.softwaremodule", new Object[] { name, version }));
@@ -248,8 +211,6 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
new Object[] { newBaseSoftwareModule.getName() + ":" + newBaseSoftwareModule.getVersion() })); new Object[] { newBaseSoftwareModule.getName() + ":" + newBaseSoftwareModule.getVersion() }));
eventBus.publish(this, new SoftwareModuleEvent(BaseEntityEventType.NEW_ENTITY, newBaseSoftwareModule)); eventBus.publish(this, new SoftwareModuleEvent(BaseEntityEventType.NEW_ENTITY, newBaseSoftwareModule));
} }
// close the window
closeThisWindow();
} }
} }
@@ -269,13 +230,16 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
eventBus.publish(this, new SoftwareModuleEvent(BaseEntityEventType.UPDATED_ENTITY, newSWModule)); eventBus.publish(this, new SoftwareModuleEvent(BaseEntityEventType.UPDATED_ENTITY, newSWModule));
} }
closeThisWindow();
} }
/** /**
* fill the data of a softwareModule in the content of the window * fill the data of a softwareModule in the content of the window
*/ */
private void populateValuesOfSwModule() { private void populateValuesOfSwModule() {
if (baseSwModuleId == null) {
return;
}
editSwModule = Boolean.TRUE;
final SoftwareModule swModle = softwareManagement.findSoftwareModuleById(baseSwModuleId); final SoftwareModule swModle = softwareManagement.findSoftwareModuleById(baseSwModuleId);
nameTextField.setValue(swModle.getName()); nameTextField.setValue(swModle.getName());
versionTextField.setValue(swModle.getVersion()); versionTextField.setValue(swModle.getVersion());
@@ -283,49 +247,10 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
: HawkbitCommonUtil.trimAndNullIfEmpty(swModle.getVendor())); : HawkbitCommonUtil.trimAndNullIfEmpty(swModle.getVendor()));
descTextArea.setValue(swModle.getDescription() == null ? HawkbitCommonUtil.SP_STRING_EMPTY descTextArea.setValue(swModle.getDescription() == null ? HawkbitCommonUtil.SP_STRING_EMPTY
: HawkbitCommonUtil.trimAndNullIfEmpty(swModle.getDescription())); : HawkbitCommonUtil.trimAndNullIfEmpty(swModle.getDescription()));
oldDescriptionValue = descTextArea.getValue();
oldVendorValue = vendorTextField.getValue();
if (swModle.getType().isDeleted()) { if (swModle.getType().isDeleted()) {
typeComboBox.addItem(swModle.getType().getName()); typeComboBox.addItem(swModle.getType().getName());
} }
typeComboBox.setValue(swModle.getType().getName()); typeComboBox.setValue(swModle.getType().getName());
window.setSaveButtonEnabled(Boolean.FALSE);
}
/**
* Method to close window.
*/
private void closeThisWindow() {
window.close();
UI.getCurrent().removeWindow(window);
}
/**
* Validation check - Mandatory.
*
* @param name
* as String
* @param version
* as version
* @return boolena as flag
*/
private boolean mandatoryCheck(final String name, final String version, final String type) {
boolean isValid = true;
if (name == null || version == null || type == null) {
if (name == null) {
nameTextField.addStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR);
}
if (version == null) {
versionTextField.addStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR);
}
if (type == null) {
typeComboBox.addStyleName(SPUIStyleDefinitions.SP_COMBOFIELD_ERROR);
}
uiNotifcation.displayValidationError(i18n.get("message.mandatory.check"));
isValid = false;
}
return isValid;
} }
private void saveOrUpdate() { private void saveOrUpdate() {
@@ -336,12 +261,8 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
} }
} }
private boolean hasDescriptionChanged(final TextChangeEvent event) { public FormLayout getFormLayout() {
return !(event.getText().equals(oldDescriptionValue) && vendorTextField.getValue().equals(oldVendorValue)); return formLayout;
}
private boolean hasVendorChanged(final TextChangeEvent event) {
return !(event.getText().equals(oldVendorValue) && descTextArea.getValue().equals(oldDescriptionValue));
} }
} }

View File

@@ -51,7 +51,6 @@ import com.vaadin.ui.UI;
/** /**
* Header of Software module table. * Header of Software module table.
*
*/ */
@SpringComponent @SpringComponent
@ViewScope @ViewScope

View File

@@ -11,13 +11,11 @@ package org.eclipse.hawkbit.ui.artifacts.smtype;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareManagement; import org.eclipse.hawkbit.repository.SoftwareManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent; import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent.SoftwareModuleTypeEnum; import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent.SoftwareModuleTypeEnum;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerConstants;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper; import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery; import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
@@ -34,12 +32,10 @@ import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.shared.ui.colorpicker.Color; import com.vaadin.shared.ui.colorpicker.Color;
import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope; import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Label; import com.vaadin.ui.Label;
import com.vaadin.ui.OptionGroup; import com.vaadin.ui.OptionGroup;
import com.vaadin.ui.components.colorpicker.ColorChangeListener; import com.vaadin.ui.components.colorpicker.ColorChangeListener;
import com.vaadin.ui.components.colorpicker.ColorSelector;
import com.vaadin.ui.themes.ValoTheme; import com.vaadin.ui.themes.ValoTheme;
/** /**
@@ -48,8 +44,7 @@ import com.vaadin.ui.themes.ValoTheme;
*/ */
@SpringComponent @SpringComponent
@ViewScope @ViewScope
public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout {
implements ColorChangeListener, ColorSelector {
private static final long serialVersionUID = -5169398523815919367L; private static final long serialVersionUID = -5169398523815919367L;
private static final Logger LOG = LoggerFactory.getLogger(CreateUpdateSoftwareTypeLayout.class); private static final Logger LOG = LoggerFactory.getLogger(CreateUpdateSoftwareTypeLayout.class);
@@ -69,7 +64,7 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
@Override @Override
protected void addListeners() { protected void addListeners() {
super.addListeners(); super.addListeners();
optiongroup.addValueChangeListener(this::createOptionValueChanged); optiongroup.addValueChangeListener(this::optionValueChanged);
} }
@Override @Override
@@ -95,7 +90,6 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
tagDesc = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "", tagDesc = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "",
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_DESC, false, "", ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_DESC, false, "",
i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH); i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
tagDesc.setId(SPUIDefinitions.NEW_SOFTWARE_TYPE_DESC); tagDesc.setId(SPUIDefinitions.NEW_SOFTWARE_TYPE_DESC);
tagDesc.setImmediate(true); tagDesc.setImmediate(true);
tagDesc.setNullRepresentation(""); tagDesc.setNullRepresentation("");
@@ -113,10 +107,8 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
} }
@Override @Override
public void createWindow() { protected String getWindowCaption() {
reset(); return i18n.get("caption.add.type");
window = SPUIComponentProvider.getWindow(i18n.get("caption.add.type"), null,
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, this::save, this::discard, null);
} }
/** /**
@@ -126,15 +118,16 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
* ValueChangeEvent * ValueChangeEvent
*/ */
@Override @Override
protected void createOptionValueChanged(final ValueChangeEvent event) { protected void optionValueChanged(final ValueChangeEvent event) {
super.createOptionValueChanged(event); super.optionValueChanged(event);
if (updateTypeStr.equals(event.getProperty().getValue())) { if (updateTypeStr.equals(event.getProperty().getValue())) {
assignOptiongroup.setEnabled(false); assignOptiongroup.setEnabled(false);
} else { } else {
assignOptiongroup.setEnabled(true); assignOptiongroup.setEnabled(true);
} }
assignOptiongroup.select(singleAssignStr);
} }
/** /**
@@ -176,7 +169,6 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
} else { } else {
assignOptiongroup.setValue(singleAssignStr); assignOptiongroup.setValue(singleAssignStr);
} }
setColorPickerComponentsColor(selectedTypeTag.getColour()); setColorPickerComponentsColor(selectedTypeTag.getColour());
} }
} }
@@ -198,10 +190,6 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
@Override @Override
protected void save(final ClickEvent event) { protected void save(final ClickEvent event) {
if (!mandatoryValuesPresent()) {
return;
}
final SoftwareModuleType existingSMTypeByKey = swTypeManagementService final SoftwareModuleType existingSMTypeByKey = swTypeManagementService
.findSoftwareModuleTypeByKey(typeKey.getValue()); .findSoftwareModuleTypeByKey(typeKey.getValue());
final SoftwareModuleType existingSMTypeByName = swTypeManagementService final SoftwareModuleType existingSMTypeByName = swTypeManagementService
@@ -211,7 +199,6 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
createNewSWModuleType(); createNewSWModuleType();
} }
} else { } else {
updateSWModuleType(existingSMTypeByName); updateSWModuleType(existingSMTypeByName);
} }
} }
@@ -233,22 +220,14 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
SoftwareModuleType newSWType = entityFactory.generateSoftwareModuleType(typeKeyValue, typeNameValue, SoftwareModuleType newSWType = entityFactory.generateSoftwareModuleType(typeKeyValue, typeNameValue,
typeDescValue, assignNumber); typeDescValue, assignNumber);
newSWType.setColour(colorPicked); newSWType.setColour(colorPicked);
newSWType.setDescription(typeDescValue);
if (null != typeDescValue) {
newSWType.setDescription(typeDescValue);
}
newSWType.setColour(colorPicked); newSWType.setColour(colorPicked);
newSWType = swTypeManagementService.createSoftwareModuleType(newSWType); newSWType = swTypeManagementService.createSoftwareModuleType(newSWType);
uiNotification.displaySuccess(i18n.get("message.save.success", new Object[] { newSWType.getName() })); uiNotification.displaySuccess(i18n.get("message.save.success", new Object[] { newSWType.getName() }));
closeWindow();
eventBus.publish(this, eventBus.publish(this,
new SoftwareModuleTypeEvent(SoftwareModuleTypeEnum.ADD_SOFTWARE_MODULE_TYPE, newSWType)); new SoftwareModuleTypeEvent(SoftwareModuleTypeEnum.ADD_SOFTWARE_MODULE_TYPE, newSWType));
} else { } else {
uiNotification.displayValidationError(i18n.get("message.error.missing.typenameorkey")); uiNotification.displayValidationError(i18n.get("message.error.missing.typenameorkey"));
} }
} }
@@ -258,51 +237,15 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
final String typeDescValue = HawkbitCommonUtil.trimAndNullIfEmpty(tagDesc.getValue()); final String typeDescValue = HawkbitCommonUtil.trimAndNullIfEmpty(tagDesc.getValue());
if (null != typeNameValue) { if (null != typeNameValue) {
existingType.setName(typeNameValue); existingType.setName(typeNameValue);
existingType.setDescription(typeDescValue);
existingType.setDescription(null != typeDescValue ? typeDescValue : null);
existingType.setColour(ColorPickerHelper.getColorPickedString(getColorPickerLayout().getSelPreview())); existingType.setColour(ColorPickerHelper.getColorPickedString(getColorPickerLayout().getSelPreview()));
swTypeManagementService.updateSoftwareModuleType(existingType); swTypeManagementService.updateSoftwareModuleType(existingType);
uiNotification.displaySuccess(i18n.get("message.update.success", new Object[] { existingType.getName() })); uiNotification.displaySuccess(i18n.get("message.update.success", new Object[] { existingType.getName() }));
closeWindow();
eventBus.publish(this, eventBus.publish(this,
new SoftwareModuleTypeEvent(SoftwareModuleTypeEnum.UPDATE_SOFTWARE_MODULE_TYPE, existingType)); new SoftwareModuleTypeEvent(SoftwareModuleTypeEnum.UPDATE_SOFTWARE_MODULE_TYPE, existingType));
} else { } else {
uiNotification.displayValidationError(i18n.get("message.tag.update.mandatory")); uiNotification.displayValidationError(i18n.get("message.tag.update.mandatory"));
} }
}
/**
* Open color picker on click of preview button. Auto select the color based
* on target tag if already selected.
*/
@Override
protected void previewButtonClicked() {
if (!tagPreviewBtnClicked) {
final String selectedOption = (String) optiongroup.getValue();
if (StringUtils.isNotEmpty(selectedOption) && selectedOption.equalsIgnoreCase(updateTypeStr)) {
if (null != tagNameComboBox.getValue()) {
final SoftwareModuleType typeSelected = swTypeManagementService
.findSoftwareModuleTypeByName(tagNameComboBox.getValue().toString());
if (null != typeSelected) {
getColorPickerLayout().setSelectedColor(typeSelected.getColour() != null
? ColorPickerHelper.rgbToColorConverter(typeSelected.getColour())
: ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR));
}
} else {
getColorPickerLayout().setSelectedColor(
ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR));
}
}
getColorPickerLayout().getSelPreview().setColor(getColorPickerLayout().getSelectedColor());
mainLayout.addComponent(colorPickerLayout, 1, 0);
mainLayout.setComponentAlignment(colorPickerLayout, Alignment.MIDDLE_CENTER);
} else {
mainLayout.removeComponent(colorPickerLayout);
}
tagPreviewBtnClicked = !tagPreviewBtnClicked;
} }
@Override @Override

View File

@@ -13,6 +13,7 @@ import java.util.Set;
import org.eclipse.hawkbit.ui.common.CoordinatesToColor; import org.eclipse.hawkbit.ui.common.CoordinatesToColor;
import org.eclipse.hawkbit.ui.management.tag.SpColorPickerPreview; import org.eclipse.hawkbit.ui.management.tag.SpColorPickerPreview;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import com.vaadin.shared.ui.colorpicker.Color; import com.vaadin.shared.ui.colorpicker.Color;
import com.vaadin.ui.AbstractColorPicker.Coordinates2Color; import com.vaadin.ui.AbstractColorPicker.Coordinates2Color;
@@ -47,6 +48,7 @@ public class ColorPickerLayout extends GridLayout {
setColumns(2); setColumns(2);
setRows(4); setRows(4);
setId(SPUIComponentIdProvider.COLOR_PICKER_LAYOUT);
init(); init();
@@ -71,6 +73,7 @@ public class ColorPickerLayout extends GridLayout {
colorSelect.setWidth("220px"); colorSelect.setWidth("220px");
redSlider = createRGBSlider("", "red"); redSlider = createRGBSlider("", "red");
redSlider.setId(SPUIComponentIdProvider.COLOR_PICKER_RED_SLIDER);
greenSlider = createRGBSlider("", "green"); greenSlider = createRGBSlider("", "green");
blueSlider = createRGBSlider("", "blue"); blueSlider = createRGBSlider("", "blue");

View File

@@ -23,6 +23,7 @@ import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlButtonRenderer; import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlButtonRenderer;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleBorderWithIcon; import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleBorderWithIcon;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder; 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.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.I18N; import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
@@ -102,6 +103,8 @@ public abstract class AbstractMetadataPopupLayout<E extends NamedVersionedEntity
private E selectedEntity; private E selectedEntity;
private HorizontalLayout mainLayout ;
@PostConstruct @PostConstruct
private void init() { private void init() {
createComponents(); createComponents();
@@ -118,21 +121,21 @@ public abstract class AbstractMetadataPopupLayout<E extends NamedVersionedEntity
* metadata to be selected * metadata to be selected
* @return @link{CommonDialogWindow} * @return @link{CommonDialogWindow}
*/ */
public CommonDialogWindow getWindow(final E entity, final M metaData) { public CommonDialogWindow getWindow(final E entity, final M metaData) {
selectedEntity = entity; selectedEntity = entity;
String nameVersion = HawkbitCommonUtil.getFormattedNameVersion(entity.getName(), entity.getVersion()); String nameVersion = HawkbitCommonUtil.getFormattedNameVersion(entity.getName(), entity.getVersion());
metadataWindow = SPUIComponentProvider.getWindow(getMetadataCaption(nameVersion), null, metadataWindow = SPUIWindowDecorator.getWindow(getMetadataCaption(nameVersion), null,
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> onSave(), event -> onCancel(), null); SPUIDefinitions.CUSTOM_METADATA_WINDOW, this, event -> onSave(), event -> onCancel(), null, mainLayout, i18n);
metadataWindow.setId(SPUIComponentIdProvider.METADATA_POPUP_ID); metadataWindow.setId(SPUIComponentIdProvider.METADATA_POPUP_ID);
metadataWindow.setHeight(550, Unit.PIXELS); metadataWindow.setHeight(550, Unit.PIXELS);
metadataWindow.setWidth(800, Unit.PIXELS); metadataWindow.setWidth(800, Unit.PIXELS);
metadataWindow.getMainLayout().setSizeFull(); metadataWindow.getMainLayout().setSizeFull();
metadataWindow.setResizable(true); metadataWindow.setResizable(true);
metadataWindow.addWindowModeChangeListener(event -> onResize(event)); metadataWindow.addWindowModeChangeListener(event -> onResize(event));
metadataWindow.getButtonsLayout().addComponent(discardButton, 1); ((HorizontalLayout)metadataWindow.getButtonsLayout()).addComponent(discardButton, 1);
setUpDetails(entity.getId(), metaData); setUpDetails(entity.getId(), metaData);
return metadataWindow; return metadataWindow;
} }
public E getSelectedEntity() { public E getSelectedEntity() {
return selectedEntity; return selectedEntity;
@@ -200,7 +203,7 @@ public abstract class AbstractMetadataPopupLayout<E extends NamedVersionedEntity
metadataFieldsLayout.setSpacing(true); metadataFieldsLayout.setSpacing(true);
metadataFieldsLayout.setExpandRatio(valueTextArea, 1F); metadataFieldsLayout.setExpandRatio(valueTextArea, 1F);
HorizontalLayout mainLayout = new HorizontalLayout(); mainLayout = new HorizontalLayout();
mainLayout.addComponent(tableLayout); mainLayout.addComponent(tableLayout);
mainLayout.addComponent(metadataFieldsLayout); mainLayout.addComponent(metadataFieldsLayout);
mainLayout.setExpandRatio(tableLayout, 0.5F); mainLayout.setExpandRatio(tableLayout, 0.5F);
@@ -545,4 +548,6 @@ public abstract class AbstractMetadataPopupLayout<E extends NamedVersionedEntity
discardButton.setEnabled(enable); discardButton.setEnabled(enable);
} }
} }

View File

@@ -10,162 +10,517 @@ package org.eclipse.hawkbit.ui.common;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.eclipse.hawkbit.ui.artifacts.smtable.SoftwareModuleAddUpdateWindow;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleBorderWithIcon; import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleBorderWithIcon;
import org.eclipse.hawkbit.ui.layouts.AbstractCreateUpdateTagLayout;
import org.eclipse.hawkbit.ui.management.targettable.TargetAddUpdateWindowLayout;
import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.vaadin.hene.flexibleoptiongroup.FlexibleOptionGroupItemComponent;
import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import com.vaadin.data.Container.ItemSetChangeEvent;
import com.vaadin.data.Container.ItemSetChangeListener;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener; import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.data.Validator;
import com.vaadin.data.validator.NullValidator;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.event.FieldEvents.TextChangeListener;
import com.vaadin.event.FieldEvents.TextChangeNotifier;
import com.vaadin.server.FontAwesome; import com.vaadin.server.FontAwesome;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.AbstractField;
import com.vaadin.ui.AbstractLayout;
import com.vaadin.ui.AbstractOrderedLayout; import com.vaadin.ui.AbstractOrderedLayout;
import com.vaadin.ui.Alignment; import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button; import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickListener; import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Component; import com.vaadin.ui.Component;
import com.vaadin.ui.Field;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Link; import com.vaadin.ui.Link;
import com.vaadin.ui.Table;
import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window; import com.vaadin.ui.Window;
import com.vaadin.ui.themes.ValoTheme;
/** /**
* *
* Superclass for pop-up-windows including a minimize and close icon in the * Table pop-up-windows including a minimize and close icon in the upper right
* upper right corner and a save and cancel button at the bottom. * corner and a save and cancel button at the bottom. Is not intended to reuse.
* *
*/ */
public class CommonDialogWindow extends Window { public class CommonDialogWindow extends Window implements Serializable {
private static final long serialVersionUID = -1321949234316858703L; private static final long serialVersionUID = 1L;
private final VerticalLayout mainLayout = new VerticalLayout(); private final VerticalLayout mainLayout = new VerticalLayout();
private final String caption; private final String caption;
private final Component content; private final Component content;
private final String helpLink; private final String helpLink;
private Button saveButton; private Button saveButton;
private Button cancelButton; private Button cancelButton;
private HorizontalLayout buttonsLayout; private HorizontalLayout buttonsLayout;
protected ValueChangeListener buttonEnableListener; protected ValueChangeListener buttonEnableListener;
private final ClickListener saveButtonClickListener; private final ClickListener saveButtonClickListener;
private final ClickListener cancelButtonClickListener; private final ClickListener cancelButtonClickListener;
/** private final ClickListener close = event -> close();
* Constructor.
*
* @param caption
* the caption
* @param content
* the content
* @param helpLink
* the helpLinks
* @param saveButtonClickListener
* the saveButtonClickListener
* @param cancelButtonClickListener
* the cancelButtonClickListener
*/
public CommonDialogWindow(final String caption, final Component content, final String helpLink,
final ClickListener saveButtonClickListener, final ClickListener cancelButtonClickListener) {
checkNotNull(saveButtonClickListener);
checkNotNull(cancelButtonClickListener);
this.caption = caption;
this.content = content;
this.helpLink = helpLink;
this.saveButtonClickListener = saveButtonClickListener;
this.cancelButtonClickListener = cancelButtonClickListener;
init(); private final transient Map<Component, Object> orginalValues;
}
private final void init() { private final List<AbstractField<?>> allComponents;
if (content instanceof AbstractOrderedLayout) { private final I18N i18n;
((AbstractOrderedLayout) content).setSpacing(true);
((AbstractOrderedLayout) content).setMargin(true);
}
if (null != content) { /**
mainLayout.addComponent(content); * Constructor.
mainLayout.setExpandRatio(content, 1.0F); *
} * @param caption
final HorizontalLayout buttonLayout = createActionButtonsLayout(); * the caption
mainLayout.addComponent(buttonLayout); * @param content
mainLayout.setComponentAlignment(buttonLayout, Alignment.TOP_CENTER); * the content
* @param helpLink
* the helpLinks
* @param saveButtonClickListener
* the saveButtonClickListener
* @param cancelButtonClickListener
* the cancelButtonClickListener
*/
public CommonDialogWindow(final String caption, final Component content, final String helpLink,
final ClickListener saveButtonClickListener, final ClickListener cancelButtonClickListener,
final AbstractLayout layout, final I18N i18n) {
checkNotNull(saveButtonClickListener);
this.caption = caption;
this.content = content;
this.helpLink = helpLink;
this.saveButtonClickListener = saveButtonClickListener;
this.cancelButtonClickListener = cancelButtonClickListener;
this.orginalValues = new HashMap<>();
this.allComponents = getAllComponents(layout);
this.i18n = i18n;
init();
}
setCaption(caption); @Override
setCaptionAsHtml(true); public void close() {
setContent(mainLayout); super.close();
setResizable(false); orginalValues.clear();
center(); removeListeners();
setModal(true); allComponents.clear();
addStyleName("fontsize"); this.saveButton.setEnabled(false);
} }
private HorizontalLayout createActionButtonsLayout() { private void removeListeners() {
for (final AbstractField<?> field : allComponents) {
removeTextListener(field);
removeValueChangeListener(field);
removeItemSetChangeistener(field);
}
}
buttonsLayout = new HorizontalLayout(); private void removeItemSetChangeistener(final AbstractField<?> field) {
buttonsLayout.setSizeUndefined(); if (!(field instanceof Table)) {
buttonsLayout.setSpacing(true); return;
createSaveButton(); }
for (final Object listener : field.getListeners(ItemSetChangeEvent.class)) {
if (listener instanceof ChangeListener) {
((Table) field).removeItemSetChangeListener((ChangeListener) listener);
}
}
}
createCancelButton(); private void removeTextListener(final AbstractField<?> field) {
buttonsLayout.addStyleName("actionButtonsMargin"); if (!(field instanceof TextChangeNotifier)) {
return;
}
for (final Object listener : field.getListeners(TextChangeEvent.class)) {
if (listener instanceof ChangeListener) {
((TextChangeNotifier) field).removeTextChangeListener((ChangeListener) listener);
}
}
}
addHelpLink(); private void removeValueChangeListener(final AbstractField<?> field) {
for (final Object listener : field.getListeners(ValueChangeEvent.class)) {
if (listener instanceof ChangeListener) {
field.removeValueChangeListener((ChangeListener) listener);
}
}
}
return buttonsLayout; private final void init() {
}
private void createCancelButton() { if (content instanceof AbstractOrderedLayout) {
cancelButton = SPUIComponentProvider.getButton(SPUIComponentIdProvider.CANCEL_BUTTON, "Cancel", "", "", true, ((AbstractOrderedLayout) content).setSpacing(true);
FontAwesome.TIMES, SPUIButtonStyleBorderWithIcon.class); ((AbstractOrderedLayout) content).setMargin(true);
cancelButton.setSizeUndefined(); }
cancelButton.addStyleName("default-color"); if (content instanceof GridLayout) {
cancelButton.addClickListener(cancelButtonClickListener); addStyleName("marginTop");
}
buttonsLayout.addComponent(cancelButton); if (null != content) {
buttonsLayout.setComponentAlignment(cancelButton, Alignment.MIDDLE_LEFT); mainLayout.addComponent(content);
buttonsLayout.setExpandRatio(cancelButton, 1.0F); mainLayout.setExpandRatio(content, 1.0F);
} }
private void createSaveButton() { createMandatoryLabel();
saveButton = SPUIComponentProvider.getButton(SPUIComponentIdProvider.SAVE_BUTTON, "Save", "", "", true,
FontAwesome.SAVE, SPUIButtonStyleBorderWithIcon.class);
saveButton.setSizeUndefined();
saveButton.addStyleName("default-color");
saveButton.addClickListener(saveButtonClickListener);
buttonsLayout.addComponent(saveButton);
buttonsLayout.setComponentAlignment(saveButton, Alignment.MIDDLE_RIGHT);
buttonsLayout.setExpandRatio(saveButton, 1.0F);
}
private void addHelpLink() { final HorizontalLayout buttonLayout = createActionButtonsLayout();
mainLayout.addComponent(buttonLayout);
mainLayout.setComponentAlignment(buttonLayout, Alignment.TOP_CENTER);
if (StringUtils.isEmpty(helpLink)) { setCaption(caption);
return; setCaptionAsHtml(true);
} setContent(mainLayout);
final Link helpLinkComponent = SPUIComponentProvider.getHelpLink(helpLink); setResizable(false);
buttonsLayout.addComponent(helpLinkComponent); center();
buttonsLayout.setComponentAlignment(helpLinkComponent, Alignment.MIDDLE_RIGHT); setModal(true);
} addStyleName("fontsize");
setOrginaleValues();
addListeners();
}
/**
* saves the original values in a Map so we can use them for detecting
* changes
*/
public final void setOrginaleValues() {
for (final AbstractField<?> field : allComponents) {
Object value = field.getValue();
if (field instanceof Table) {
value = Sets.newHashSet(((Table) field).getContainerDataSource().getItemIds());
}
orginalValues.put(field, value);
}
saveButton.setEnabled(isSaveButtonEnabledAfterValueChange(null, null));
}
protected void addListeners() {
addComponenetListeners();
addCloseListenerForSaveButton();
addCloseListenerForCancelButton();
}
public void setSaveButtonEnabled(final boolean enabled) { protected void addCloseListenerForSaveButton() {
saveButton.setEnabled(enabled); saveButton.addClickListener(close);
} }
protected void addCloseListenerForCancelButton() {
cancelButton.addClickListener(close);
}
protected void addComponenetListeners() {
for (final AbstractField<?> field : allComponents) {
if (field instanceof TextChangeNotifier) {
((TextChangeNotifier) field).addTextChangeListener(new ChangeListener(field));
}
if (field instanceof Table) {
((Table) field).addItemSetChangeListener(new ChangeListener(field));
} else {
field.addValueChangeListener(new ChangeListener(field));
}
}
}
private boolean isSaveButtonEnabledAfterValueChange(final Component currentChangedComponent,
final Object newValue) {
return isMandatoryFieldNotEmptyAndValid(currentChangedComponent, newValue)
&& isValuesChanged(currentChangedComponent, newValue);
}
private boolean isValuesChanged(final Component currentChangedComponent, final Object newValue) {
for (final AbstractField<?> field : allComponents) {
Object originalValue = orginalValues.get(field);
if (field instanceof CheckBox && originalValue == null) {
originalValue = Boolean.FALSE;
}
final Object currentValue = getCurrentVaue(currentChangedComponent, newValue, field);
if (!isValueEquals(field, originalValue, currentValue)) {
return true;
}
}
return false;
}
private boolean isValueEquals(final AbstractField<?> field, final Object orginalValue, final Object currentValue) {
if (Set.class.equals(field.getType())) {
return CollectionUtils.isEqualCollection(CollectionUtils.emptyIfNull((Collection<?>) orginalValue),
CollectionUtils.emptyIfNull((Collection<?>) currentValue));
}
if (String.class.equals(field.getType())) {
return Objects.equals(Strings.emptyToNull((String) orginalValue),
Strings.emptyToNull((String) currentValue));
}
return Objects.equals(orginalValue, currentValue);
}
private Object getCurrentVaue(final Component currentChangedComponent, final Object newValue,
final AbstractField<?> field) {
Object currentValue = field.getValue();
if (field instanceof Table) {
currentValue = ((Table) field).getContainerDataSource().getItemIds();
}
if (field.equals(currentChangedComponent)) {
currentValue = newValue;
}
return currentValue;
}
private boolean shouldMandatoryLabelShown() {
for (final AbstractField<?> field : allComponents) {
if (field.isRequired()) {
return true;
}
}
return false;
}
private boolean isMandatoryFieldNotEmptyAndValid(final Component currentChangedComponent, final Object newValue) {
boolean valid = true;
final List<AbstractField<?>> requiredComponents = allComponents.stream().filter(field -> field.isRequired())
.collect(Collectors.toList());
requiredComponents.addAll(allComponents.stream().filter(this::hasNullValidator).collect(Collectors.toList()));
for (final AbstractField field : requiredComponents) {
Object value = getCurrentVaue(currentChangedComponent, newValue, field);
if (String.class.equals(field.getType())) {
value = Strings.emptyToNull((String) value);
}
if (Set.class.equals(field.getType())) {
value = emptyToNull((Collection<?>) value);
}
if (value == null) {
return false;
}
// We need to loop through the entire loop for validity testing.
// Otherwise the UI will only mark the
// first field with errors and then stop. If there are several
// fields with errors, this is bad.
field.setValue(value);
if (!field.isValid()) {
valid = false;
}
}
return valid;
}
private static Object emptyToNull(final Collection<?> c) {
return (c == null || c.isEmpty()) ? null : c;
}
private boolean hasNullValidator(final Component component) {
if (component instanceof AbstractField<?>) {
final AbstractField<?> fieldComponent = (AbstractField<?>) component;
for (final Validator validator : fieldComponent.getValidators()) {
if (validator instanceof NullValidator) {
return true;
}
}
}
return false;
}
private List<AbstractField<?>> getAllComponents(final AbstractLayout abstractLayout) {
final List<AbstractField<?>> components = new ArrayList<>();
final Iterator<Component> iterate = abstractLayout.iterator();
while (iterate.hasNext()) {
final Component c = iterate.next();
if (c instanceof AbstractLayout) {
components.addAll(getAllComponents((AbstractLayout) c));
}
if (c instanceof AbstractField) {
components.add((AbstractField<?>) c);
}
if (c instanceof FlexibleOptionGroupItemComponent) {
components.add(((FlexibleOptionGroupItemComponent) c).getOwner());
}
}
return components;
}
private HorizontalLayout createActionButtonsLayout() {
buttonsLayout = new HorizontalLayout();
buttonsLayout.setSizeUndefined();
buttonsLayout.setSpacing(true);
createSaveButton();
createCancelButton();
buttonsLayout.addStyleName("actionButtonsMargin");
addHelpLink();
return buttonsLayout;
}
private void createMandatoryLabel() {
if (!shouldMandatoryLabelShown()) {
return;
}
final Label mandatoryLabel = new Label(i18n.get("label.mandatory.field"));
mandatoryLabel.addStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR + " " + ValoTheme.LABEL_TINY);
if (content instanceof TargetAddUpdateWindowLayout) {
((TargetAddUpdateWindowLayout) content).getFormLayout().addComponent(mandatoryLabel);
} else if (content instanceof SoftwareModuleAddUpdateWindow) {
((SoftwareModuleAddUpdateWindow) content).getFormLayout().addComponent(mandatoryLabel);
} else if (content instanceof AbstractCreateUpdateTagLayout) {
((AbstractCreateUpdateTagLayout) content).getMainLayout().addComponent(mandatoryLabel);
}
mainLayout.addComponent(mandatoryLabel);
}
private void createCancelButton() {
cancelButton = SPUIComponentProvider.getButton(SPUIComponentIdProvider.CANCEL_BUTTON, "Cancel", "", "", true,
FontAwesome.TIMES, SPUIButtonStyleBorderWithIcon.class);
cancelButton.setSizeUndefined();
cancelButton.addStyleName("default-color");
if (cancelButtonClickListener != null) {
cancelButton.addClickListener(cancelButtonClickListener);
}
buttonsLayout.addComponent(cancelButton);
buttonsLayout.setComponentAlignment(cancelButton, Alignment.MIDDLE_LEFT);
buttonsLayout.setExpandRatio(cancelButton, 1.0F);
}
private void createSaveButton() {
saveButton = SPUIComponentProvider.getButton(SPUIComponentIdProvider.SAVE_BUTTON, "Save", "", "", true,
FontAwesome.SAVE, SPUIButtonStyleBorderWithIcon.class);
saveButton.setSizeUndefined();
saveButton.addStyleName("default-color");
saveButton.addClickListener(saveButtonClickListener);
saveButton.setEnabled(false);
buttonsLayout.addComponent(saveButton);
buttonsLayout.setComponentAlignment(saveButton, Alignment.MIDDLE_RIGHT);
buttonsLayout.setExpandRatio(saveButton, 1.0F);
}
private void addHelpLink() {
if (StringUtils.isEmpty(helpLink)) {
return;
}
final Link helpLinkComponent = SPUIComponentProvider.getHelpLink(helpLink);
buttonsLayout.addComponent(helpLinkComponent);
buttonsLayout.setComponentAlignment(helpLinkComponent, Alignment.MIDDLE_RIGHT);
}
public AbstractComponent getButtonsLayout() {
return this.buttonsLayout;
}
private class ChangeListener implements ValueChangeListener, TextChangeListener, ItemSetChangeListener {
private final Field<?> field;
public ChangeListener(final Field<?> field) {
super();
this.field = field;
}
@Override
public void textChange(final TextChangeEvent event) {
saveButton.setEnabled(isSaveButtonEnabledAfterValueChange(field, event.getText()));
}
@Override
public void valueChange(final ValueChangeEvent event) {
saveButton.setEnabled(isSaveButtonEnabledAfterValueChange(field, field.getValue()));
}
@Override
public void containerItemSetChange(final ItemSetChangeEvent event) {
if (!(field instanceof Table)) {
return;
}
final Table table = (Table) field;
saveButton.setEnabled(
isSaveButtonEnabledAfterValueChange(table, table.getContainerDataSource().getItemIds()));
}
}
/**
* Adds the component manually to the allComponents-List and adds a
* ValueChangeListener to it. Necessary in Update Distribution Type as the
* CheckBox concerned is an ItemProperty...
*
* @param component
* AbstractField
*/
public void updateAllComponents(final AbstractField component) {
allComponents.add(component);
component.addValueChangeListener(new ChangeListener(component));
}
public VerticalLayout getMainLayout() {
return mainLayout;
}
public void setSaveButtonEnabled(final boolean enabled) {
saveButton.setEnabled(enabled);
}
public void setCancelButtonEnabled(final boolean enabled) {
cancelButton.setEnabled(enabled);
}
public HorizontalLayout getButtonsLayout() {
return buttonsLayout;
}
public VerticalLayout getMainLayout() {
return mainLayout;
}
} }

View File

@@ -0,0 +1,26 @@
package org.eclipse.hawkbit.ui.common;
import org.eclipse.hawkbit.ui.utils.I18N;
import com.vaadin.event.FieldEvents.BlurListener;
import com.vaadin.ui.AbstractLayout;
import com.vaadin.ui.Component;
import com.vaadin.ui.Button.ClickListener;
public class CustomCommonDialogWindow extends CommonDialogWindow {
private static final long serialVersionUID = -4453608850403359992L;
public CustomCommonDialogWindow(final String caption, final Component content, final String helpLink,
final ClickListener saveButtonClickListener, final ClickListener cancelButtonClickListener,
final AbstractLayout layout, final I18N i18n) {
super(caption, content, helpLink, saveButtonClickListener, cancelButtonClickListener, layout, i18n);
}
@Override
protected void addListeners() {
addComponenetListeners();
addCloseListenerForCancelButton();
}
}

View File

@@ -89,13 +89,15 @@ public class DistributionSetMetadatadetailslayout extends Table{
*/ */
public void populateDSMetadata(final DistributionSet distributionSet) { public void populateDSMetadata(final DistributionSet distributionSet) {
removeAllItems(); removeAllItems();
if (null != distributionSet) { if (null == distributionSet) {
selectedDistSetId = distributionSet.getId(); return;
final List<DistributionSetMetadata> dsMetadataList = distributionSet.getMetadata(); }
if (null != dsMetadataList && !dsMetadataList.isEmpty()) { selectedDistSetId = distributionSet.getId();
dsMetadataList.forEach(dsMetadata -> setDSMetadataProperties(dsMetadata)); final List<DistributionSetMetadata> dsMetadataList = distributionSet.getMetadata();
} if (null != dsMetadataList && !dsMetadataList.isEmpty()) {
} dsMetadataList.forEach(dsMetadata -> setDSMetadataProperties(dsMetadata));
}
} }
/** /**

View File

@@ -41,129 +41,130 @@ import com.vaadin.ui.themes.ValoTheme;
@ViewScope @ViewScope
public class SoftwareModuleMetadatadetailslayout extends Table { 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 SoftwareManagement softwareManagement; private SoftwareManagement softwareManagement;
private SwMetadataPopupLayout swMetadataPopupLayout; private SwMetadataPopupLayout swMetadataPopupLayout;
private I18N i18n; private I18N i18n;
private Long selectedSWModuleId; private Long selectedSWModuleId;
private transient EntityFactory entityFactory; private transient EntityFactory entityFactory;
public void init(final I18N i18n, final SpPermissionChecker permissionChecker, public void init(final I18N i18n, final SpPermissionChecker permissionChecker,
final SoftwareManagement softwareManagement, final SwMetadataPopupLayout swMetadataPopupLayout, final SoftwareManagement softwareManagement, final SwMetadataPopupLayout swMetadataPopupLayout,
final EntityFactory entityFactory) { final EntityFactory entityFactory) {
this.i18n = i18n; this.i18n = i18n;
this.permissionChecker = permissionChecker; this.permissionChecker = permissionChecker;
this.softwareManagement = softwareManagement; this.softwareManagement = softwareManagement;
this.swMetadataPopupLayout = swMetadataPopupLayout; this.swMetadataPopupLayout = swMetadataPopupLayout;
this.entityFactory = entityFactory; this.entityFactory = entityFactory;
createSWMMetadataTable(); createSWMMetadataTable();
addCustomGeneratedColumns(); addCustomGeneratedColumns();
} }
/** /**
* Populate software module metadata table. * Populate software module metadata table.
* *
* @param swModule * @param swModule
*/ */
public void populateSMMetadata(final SoftwareModule swModule) { public void populateSMMetadata(final SoftwareModule swModule) {
removeAllItems(); removeAllItems();
if (null != swModule) { if (null == swModule) {
selectedSWModuleId = swModule.getId(); return;
final List<SoftwareModuleMetadata> swMetadataList = swModule.getMetadata(); }
if (null != swMetadataList && !swMetadataList.isEmpty()) { selectedSWModuleId = swModule.getId();
swMetadataList.forEach(swMetadata -> setSWMetadataProperties(swMetadata)); final List<SoftwareModuleMetadata> swMetadataList = swModule.getMetadata();
} if (null != swMetadataList && !swMetadataList.isEmpty()) {
} swMetadataList.forEach(swMetadata -> setSWMetadataProperties(swMetadata));
} }
}
/** /**
* Create metadata. * Create metadata.
* *
* @param metadataKeyName * @param metadataKeyName
*/ */
public void createMetadata(final String metadataKeyName) { public void createMetadata(final String metadataKeyName) {
final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource(); final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource();
final Item item = metadataContainer.addItem(metadataKeyName); final Item item = metadataContainer.addItem(metadataKeyName);
item.getItemProperty(METADATA_KEY).setValue(metadataKeyName); item.getItemProperty(METADATA_KEY).setValue(metadataKeyName);
} }
/** /**
* Delete metadata. * Delete metadata.
* *
* @param metadataKeyName * @param metadataKeyName
*/ */
public void deleteMetadata(final String metadataKeyName) { public void deleteMetadata(final String metadataKeyName) {
final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource(); final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource();
metadataContainer.removeItem(metadataKeyName); metadataContainer.removeItem(metadataKeyName);
} }
private void createSWMMetadataTable() { private void createSWMMetadataTable() {
addStyleName(ValoTheme.TABLE_NO_HORIZONTAL_LINES); addStyleName(ValoTheme.TABLE_NO_HORIZONTAL_LINES);
addStyleName(ValoTheme.TABLE_NO_STRIPES); addStyleName(ValoTheme.TABLE_NO_STRIPES);
addStyleName(SPUIStyleDefinitions.SW_MODULE_TABLE); addStyleName(SPUIStyleDefinitions.SW_MODULE_TABLE);
setSelectable(false); setSelectable(false);
setImmediate(true); setImmediate(true);
setContainerDataSource(getSwModuleMetadataContainer()); setContainerDataSource(getSwModuleMetadataContainer());
setColumnHeaderMode(ColumnHeaderMode.EXPLICIT); setColumnHeaderMode(ColumnHeaderMode.EXPLICIT);
addSMMetadataTableHeader(); addSMMetadataTableHeader();
setSizeFull(); setSizeFull();
//same as height of other tabs in details tabsheet //same as height of other tabs in details tabsheet
setHeight(116,Unit.PIXELS); setHeight(116,Unit.PIXELS);
} }
private IndexedContainer getSwModuleMetadataContainer() { private IndexedContainer getSwModuleMetadataContainer() {
final IndexedContainer container = new IndexedContainer(); final IndexedContainer container = new IndexedContainer();
container.addContainerProperty(METADATA_KEY, String.class, ""); container.addContainerProperty(METADATA_KEY, String.class, "");
setColumnAlignment(METADATA_KEY, Align.LEFT); setColumnAlignment(METADATA_KEY, Align.LEFT);
return container; return container;
} }
private void addSMMetadataTableHeader() { private void addSMMetadataTableHeader() {
setColumnHeader(METADATA_KEY, i18n.get("header.key")); setColumnHeader(METADATA_KEY, i18n.get("header.key"));
} }
private void setSWMetadataProperties(final SoftwareModuleMetadata swMetadata) { private void setSWMetadataProperties(final SoftwareModuleMetadata swMetadata) {
final Item item = getContainerDataSource().addItem(swMetadata.getKey()); final Item item = getContainerDataSource().addItem(swMetadata.getKey());
item.getItemProperty(METADATA_KEY).setValue(swMetadata.getKey()); item.getItemProperty(METADATA_KEY).setValue(swMetadata.getKey());
} }
private void addCustomGeneratedColumns() { private void addCustomGeneratedColumns() {
addGeneratedColumn(METADATA_KEY, (source, itemId, columnId) -> customMetadataDetailButton((String) itemId)); addGeneratedColumn(METADATA_KEY, (source, itemId, columnId) -> customMetadataDetailButton((String) itemId));
} }
private Button customMetadataDetailButton(final String metadataKey) { private Button customMetadataDetailButton(final String metadataKey) {
final Button viewLink = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey, "View" final Button viewLink = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey, "View"
+ metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class); + metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class);
viewLink.setData(metadataKey); viewLink.setData(metadataKey);
if (permissionChecker.hasUpdateDistributionPermission()) { if (permissionChecker.hasUpdateDistributionPermission()) {
viewLink.addStyleName(ValoTheme.BUTTON_TINY + " " + ValoTheme.BUTTON_LINK + " " + "on-focus-no-border link" viewLink.addStyleName(ValoTheme.BUTTON_TINY + " " + ValoTheme.BUTTON_LINK + " " + "on-focus-no-border link"
+ " " + "text-style"); + " " + "text-style");
viewLink.addClickListener(event -> showMetadataDetails(selectedSWModuleId, metadataKey)); viewLink.addClickListener(event -> showMetadataDetails(selectedSWModuleId, metadataKey));
} }
return viewLink; return viewLink;
} }
private static String getDetailLinkId(final String name) { private static String getDetailLinkId(final String name) {
return new StringBuilder(SPUIComponentIdProvider.SW_METADATA_DETAIL_LINK).append('.').append(name).toString(); return new StringBuilder(SPUIComponentIdProvider.SW_METADATA_DETAIL_LINK).append('.').append(name).toString();
} }
private void showMetadataDetails(final Long selectedSWModuleId, final String metadataKey) { private void showMetadataDetails(final Long selectedSWModuleId, final String metadataKey) {
SoftwareModule swmodule = softwareManagement.findSoftwareModuleById(selectedSWModuleId); SoftwareModule swmodule = softwareManagement.findSoftwareModuleById(selectedSWModuleId);
/* display the window */ /* display the window */
UI.getCurrent().addWindow( UI.getCurrent().addWindow(
swMetadataPopupLayout.getWindow(swmodule, swMetadataPopupLayout.getWindow(swmodule,
entityFactory.generateSoftwareModuleMetadata(swmodule, metadataKey, ""))); entityFactory.generateSoftwareModuleMetadata(swmodule, metadataKey, "")));
} }
} }

View File

@@ -22,7 +22,8 @@ import com.vaadin.ui.Button.ClickEvent;
*/ */
public abstract class AbstractFilterMultiButtonClick extends AbstractFilterButtonClickBehaviour { public abstract class AbstractFilterMultiButtonClick extends AbstractFilterButtonClickBehaviour {
protected final Set<Button> alreadyClickedButtons = new HashSet<>(); private static final long serialVersionUID = 1L;
protected final transient Set<Button> alreadyClickedButtons = new HashSet<>();
/* /*
* (non-Javadoc) * (non-Javadoc)

View File

@@ -95,9 +95,6 @@ public abstract class AbstractTable<E extends NamedEntity, I> extends Table {
if (values == null) { if (values == null) {
values = Collections.emptySet(); values = Collections.emptySet();
} }
if (values.contains(null)) {
LOG.warn("Null values in table content. How could this happen?");
}
return values; return values;
} }

View File

@@ -43,10 +43,6 @@ import com.vaadin.ui.themes.ValoTheme;
/** /**
* Abstract class for target/ds tag token layout. * Abstract class for target/ds tag token layout.
*
*
*
*
*/ */
public abstract class AbstractTagToken<T extends BaseEntity> implements Serializable { public abstract class AbstractTagToken<T extends BaseEntity> implements Serializable {
@@ -58,9 +54,9 @@ public abstract class AbstractTagToken<T extends BaseEntity> implements Serializ
protected IndexedContainer container; protected IndexedContainer container;
protected final Map<Long, TagData> tagDetails = new HashMap<>(); protected final transient Map<Long, TagData> tagDetails = new HashMap<>();
protected final Map<Long, TagData> tokensAdded = new HashMap<>(); protected final transient Map<Long, TagData> tokensAdded = new HashMap<>();
protected CssLayout tokenLayout = new CssLayout(); protected CssLayout tokenLayout = new CssLayout();

View File

@@ -14,7 +14,6 @@ import java.util.Map;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.eclipse.hawkbit.repository.model.BaseEntity; import org.eclipse.hawkbit.repository.model.BaseEntity;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter; import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonDecorator; import org.eclipse.hawkbit.ui.decorators.SPUIButtonDecorator;
import org.eclipse.hawkbit.ui.decorators.SPUIComboBoxDecorator; import org.eclipse.hawkbit.ui.decorators.SPUIComboBoxDecorator;
@@ -33,10 +32,8 @@ import com.vaadin.server.FontAwesome;
import com.vaadin.server.Resource; import com.vaadin.server.Resource;
import com.vaadin.shared.ui.label.ContentMode; import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Button; import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.CheckBox; import com.vaadin.ui.CheckBox;
import com.vaadin.ui.ComboBox; import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label; import com.vaadin.ui.Label;
import com.vaadin.ui.Link; import com.vaadin.ui.Link;
@@ -140,24 +137,6 @@ public final class SPUIComponentProvider {
return SPUILabelDecorator.getDeocratedLabel(name, 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 CommonDialogWindow getWindow(final String caption, final String id, final String type,
final Component content, final ClickListener saveButtonClickListener,
final ClickListener cancelButtonClickListener, final String helpLink) {
return SPUIWindowDecorator.getDeocratedWindow(caption, id, type, content, saveButtonClickListener,
cancelButtonClickListener, helpLink);
}
/** /**
* Get window component. * Get window component.
* *
@@ -204,6 +183,8 @@ public final class SPUIComponentProvider {
/** /**
* Get Label UI component. * * Get Label UI component. *
* *
* @param caption
* set the caption of the textArea
* @param style * @param style
* set style * set style
* @param styleName * @param styleName

View File

@@ -9,9 +9,12 @@
package org.eclipse.hawkbit.ui.decorators; package org.eclipse.hawkbit.ui.decorators;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow; 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.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import com.vaadin.ui.AbstractLayout;
import com.vaadin.ui.Button.ClickListener; import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Component; import com.vaadin.ui.Component;
import com.vaadin.ui.Window; import com.vaadin.ui.Window;
@@ -42,26 +45,35 @@ public final class SPUIWindowDecorator {
* window type * window type
* @return Window * @return Window
*/ */
public static CommonDialogWindow getDeocratedWindow(final String caption, final String id, final String type, public static CommonDialogWindow getWindow(final String caption, final String id, final String type,
final Component content, final ClickListener saveButtonClickListener, final Component content, final ClickListener saveButtonClickListener,
final ClickListener cancelButtonClickListener, final String helpLink) { 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);
final CommonDialogWindow window = new CommonDialogWindow(caption, content, helpLink, saveButtonClickListener, } else if (SPUIDefinitions.CREATE_UPDATE_WINDOW.equals(type)) {
cancelButtonClickListener); window.setDraggable(true);
if (null != id) { window.setClosable(true);
window.setId(id); }
} }
if (SPUIDefinitions.CONFIRMATION_WINDOW.equals(type)) { return window;
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. * Decorates window based on type.

View File

@@ -9,6 +9,7 @@
package org.eclipse.hawkbit.ui.distributions.disttype; package org.eclipse.hawkbit.ui.distributions.disttype;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
@@ -16,7 +17,6 @@ import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareManagement; import org.eclipse.hawkbit.repository.SoftwareManagement;
import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerConstants;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper; import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
import org.eclipse.hawkbit.ui.common.DistributionSetTypeBeanQuery; import org.eclipse.hawkbit.ui.common.DistributionSetTypeBeanQuery;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
@@ -49,8 +49,6 @@ import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Table; import com.vaadin.ui.Table;
import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.components.colorpicker.ColorChangeListener;
import com.vaadin.ui.components.colorpicker.ColorSelector;
import com.vaadin.ui.themes.ValoTheme; import com.vaadin.ui.themes.ValoTheme;
/** /**
@@ -58,8 +56,7 @@ import com.vaadin.ui.themes.ValoTheme;
*/ */
@SpringComponent @SpringComponent
@ViewScope @ViewScope
public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout {
implements ColorChangeListener, ColorSelector {
private static final long serialVersionUID = -5169398523815877767L; private static final long serialVersionUID = -5169398523815877767L;
private static final Logger LOG = LoggerFactory.getLogger(CreateUpdateDistSetTypeLayout.class); private static final Logger LOG = LoggerFactory.getLogger(CreateUpdateDistSetTypeLayout.class);
@@ -82,8 +79,12 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
private Table sourceTable; private Table sourceTable;
private Table selectedTable; private Table selectedTable;
private IndexedContainer selectedTablecontainer; private IndexedContainer selectedTableContainer;
private IndexedContainer sourceTablecontainer; private IndexedContainer sourceTableContainer;
private IndexedContainer originalSelectedTableContainer;
private Map<CheckBox, Boolean> mandatoryCheckboxMap;
@Override @Override
protected void createRequiredComponents() { protected void createRequiredComponents() {
@@ -103,7 +104,6 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
tagDesc = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "", tagDesc = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "",
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.DIST_SET_TYPE_DESC, false, "", ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.DIST_SET_TYPE_DESC, false, "",
i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH); i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
tagDesc.setId(SPUIDefinitions.NEW_DISTRIBUTION_TYPE_DESC); tagDesc.setId(SPUIDefinitions.NEW_DISTRIBUTION_TYPE_DESC);
tagDesc.setImmediate(true); tagDesc.setImmediate(true);
tagDesc.setNullRepresentation(""); tagDesc.setNullRepresentation("");
@@ -159,9 +159,6 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
return twinColumnLayout; return twinColumnLayout;
} }
/**
*
*/
private void buildSelectedTable() { private void buildSelectedTable() {
selectedTable = new Table(); selectedTable = new Table();
@@ -176,13 +173,14 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
selectedTable.addStyleName("dist_type_twin-table"); selectedTable.addStyleName("dist_type_twin-table");
selectedTable.setSizeFull(); selectedTable.setSizeFull();
createSelectedTableContainer(); createSelectedTableContainer();
selectedTable.setContainerDataSource(selectedTablecontainer); selectedTable.setContainerDataSource(selectedTableContainer);
addTooltTipToSelectedTable(); addTooltTipToSelectedTable();
selectedTable.setImmediate(true); selectedTable.setImmediate(true);
selectedTable.setVisibleColumns(DIST_TYPE_NAME, DIST_TYPE_MANDATORY); selectedTable.setVisibleColumns(DIST_TYPE_NAME, DIST_TYPE_MANDATORY);
selectedTable.setColumnHeaders(i18n.get("header.dist.twintable.selected"), STAR); selectedTable.setColumnHeaders(i18n.get("header.dist.twintable.selected"), STAR);
selectedTable.setColumnExpandRatio(DIST_TYPE_NAME, 0.75f); selectedTable.setColumnExpandRatio(DIST_TYPE_NAME, 0.75F);
selectedTable.setColumnExpandRatio(DIST_TYPE_MANDATORY, 0.25f); selectedTable.setColumnExpandRatio(DIST_TYPE_MANDATORY, 0.25F);
selectedTable.setRequired(true);
} }
private void addTooltTipToSelectedTable() { private void addTooltTipToSelectedTable() {
@@ -218,14 +216,13 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
sourceTable.addStyleName(ValoTheme.TABLE_NO_VERTICAL_LINES); sourceTable.addStyleName(ValoTheme.TABLE_NO_VERTICAL_LINES);
sourceTable.addStyleName(ValoTheme.TABLE_SMALL); sourceTable.addStyleName(ValoTheme.TABLE_SMALL);
sourceTable.setImmediate(true); sourceTable.setImmediate(true);
// sourceTable
sourceTable.setSizeFull(); sourceTable.setSizeFull();
sourceTable.addStyleName("dist_type_twin-table"); sourceTable.addStyleName("dist_type_twin-table");
sourceTable.setSortEnabled(false); sourceTable.setSortEnabled(false);
sourceTablecontainer = new IndexedContainer(); sourceTableContainer = new IndexedContainer();
sourceTablecontainer.addContainerProperty(DIST_TYPE_NAME, String.class, ""); sourceTableContainer.addContainerProperty(DIST_TYPE_NAME, String.class, "");
sourceTablecontainer.addContainerProperty(DIST_TYPE_DESCRIPTION, String.class, ""); sourceTableContainer.addContainerProperty(DIST_TYPE_DESCRIPTION, String.class, "");
sourceTable.setContainerDataSource(sourceTablecontainer); sourceTable.setContainerDataSource(sourceTableContainer);
sourceTable.setVisibleColumns(new Object[] { DIST_TYPE_NAME }); sourceTable.setVisibleColumns(new Object[] { DIST_TYPE_NAME });
sourceTable.setColumnHeaders(i18n.get("header.dist.twintable.available")); sourceTable.setColumnHeaders(i18n.get("header.dist.twintable.available"));
@@ -237,20 +234,29 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
private void createSelectedTableContainer() { private void createSelectedTableContainer() {
selectedTablecontainer = new IndexedContainer(); selectedTableContainer = new IndexedContainer();
selectedTablecontainer.addContainerProperty(DIST_TYPE_NAME, String.class, ""); selectedTableContainer.addContainerProperty(DIST_TYPE_NAME, String.class, "");
selectedTablecontainer.addContainerProperty(DIST_TYPE_DESCRIPTION, String.class, ""); selectedTableContainer.addContainerProperty(DIST_TYPE_DESCRIPTION, String.class, "");
selectedTablecontainer.addContainerProperty(DIST_TYPE_MANDATORY, CheckBox.class, null); selectedTableContainer.addContainerProperty(DIST_TYPE_MANDATORY, CheckBox.class, null);
}
private void createOriginalSelectedTableContainer() {
originalSelectedTableContainer = new IndexedContainer();
originalSelectedTableContainer.addContainerProperty(DIST_TYPE_NAME, String.class, "");
originalSelectedTableContainer.addContainerProperty(DIST_TYPE_DESCRIPTION, String.class, "");
originalSelectedTableContainer.addContainerProperty(DIST_TYPE_MANDATORY, CheckBox.class, null);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void addSMType() { private void addSMType() {
final Set<Long> selectedIds = (Set<Long>) sourceTable.getValue(); final Set<Long> selectedIds = (Set<Long>) sourceTable.getValue();
if (null != selectedIds && !selectedIds.isEmpty()) { if (selectedIds == null) {
for (final Long id : selectedIds) { return;
addTargetTableData(id); }
} for (final Long id : selectedIds) {
addTargetTableData(id);
} }
} }
@@ -258,23 +264,24 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Set<Long> selectedIds = (Set<Long>) selectedTable.getValue(); final Set<Long> selectedIds = (Set<Long>) selectedTable.getValue();
if (null != selectedIds && !selectedIds.isEmpty()) { if (selectedIds == null) {
for (final Long id : selectedIds) { return;
addSourceTableData(id); }
selectedTable.removeItem(id); for (final Long id : selectedIds) {
} addSourceTableData(id);
selectedTable.removeItem(id);
} }
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void getSourceTableData() { private void getSourceTableData() {
sourceTablecontainer.removeAllItems(); sourceTableContainer.removeAllItems();
final Iterable<SoftwareModuleType> moduleTypeBeans = softwareManagement final Iterable<SoftwareModuleType> moduleTypeBeans = softwareManagement
.findSoftwareModuleTypesAll(new PageRequest(0, 1_000)); .findSoftwareModuleTypesAll(new PageRequest(0, 1_000));
Item saveTblitem; Item saveTblitem;
for (final SoftwareModuleType swTypeTag : moduleTypeBeans) { for (final SoftwareModuleType swTypeTag : moduleTypeBeans) {
saveTblitem = sourceTablecontainer.addItem(swTypeTag.getId()); saveTblitem = sourceTableContainer.addItem(swTypeTag.getId());
saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(swTypeTag.getName()); saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(swTypeTag.getName());
saveTblitem.getItemProperty(DIST_TYPE_DESCRIPTION).setValue(swTypeTag.getDescription()); saveTblitem.getItemProperty(DIST_TYPE_DESCRIPTION).setValue(swTypeTag.getDescription());
} }
@@ -307,11 +314,13 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
private void getSelectedTableItemData(final Long id) { private void getSelectedTableItemData(final Long id) {
Item saveTblitem; Item saveTblitem;
if (null != selectedTablecontainer) { if (selectedTableContainer != null) {
saveTblitem = selectedTablecontainer.addItem(id); saveTblitem = selectedTableContainer.addItem(id);
saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue( saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(
sourceTable.getContainerDataSource().getItem(id).getItemProperty(DIST_TYPE_NAME).getValue()); sourceTable.getContainerDataSource().getItem(id).getItemProperty(DIST_TYPE_NAME).getValue());
saveTblitem.getItemProperty(DIST_TYPE_MANDATORY).setValue(new CheckBox()); final CheckBox mandatoryCheckBox = new CheckBox();
window.updateAllComponents(mandatoryCheckBox);
saveTblitem.getItemProperty(DIST_TYPE_MANDATORY).setValue(mandatoryCheckBox);
saveTblitem.getItemProperty(DIST_TYPE_DESCRIPTION).setValue( saveTblitem.getItemProperty(DIST_TYPE_DESCRIPTION).setValue(
sourceTable.getContainerDataSource().getItem(id).getItemProperty(DIST_TYPE_DESCRIPTION).getValue()); sourceTable.getContainerDataSource().getItem(id).getItemProperty(DIST_TYPE_DESCRIPTION).getValue());
} }
@@ -320,10 +329,9 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void addSourceTableData(final Long selectedId) { private void addSourceTableData(final Long selectedId) {
if (null != sourceTablecontainer) { if (sourceTableContainer != null) {
Item saveTblitem; Item saveTblitem;
saveTblitem = sourceTablecontainer.addItem(selectedId); saveTblitem = sourceTableContainer.addItem(selectedId);
selectedTable.getContainerDataSource().getItem(selectedId).getItemProperty(DIST_TYPE_NAME);
saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(selectedTable.getContainerDataSource() saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(selectedTable.getContainerDataSource()
.getItem(selectedId).getItemProperty(DIST_TYPE_NAME).getValue()); .getItem(selectedId).getItemProperty(DIST_TYPE_NAME).getValue());
saveTblitem.getItemProperty(DIST_TYPE_DESCRIPTION).setValue(selectedTable.getContainerDataSource() saveTblitem.getItemProperty(DIST_TYPE_DESCRIPTION).setValue(selectedTable.getContainerDataSource()
@@ -353,20 +361,14 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
final SoftwareModuleType swModuleType = softwareManagement.findSoftwareModuleTypeByName(distTypeName); final SoftwareModuleType swModuleType = softwareManagement.findSoftwareModuleTypeByName(distTypeName);
checkMandatoryAndAddMandatoryModuleType(newDistType, isMandatory, swModuleType); checkMandatoryAndAddMandatoryModuleType(newDistType, isMandatory, swModuleType);
} }
if (null != typeDescValue) { newDistType.setDescription(typeDescValue);
newDistType.setDescription(typeDescValue);
}
newDistType.setColour(colorPicked); newDistType.setColour(colorPicked);
newDistType = distributionSetManagement.createDistributionSetType(newDistType); newDistType = distributionSetManagement.createDistributionSetType(newDistType);
uiNotification.displaySuccess(i18n.get("message.save.success", new Object[] { newDistType.getName() })); uiNotification.displaySuccess(i18n.get("message.save.success", new Object[] { newDistType.getName() }));
closeWindow();
eventBus.publish(this, eventBus.publish(this,
new DistributionSetTypeEvent(DistributionSetTypeEnum.ADD_DIST_SET_TYPE, newDistType)); new DistributionSetTypeEvent(DistributionSetTypeEnum.ADD_DIST_SET_TYPE, newDistType));
} else { } else {
uiNotification.displayValidationError(i18n.get("message.error.missing.typenameorkey")); uiNotification.displayValidationError(i18n.get("message.error.missing.typenameorkey"));
} }
} }
@@ -386,7 +388,7 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
if (null != typeNameValue) { if (null != typeNameValue) {
updateDistSetType.setName(typeNameValue); updateDistSetType.setName(typeNameValue);
updateDistSetType.setKey(typeKeyValue); updateDistSetType.setKey(typeKeyValue);
updateDistSetType.setDescription(null != typeDescValue ? typeDescValue : null); updateDistSetType.setDescription(typeDescValue);
if (distributionSetManagement.countDistributionSetsByType(existingType) <= 0 && null != itemIds if (distributionSetManagement.countDistributionSetsByType(existingType) <= 0 && null != itemIds
&& !itemIds.isEmpty()) { && !itemIds.isEmpty()) {
@@ -404,21 +406,17 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
distributionSetManagement.updateDistributionSetType(updateDistSetType); distributionSetManagement.updateDistributionSetType(updateDistSetType);
uiNotification uiNotification
.displaySuccess(i18n.get("message.update.success", new Object[] { updateDistSetType.getName() })); .displaySuccess(i18n.get("message.update.success", new Object[] { updateDistSetType.getName() }));
closeWindow();
eventBus.publish(this, eventBus.publish(this,
new DistributionSetTypeEvent(DistributionSetTypeEnum.UPDATE_DIST_SET_TYPE, updateDistSetType)); new DistributionSetTypeEvent(DistributionSetTypeEnum.UPDATE_DIST_SET_TYPE, updateDistSetType));
} else { } else {
uiNotification.displayValidationError(i18n.get("message.tag.update.mandatory")); uiNotification.displayValidationError(i18n.get("message.tag.update.mandatory"));
} }
} }
private void checkMandatoryAndAddMandatoryModuleType(final DistributionSetType updateDistSetType, private void checkMandatoryAndAddMandatoryModuleType(final DistributionSetType updateDistSetType,
final Boolean isMandatory, final SoftwareModuleType swModuleType) { final Boolean isMandatory, final SoftwareModuleType swModuleType) {
if (isMandatory) { if (isMandatory) {
updateDistSetType.addMandatoryModuleType(swModuleType); updateDistSetType.addMandatoryModuleType(swModuleType);
} else { } else {
updateDistSetType.addOptionalModuleType(swModuleType); updateDistSetType.addOptionalModuleType(swModuleType);
} }
@@ -440,32 +438,6 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
return distSetType; return distSetType;
} }
/*
* (non-Javadoc)
*
* @see com.vaadin.ui.components.colorpicker.HasColorChangeListener#
* addColorChangeListener(com.vaadin
* .ui.components.colorpicker.ColorChangeListener)
*/
@Override
public void addColorChangeListener(final ColorChangeListener listener) {
LOG.info("in side addColorChangeListener() ");
}
/*
* (non-Javadoc)
*
* @see com.vaadin.ui.components.colorpicker.HasColorChangeListener#
* removeColorChangeListener(com.
* vaadin.ui.components.colorpicker.ColorChangeListener)
*/
@Override
public void removeColorChangeListener(final ColorChangeListener listener) {
LOG.info("in side removeColorChangeListener() ");
}
/** /**
* reset the components. * reset the components.
*/ */
@@ -484,9 +456,9 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
* ValueChangeEvent * ValueChangeEvent
*/ */
@Override @Override
protected void createOptionValueChanged(final ValueChangeEvent event) { protected void optionValueChanged(final ValueChangeEvent event) {
super.createOptionValueChanged(event); super.optionValueChanged(event);
if (updateTypeStr.equals(event.getProperty().getValue())) { if (updateTypeStr.equals(event.getProperty().getValue())) {
selectedTable.getContainerDataSource().removeAllItems(); selectedTable.getContainerDataSource().removeAllItems();
@@ -552,18 +524,17 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
if (null != selectedTypeTag) { if (null != selectedTypeTag) {
tagDesc.setValue(selectedTypeTag.getDescription()); tagDesc.setValue(selectedTypeTag.getDescription());
typeKey.setValue(selectedTypeTag.getKey()); typeKey.setValue(selectedTypeTag.getKey());
if (distributionSetManagement.countDistributionSetsByType(selectedTypeTag) <= 0) { if (distributionSetManagement.countDistributionSetsByType(selectedTypeTag) <= 0) {
distTypeSelectLayout.setEnabled(true); distTypeSelectLayout.setEnabled(true);
selectedTable.setEnabled(true); selectedTable.setEnabled(true);
window.setSaveButtonEnabled(true);
} else { } else {
uiNotification.displayValidationError( uiNotification.displayValidationError(
selectedTypeTag.getName() + " " + i18n.get("message.error.dist.set.type.update")); selectedTypeTag.getName() + " " + i18n.get("message.error.dist.set.type.update"));
distTypeSelectLayout.setEnabled(false); distTypeSelectLayout.setEnabled(false);
selectedTable.setEnabled(false); selectedTable.setEnabled(false);
window.setSaveButtonEnabled(false);
} }
createOriginalSelectedTableContainer();
for (final SoftwareModuleType swModuleType : selectedTypeTag.getOptionalModuleTypes()) { for (final SoftwareModuleType swModuleType : selectedTypeTag.getOptionalModuleTypes()) {
addTargetTableforUpdate(swModuleType, false); addTargetTableforUpdate(swModuleType, false);
} }
@@ -583,65 +554,41 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void addTargetTableforUpdate(final SoftwareModuleType swModuleType, final boolean mandatory) { private void addTargetTableforUpdate(final SoftwareModuleType swModuleType, final boolean mandatory) {
Item saveTblitem; if (selectedTableContainer == null) {
if (null != selectedTablecontainer) { return;
saveTblitem = selectedTablecontainer.addItem(swModuleType.getId());
sourceTable.removeItem(swModuleType.getId());
saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(swModuleType.getName());
saveTblitem.getItemProperty(DIST_TYPE_MANDATORY).setValue(new CheckBox("", mandatory));
} }
final Item saveTblitem = selectedTableContainer.addItem(swModuleType.getId());
sourceTable.removeItem(swModuleType.getId());
saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(swModuleType.getName());
final CheckBox mandatoryCheckbox = new CheckBox("", mandatory);
mandatoryCheckbox.setId(swModuleType.getName());
saveTblitem.getItemProperty(DIST_TYPE_MANDATORY).setValue(mandatoryCheckbox);
final Item originalItem = originalSelectedTableContainer.addItem(swModuleType.getId());
originalItem.getItemProperty(DIST_TYPE_NAME).setValue(swModuleType.getName());
originalItem.getItemProperty(DIST_TYPE_MANDATORY).setValue(mandatoryCheckbox);
window.updateAllComponents(mandatoryCheckbox);
} }
@Override @Override
protected void save(final ClickEvent event) { protected void save(final ClickEvent event) {
final DistributionSetType existingDistTypeByKey = distributionSetManagement
if (mandatoryValuesPresent()) { .findDistributionSetTypeByKey(typeKey.getValue());
final DistributionSetType existingDistTypeByKey = distributionSetManagement final DistributionSetType existingDistTypeByName = distributionSetManagement
.findDistributionSetTypeByKey(typeKey.getValue()); .findDistributionSetTypeByName(tagName.getValue());
final DistributionSetType existingDistTypeByName = distributionSetManagement if (optiongroup.getValue().equals(createTypeStr)) {
.findDistributionSetTypeByName(tagName.getValue()); if (!checkIsDuplicateByKey(existingDistTypeByKey) && !checkIsDuplicate(existingDistTypeByName)) {
if (optiongroup.getValue().equals(createTypeStr)) { createNewDistributionSetType();
if (!checkIsDuplicateByKey(existingDistTypeByKey) && !checkIsDuplicate(existingDistTypeByName)) {
createNewDistributionSetType();
}
} else {
updateDistributionSetType(existingDistTypeByKey);
} }
}
}
@Override
public void createWindow() {
reset();
window = SPUIComponentProvider.getWindow(i18n.get("caption.add.type"), null,
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, this::save, this::discard, null);
}
@Override
protected void previewButtonClicked() {
if (!tagPreviewBtnClicked) {
final String selectedOption = (String) optiongroup.getValue();
if (null != selectedOption && selectedOption.equalsIgnoreCase(updateTypeStr)
&& null != tagNameComboBox.getValue()) {
final DistributionSetType existedDistType = distributionSetManagement
.findDistributionSetTypeByKey(tagNameComboBox.getValue().toString());
if (null != existedDistType) {
getColorPickerLayout().setSelectedColor(existedDistType.getColour() != null
? ColorPickerHelper.rgbToColorConverter(existedDistType.getColour())
: ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR));
} else {
getColorPickerLayout().setSelectedColor(
ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR));
}
}
getColorPickerLayout().getSelPreview().setColor(getColorPickerLayout().getSelectedColor());
mainLayout.addComponent(colorPickerLayout, 1, 0);
mainLayout.setComponentAlignment(colorPickerLayout, Alignment.MIDDLE_CENTER);
} else { } else {
mainLayout.removeComponent(colorPickerLayout); updateDistributionSetType(existingDistTypeByKey);
} }
tagPreviewBtnClicked = !tagPreviewBtnClicked; }
@Override
protected String getWindowCaption() {
return i18n.get("caption.add.type");
} }
@Override @Override

View File

@@ -96,7 +96,7 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet
private VerticalLayout tagsLayout; private VerticalLayout tagsLayout;
Map<String, StringBuilder> assignedSWModule = new HashMap<>(); private final Map<String, StringBuilder> assignedSWModule = new HashMap<>();
@EventBusListenerMethod(scope = EventScope.SESSION) @EventBusListenerMethod(scope = EventScope.SESSION)
@@ -297,8 +297,7 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet
@Override @Override
protected void onEdit(final ClickEvent event) { protected void onEdit(final ClickEvent event) {
final Window newDistWindow = distributionAddUpdateWindowLayout.getWindow(); final Window newDistWindow = distributionAddUpdateWindowLayout.getWindow(getSelectedBaseEntityId());
distributionAddUpdateWindowLayout.populateValuesOfDistribution(getSelectedBaseEntityId());
newDistWindow.setCaption(getI18n().get("caption.update.dist")); newDistWindow.setCaption(getI18n().get("caption.update.dist"));
UI.getCurrent().addWindow(newDistWindow); UI.getCurrent().addWindow(newDistWindow);
newDistWindow.setVisible(Boolean.TRUE); newDistWindow.setVisible(Boolean.TRUE);

View File

@@ -152,7 +152,7 @@ public class DistributionSetTableHeader extends AbstractTableHeader {
@Override @Override
protected void addNewItem(final ClickEvent event) { protected void addNewItem(final ClickEvent event) {
final Window newDistWindow = addUpdateWindowLayout.getWindow(); final Window newDistWindow = addUpdateWindowLayout.getWindow(null);
newDistWindow.setCaption(i18n.get("caption.add.new.dist")); newDistWindow.setCaption(i18n.get("caption.add.new.dist"));
UI.getCurrent().addWindow(newDistWindow); UI.getCurrent().addWindow(newDistWindow);
newDistWindow.setVisible(Boolean.TRUE); newDistWindow.setVisible(Boolean.TRUE);

View File

@@ -20,17 +20,16 @@ import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerLayout; import org.eclipse.hawkbit.ui.colorpicker.ColorPickerLayout;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow; import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; 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.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.I18N; import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions; import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UINotification; import org.eclipse.hawkbit.ui.utils.UINotification;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.spring.events.EventBus; import org.vaadin.spring.events.EventBus;
import com.google.common.base.Strings;
import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener; import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.server.Page; import com.vaadin.server.Page;
@@ -87,7 +86,6 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
protected CommonDialogWindow window; protected CommonDialogWindow window;
protected Label colorLabel; protected Label colorLabel;
protected Label madatoryLabel;
protected TextField tagName; protected TextField tagName;
protected TextArea tagDesc; protected TextArea tagDesc;
protected Button tagColorPreviewBtn; protected Button tagColorPreviewBtn;
@@ -99,17 +97,13 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
protected GridLayout mainLayout; protected GridLayout mainLayout;
protected VerticalLayout contentLayout; protected VerticalLayout contentLayout;
protected boolean tagPreviewBtnClicked = false; protected boolean tagPreviewBtnClicked;
private String colorPicked; private String colorPicked;
protected String tagNameValue; protected String tagNameValue;
protected String tagDescValue; protected String tagDescValue;
protected void createWindow() { protected abstract String getWindowCaption();
reset();
setWindow(SPUIComponentProvider.getWindow(i18n.get("caption.add.tag"), null,
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, this::save, this::discard, null));
}
/** /**
* Save new tag / update new tag. * Save new tag / update new tag.
@@ -142,7 +136,6 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
setSizeUndefined(); setSizeUndefined();
createRequiredComponents(); createRequiredComponents();
buildLayout(); buildLayout();
createWindow();
addListeners(); addListeners();
eventBus.subscribe(this); eventBus.subscribe(this);
} }
@@ -157,7 +150,6 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
createTagStr = i18n.get("label.create.tag"); createTagStr = i18n.get("label.create.tag");
updateTagStr = i18n.get("label.update.tag"); updateTagStr = i18n.get("label.update.tag");
comboLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.tag"), null); comboLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.tag"), null);
madatoryLabel = getMandatoryLabel();
colorLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.tag.color"), null); colorLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.tag.color"), null);
colorLabel.addStyleName(SPUIDefinitions.COLOR_LABEL_STYLE); colorLabel.addStyleName(SPUIDefinitions.COLOR_LABEL_STYLE);
@@ -169,7 +161,6 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
tagDesc = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "", tagDesc = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "",
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TAG_DESC, false, "", i18n.get("textfield.description"), ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TAG_DESC, false, "", i18n.get("textfield.description"),
SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH); SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
tagDesc.setId(SPUIDefinitions.NEW_TARGET_TAG_DESC); tagDesc.setId(SPUIDefinitions.NEW_TARGET_TAG_DESC);
tagDesc.setImmediate(true); tagDesc.setImmediate(true);
tagDesc.setNullRepresentation(""); tagDesc.setNullRepresentation("");
@@ -178,6 +169,7 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
i18n.get("label.combobox.tag")); i18n.get("label.combobox.tag"));
tagNameComboBox.addStyleName(SPUIDefinitions.FILTER_TYPE_COMBO_STYLE); tagNameComboBox.addStyleName(SPUIDefinitions.FILTER_TYPE_COMBO_STYLE);
tagNameComboBox.setImmediate(true); tagNameComboBox.setImmediate(true);
tagNameComboBox.setId(SPUIComponentIdProvider.DIST_TAG_COMBO);
tagColorPreviewBtn = new Button(); tagColorPreviewBtn = new Button();
tagColorPreviewBtn.setId(SPUIComponentIdProvider.TAG_COLOR_PREVIEW_ID); tagColorPreviewBtn.setId(SPUIComponentIdProvider.TAG_COLOR_PREVIEW_ID);
@@ -200,7 +192,6 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
formLayout.addComponent(optiongroup); formLayout.addComponent(optiongroup);
formLayout.addComponent(comboLayout); formLayout.addComponent(comboLayout);
formLayout.addComponent(madatoryLabel);
formLayout.addComponent(tagName); formLayout.addComponent(tagName);
formLayout.addComponent(tagDesc); formLayout.addComponent(tagDesc);
formLayout.addStyleName("form-lastrow"); formLayout.addStyleName("form-lastrow");
@@ -215,6 +206,10 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
mainLayout.setSizeFull(); mainLayout.setSizeFull();
mainLayout.addComponent(contentLayout, 0, 0); mainLayout.addComponent(contentLayout, 0, 0);
colorPickerLayout.setVisible(false);
mainLayout.addComponent(colorPickerLayout, 1, 0);
mainLayout.setComponentAlignment(colorPickerLayout, Alignment.MIDDLE_CENTER);
setCompositionRoot(mainLayout); setCompositionRoot(mainLayout);
tagName.focus(); tagName.focus();
} }
@@ -234,13 +229,10 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
protected void previewButtonClicked() { protected void previewButtonClicked() {
if (!tagPreviewBtnClicked) { if (!tagPreviewBtnClicked) {
setColor(); setColor();
mainLayout.getComponent(1, 0);
mainLayout.addComponent(colorPickerLayout, 1, 0);
mainLayout.setComponentAlignment(colorPickerLayout, Alignment.MIDDLE_CENTER);
} else {
mainLayout.removeComponent(colorPickerLayout);
} }
tagPreviewBtnClicked = !tagPreviewBtnClicked; tagPreviewBtnClicked = !tagPreviewBtnClicked;
colorPickerLayout.setVisible(tagPreviewBtnClicked);
} }
private void setColor() { private void setColor() {
@@ -270,12 +262,6 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
} }
} }
protected Label getMandatoryLabel() {
final Label label = new Label(i18n.get("label.mandatory.field"));
label.setStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR + " " + ValoTheme.LABEL_SMALL);
return label;
}
private void tagNameChosen(final ValueChangeEvent event) { private void tagNameChosen(final ValueChangeEvent event) {
final String tagSelected = (String) event.getProperty().getValue(); final String tagSelected = (String) event.getProperty().getValue();
if (null != tagSelected) { if (null != tagSelected) {
@@ -283,6 +269,7 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
} else { } else {
resetTagNameField(); resetTagNameField();
} }
window.setOrginaleValues();
} }
protected void resetTagNameField() { protected void resetTagNameField() {
@@ -290,7 +277,6 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
tagName.clear(); tagName.clear();
tagDesc.clear(); tagDesc.clear();
restoreComponentStyles(); restoreComponentStyles();
mainLayout.removeComponent(colorPickerLayout);
colorPickerLayout.setSelectedColor(colorPickerLayout.getDefaultColor()); colorPickerLayout.setSelectedColor(colorPickerLayout.getDefaultColor());
colorPickerLayout.getSelPreview().setColor(colorPickerLayout.getSelectedColor()); colorPickerLayout.getSelPreview().setColor(colorPickerLayout.getSelectedColor());
tagPreviewBtnClicked = false; tagPreviewBtnClicked = false;
@@ -327,7 +313,7 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
getPreviewButtonColor(ColorPickerConstants.DEFAULT_COLOR); getPreviewButtonColor(ColorPickerConstants.DEFAULT_COLOR);
colorPickerLayout.getSelPreview() colorPickerLayout.getSelPreview()
.setColor(ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR)); .setColor(ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR));
mainLayout.removeComponent(colorPickerLayout); window.setOrginaleValues();
} }
/** /**
@@ -342,9 +328,9 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
// hide target name combo // hide target name combo
comboLayout.removeComponent(comboLabel); comboLayout.removeComponent(comboLabel);
comboLayout.removeComponent(tagNameComboBox); comboLayout.removeComponent(tagNameComboBox);
mainLayout.removeComponent(colorPickerLayout);
// Default green color // Default green color
colorPickerLayout.setVisible(false);
colorPickerLayout.setSelectedColor(colorPickerLayout.getDefaultColor()); colorPickerLayout.setSelectedColor(colorPickerLayout.getDefaultColor());
colorPickerLayout.getSelPreview().setColor(colorPickerLayout.getSelectedColor()); colorPickerLayout.getSelPreview().setColor(colorPickerLayout.getSelectedColor());
tagPreviewBtnClicked = false; tagPreviewBtnClicked = false;
@@ -389,6 +375,7 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
*/ */
protected void createDynamicStyleForComponents(final TextField tagName, final TextArea tagDesc, protected void createDynamicStyleForComponents(final TextField tagName, final TextArea tagDesc,
final String taregtTagColor) { final String taregtTagColor) {
tagName.removeStyleName(SPUIDefinitions.TAG_NAME); tagName.removeStyleName(SPUIDefinitions.TAG_NAME);
tagDesc.removeStyleName(SPUIDefinitions.TAG_DESC); tagDesc.removeStyleName(SPUIDefinitions.TAG_DESC);
getTargetDynamicStyles(taregtTagColor); getTargetDynamicStyles(taregtTagColor);
@@ -435,11 +422,7 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
createDynamicStyleForComponents(tagName, tagDesc, colorPickedPreview); createDynamicStyleForComponents(tagName, tagDesc, colorPickedPreview);
colorPickerLayout.getColorSelect().setColor(colorPickerLayout.getSelPreview().getColor()); colorPickerLayout.getColorSelect().setColor(colorPickerLayout.getSelPreview().getColor());
} }
}
protected void closeWindow() {
window.close();
UI.getCurrent().removeWindow(window);
} }
/** /**
@@ -448,6 +431,7 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
protected void createOptionGroup(final boolean hasCreatePermission, final boolean hasUpdatePermission) { protected void createOptionGroup(final boolean hasCreatePermission, final boolean hasUpdatePermission) {
optiongroup = new OptionGroup("Select Action"); optiongroup = new OptionGroup("Select Action");
optiongroup.setId(SPUIComponentIdProvider.OPTION_GROUP);
optiongroup.addStyleName(ValoTheme.OPTIONGROUP_SMALL); optiongroup.addStyleName(ValoTheme.OPTIONGROUP_SMALL);
optiongroup.addStyleName("custom-option-group"); optiongroup.addStyleName("custom-option-group");
optiongroup.setNullSelectionAllowed(false); optiongroup.setNullSelectionAllowed(false);
@@ -472,27 +456,17 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
} }
} }
@Override
public void addColorChangeListener(final ColorChangeListener listener) {
}
@Override
public void removeColorChangeListener(final ColorChangeListener listener) {
}
public ColorPickerLayout getColorPickerLayout() { public ColorPickerLayout getColorPickerLayout() {
return colorPickerLayout; return colorPickerLayout;
} }
public CommonDialogWindow getWindow() { public CommonDialogWindow getWindow() {
reset(); reset();
window = SPUIWindowDecorator.getWindow(getWindowCaption(), null, SPUIDefinitions.CREATE_UPDATE_WINDOW, this,
this::save, this::discard, null, mainLayout, i18n);
return window; return window;
} }
public void setWindow(final CommonDialogWindow window) {
this.window = window;
}
/** /**
* Value change listeners implementations of sliders. * Value change listeners implementations of sliders.
*/ */
@@ -565,7 +539,6 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
tagManagement.updateDistributionSetTag((DistributionSetTag) targetObj); tagManagement.updateDistributionSetTag((DistributionSetTag) targetObj);
} }
uiNotification.displaySuccess(i18n.get("message.update.success", new Object[] { targetObj.getName() })); uiNotification.displaySuccess(i18n.get("message.update.success", new Object[] { targetObj.getName() }));
closeWindow();
} else { } else {
uiNotification.displayValidationError(i18n.get("message.tag.update.mandatory")); uiNotification.displayValidationError(i18n.get("message.tag.update.mandatory"));
} }
@@ -587,27 +560,6 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
getPreviewButtonColor(previewColor); getPreviewButtonColor(previewColor);
} }
/**
*
* @return
*/
protected Boolean mandatoryValuesPresent() {
if (Strings.isNullOrEmpty(tagName.getValue())) {
if (optiongroup.getValue().equals(createTagStr)) {
displayValidationError(SPUILabelDefinitions.MISSING_TAG_NAME);
}
if (optiongroup.getValue().equals(updateTagStr)) {
if (null == tagNameComboBox.getValue()) {
displayValidationError(i18n.get(MESSAGE_ERROR_MISSING_TAGNAME));
} else {
displayValidationError(SPUILabelDefinitions.MISSING_TAG_NAME);
}
}
return Boolean.FALSE;
}
return Boolean.TRUE;
}
protected Boolean checkIsDuplicate(final Tag existingTag) { protected Boolean checkIsDuplicate(final Tag existingTag) {
if (existingTag != null) { if (existingTag != null) {
displayValidationError(i18n.get("message.tag.duplicate.check", new Object[] { existingTag.getName() })); displayValidationError(i18n.get("message.tag.duplicate.check", new Object[] { existingTag.getName() }));
@@ -644,4 +596,16 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
return formLayout; return formLayout;
} }
public GridLayout getMainLayout() {
return mainLayout;
}
@Override
public void addColorChangeListener(final ColorChangeListener listener) {
}
@Override
public void removeColorChangeListener(final ColorChangeListener listener) {
}
} }

View File

@@ -17,9 +17,7 @@ import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import com.google.common.base.Strings;
import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.server.Page; import com.vaadin.server.Page;
import com.vaadin.shared.ui.colorpicker.Color; import com.vaadin.shared.ui.colorpicker.Color;
@@ -33,12 +31,10 @@ import com.vaadin.ui.components.colorpicker.ColorSelector;
import com.vaadin.ui.themes.ValoTheme; import com.vaadin.ui.themes.ValoTheme;
/** /**
*
* Superclass defining common properties and methods for creating/updating * Superclass defining common properties and methods for creating/updating
* types. * types.
*
*/ */
public class CreateUpdateTypeLayout extends AbstractCreateUpdateTagLayout { public abstract class CreateUpdateTypeLayout extends AbstractCreateUpdateTagLayout {
private static final long serialVersionUID = 5732904956185988397L; private static final long serialVersionUID = 5732904956185988397L;
@@ -52,7 +48,7 @@ public class CreateUpdateTypeLayout extends AbstractCreateUpdateTagLayout {
@Override @Override
protected void addListeners() { protected void addListeners() {
super.addListeners(); super.addListeners();
optiongroup.addValueChangeListener(this::createOptionValueChanged); optiongroup.addValueChangeListener(this::optionValueChanged);
} }
@Override @Override
@@ -61,7 +57,6 @@ public class CreateUpdateTypeLayout extends AbstractCreateUpdateTagLayout {
createTypeStr = i18n.get("label.create.type"); createTypeStr = i18n.get("label.create.type");
updateTypeStr = i18n.get("label.update.type"); updateTypeStr = i18n.get("label.update.type");
comboLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.type"), null); comboLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.type"), null);
madatoryLabel = getMandatoryLabel();
colorLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.type.color"), null); colorLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.type.color"), null);
colorLabel.addStyleName(SPUIDefinitions.COLOR_LABEL_STYLE); colorLabel.addStyleName(SPUIDefinitions.COLOR_LABEL_STYLE);
@@ -137,7 +132,8 @@ public class CreateUpdateTypeLayout extends AbstractCreateUpdateTagLayout {
* @param event * @param event
* ValueChangeEvent * ValueChangeEvent
*/ */
protected void createOptionValueChanged(final ValueChangeEvent event) { @Override
protected void optionValueChanged(final ValueChangeEvent event) {
if (updateTypeStr.equals(event.getProperty().getValue())) { if (updateTypeStr.equals(event.getProperty().getValue())) {
tagName.clear(); tagName.clear();
@@ -151,7 +147,6 @@ public class CreateUpdateTypeLayout extends AbstractCreateUpdateTagLayout {
} else { } else {
typeKey.setEnabled(true); typeKey.setEnabled(true);
tagName.setEnabled(true); tagName.setEnabled(true);
window.setSaveButtonEnabled(true);
tagName.clear(); tagName.clear();
tagDesc.clear(); tagDesc.clear();
typeKey.clear(); typeKey.clear();
@@ -203,6 +198,7 @@ public class CreateUpdateTypeLayout extends AbstractCreateUpdateTagLayout {
protected void createOptionGroup(final boolean hasCreatePermission, final boolean hasUpdatePermission) { protected void createOptionGroup(final boolean hasCreatePermission, final boolean hasUpdatePermission) {
optiongroup = new OptionGroup("Select Action"); optiongroup = new OptionGroup("Select Action");
optiongroup.setId(SPUIComponentIdProvider.OPTION_GROUP);
optiongroup.addStyleName(ValoTheme.OPTIONGROUP_SMALL); optiongroup.addStyleName(ValoTheme.OPTIONGROUP_SMALL);
optiongroup.addStyleName("custom-option-group"); optiongroup.addStyleName("custom-option-group");
optiongroup.setNullSelectionAllowed(false); optiongroup.setNullSelectionAllowed(false);
@@ -285,24 +281,6 @@ public class CreateUpdateTypeLayout extends AbstractCreateUpdateTagLayout {
return Boolean.FALSE; return Boolean.FALSE;
} }
@Override
protected Boolean mandatoryValuesPresent() {
if (Strings.isNullOrEmpty(tagName.getValue()) || Strings.isNullOrEmpty(typeKey.getValue())) {
if (optiongroup.getValue().equals(createTypeStr)) {
displayValidationError(SPUILabelDefinitions.MISSING_TYPE_NAME_KEY);
}
if (optiongroup.getValue().equals(updateTypeStr)) {
if (null == tagNameComboBox.getValue()) {
displayValidationError(i18n.get("message.error.missing.tagName"));
} else {
displayValidationError(SPUILabelDefinitions.MISSING_TAG_NAME);
}
}
return Boolean.FALSE;
}
return Boolean.TRUE;
}
@Override @Override
protected void save(final ClickEvent event) { protected void save(final ClickEvent event) {
// is implemented in the inherited class // is implemented in the inherited class

View File

@@ -8,9 +8,7 @@
*/ */
package org.eclipse.hawkbit.ui.management.dstable; package org.eclipse.hawkbit.ui.management.dstable;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
@@ -26,6 +24,7 @@ import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.DistributionSetTypeBeanQuery; import org.eclipse.hawkbit.ui.common.DistributionSetTypeBeanQuery;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIWindowDecorator;
import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent; import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent;
import org.eclipse.hawkbit.ui.management.event.DragEvent; import org.eclipse.hawkbit.ui.management.event.DragEvent;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
@@ -43,26 +42,18 @@ import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
import org.vaadin.addons.lazyquerycontainer.LazyQueryDefinition; import org.vaadin.addons.lazyquerycontainer.LazyQueryDefinition;
import org.vaadin.spring.events.EventBus; import org.vaadin.spring.events.EventBus;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.event.FieldEvents.TextChangeListener;
import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope; import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.CheckBox; import com.vaadin.ui.CheckBox;
import com.vaadin.ui.ComboBox; import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent; import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.FormLayout; import com.vaadin.ui.FormLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextArea; import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField; import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.themes.ValoTheme; import com.vaadin.ui.themes.ValoTheme;
/** /**
* * WindowContent for adding/editing a Distribution
*
*/ */
@SpringComponent @SpringComponent
@ViewScope @ViewScope
@@ -92,24 +83,12 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
private TextField distNameTextField; private TextField distNameTextField;
private TextField distVersionTextField; private TextField distVersionTextField;
private Label madatoryLabel;
private TextArea descTextArea; private TextArea descTextArea;
private CheckBox reqMigStepCheckbox; private CheckBox reqMigStepCheckbox;
private ComboBox distsetTypeNameComboBox; private ComboBox distsetTypeNameComboBox;
private boolean editDistribution = Boolean.FALSE; private boolean editDistribution = Boolean.FALSE;
private Long editDistId; private Long editDistId;
private CommonDialogWindow addDistributionWindow; private CommonDialogWindow window;
private String originalDistName;
private String originalDistVersion;
private String originalDistDescription;
private Boolean originalReqMigStep;
private String originalDistSetType;
private final List<Component> changedComponents = new ArrayList<>();
private ValueChangeListener reqMigStepCheckboxListerner;
private TextChangeListener descTextAreaListener;
private TextChangeListener distNameTextFieldListener;
private TextChangeListener distVersionTextFieldListener;
private ValueChangeListener distsetTypeNameComboBoxListener;
private FormLayout formLayout; private FormLayout formLayout;
@@ -123,16 +102,10 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
} }
private void buildLayout() { private void buildLayout() {
/*
* The main layout of the window contains mandatory info, textboxes
* (controller Id, name & description) and action buttons layout
*/
addStyleName("lay-color"); addStyleName("lay-color");
setSizeUndefined(); setSizeUndefined();
formLayout = new FormLayout(); formLayout = new FormLayout();
formLayout.addComponent(madatoryLabel);
formLayout.addComponent(distsetTypeNameComboBox); formLayout.addComponent(distsetTypeNameComboBox);
formLayout.addComponent(distNameTextField); formLayout.addComponent(distNameTextField);
formLayout.addComponent(distVersionTextField); formLayout.addComponent(distVersionTextField);
@@ -140,7 +113,6 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
formLayout.addComponent(reqMigStepCheckbox); formLayout.addComponent(reqMigStepCheckbox);
setCompositionRoot(formLayout); setCompositionRoot(formLayout);
distNameTextField.focus(); distNameTextField.focus();
} }
@@ -164,6 +136,7 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
distsetTypeNameComboBox.setImmediate(true); distsetTypeNameComboBox.setImmediate(true);
distsetTypeNameComboBox.setNullSelectionAllowed(false); distsetTypeNameComboBox.setNullSelectionAllowed(false);
distsetTypeNameComboBox.setId(SPUIComponentIdProvider.DIST_ADD_DISTSETTYPE); distsetTypeNameComboBox.setId(SPUIComponentIdProvider.DIST_ADD_DISTSETTYPE);
populateDistSetTypeNameCombo();
descTextArea = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "text-area-style", descTextArea = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "text-area-style",
ValoTheme.TEXTAREA_TINY, false, null, i18n.get("textfield.description"), ValoTheme.TEXTAREA_TINY, false, null, i18n.get("textfield.description"),
@@ -171,10 +144,6 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
descTextArea.setId(SPUIComponentIdProvider.DIST_ADD_DESC); descTextArea.setId(SPUIComponentIdProvider.DIST_ADD_DESC);
descTextArea.setNullRepresentation(""); descTextArea.setNullRepresentation("");
/* Label for mandatory symbol */
madatoryLabel = new Label(i18n.get("label.mandatory.field"));
madatoryLabel.setStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR + " " + ValoTheme.LABEL_SMALL);
reqMigStepCheckbox = SPUIComponentProvider.getCheckBox(i18n.get("checkbox.dist.required.migration.step"), reqMigStepCheckbox = SPUIComponentProvider.getCheckBox(i18n.get("checkbox.dist.required.migration.step"),
"dist-checkbox-style", null, false, ""); "dist-checkbox-style", null, false, "");
reqMigStepCheckbox.addStyleName(ValoTheme.CHECKBOX_SMALL); reqMigStepCheckbox.addStyleName(ValoTheme.CHECKBOX_SMALL);
@@ -200,27 +169,17 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
return disttypeContainer; return disttypeContainer;
} }
private void enableSaveButton() {
addDistributionWindow.setSaveButtonEnabled(true);
}
private DistributionSetType getDefaultDistributionSetType() { private DistributionSetType getDefaultDistributionSetType() {
final TenantMetaData tenantMetaData = systemManagement.getTenantMetadata(); final TenantMetaData tenantMetaData = systemManagement.getTenantMetadata();
return tenantMetaData.getDefaultDsType(); return tenantMetaData.getDefaultDsType();
} }
private void disableSaveButton() {
addDistributionWindow.setSaveButtonEnabled(false);
}
private void saveDistribution() { private void saveDistribution() {
/* add new or update target */
if (editDistribution) { if (editDistribution) {
updateDistribution(); updateDistribution();
} else { } else {
addNewDistribution(); addNewDistribution();
} }
} }
/** /**
@@ -232,7 +191,7 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
final String distSetTypeName = HawkbitCommonUtil final String distSetTypeName = HawkbitCommonUtil
.trimAndNullIfEmpty((String) distsetTypeNameComboBox.getValue()); .trimAndNullIfEmpty((String) distsetTypeNameComboBox.getValue());
if (mandatoryCheck(name, version, distSetTypeName) && duplicateCheck(name, version)) { if (duplicateCheck(name, version)) {
final DistributionSet currentDS = distributionSetManagement.findDistributionSetByIdWithDetails(editDistId); final DistributionSet currentDS = distributionSetManagement.findDistributionSetByIdWithDetails(editDistId);
final String desc = HawkbitCommonUtil.trimAndNullIfEmpty(descTextArea.getValue()); final String desc = HawkbitCommonUtil.trimAndNullIfEmpty(descTextArea.getValue());
final boolean isMigStepReq = reqMigStepCheckbox.getValue(); final boolean isMigStepReq = reqMigStepCheckbox.getValue();
@@ -250,23 +209,9 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
notificationMessage.displayValidationError( notificationMessage.displayValidationError(
i18n.get("message.distribution.no.update", currentDS.getName() + ":" + currentDS.getVersion())); i18n.get("message.distribution.no.update", currentDS.getName() + ":" + currentDS.getVersion()));
} }
closeThisWindow();
} }
} }
private void addListeners() {
reqMigStepCheckboxListerner = event -> checkValueChanged(originalReqMigStep, event);
descTextAreaListener = event -> checkValueChanged(originalDistDescription, event);
distNameTextFieldListener = event -> checkValueChanged(originalDistName, event);
distVersionTextFieldListener = event -> checkValueChanged(originalDistVersion, event);
distsetTypeNameComboBoxListener = event -> checkValueChanged(originalDistSetType, event);
reqMigStepCheckbox.addValueChangeListener(reqMigStepCheckboxListerner);
descTextArea.addTextChangeListener(descTextAreaListener);
distNameTextField.addTextChangeListener(distNameTextFieldListener);
distVersionTextField.addTextChangeListener(distVersionTextFieldListener);
distsetTypeNameComboBox.addValueChangeListener(distsetTypeNameComboBoxListener);
}
/** /**
* Add new Distribution set. * Add new Distribution set.
*/ */
@@ -277,7 +222,7 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
final String distSetTypeName = HawkbitCommonUtil final String distSetTypeName = HawkbitCommonUtil
.trimAndNullIfEmpty((String) distsetTypeNameComboBox.getValue()); .trimAndNullIfEmpty((String) distsetTypeNameComboBox.getValue());
if (mandatoryCheck(name, version, distSetTypeName) && duplicateCheck(name, version)) { if (duplicateCheck(name, version)) {
final String desc = HawkbitCommonUtil.trimAndNullIfEmpty(descTextArea.getValue()); final String desc = HawkbitCommonUtil.trimAndNullIfEmpty(descTextArea.getValue());
final boolean isMigStepReq = reqMigStepCheckbox.getValue(); final boolean isMigStepReq = reqMigStepCheckbox.getValue();
DistributionSet newDist = entityFactory.generateDistributionSet(); DistributionSet newDist = entityFactory.generateDistributionSet();
@@ -287,21 +232,11 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
notificationMessage.displaySuccess(i18n.get("message.new.dist.save.success", notificationMessage.displaySuccess(i18n.get("message.new.dist.save.success",
new Object[] { newDist.getName(), newDist.getVersion() })); new Object[] { newDist.getName(), newDist.getVersion() }));
/* close the window */
closeThisWindow();
eventBus.publish(this, new DistributionTableEvent(BaseEntityEventType.NEW_ENTITY, newDist)); eventBus.publish(this, new DistributionTableEvent(BaseEntityEventType.NEW_ENTITY, newDist));
} }
} }
/**
* Close window.
*/
private void closeThisWindow() {
addDistributionWindow.close();
UI.getCurrent().removeWindow(addDistributionWindow);
}
/** /**
* Set Values for Distribution set. * Set Values for Distribution set.
* *
@@ -345,47 +280,6 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
} }
} }
/**
* Mandatory Check.
*
* @param name
* as String
* @param version
* as String
* @param selectedJVM
* as String
* @param selectedAgentHub
* as String
* @param selectedOs
* as String
* @return boolean as flag
*/
private boolean mandatoryCheck(final String name, final String version, final String distSetTypeName) {
if (name == null || version == null || distSetTypeName == null) {
if (name == null) {
distNameTextField.addStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR);
}
if (version == null) {
distVersionTextField.addStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR);
}
if (distSetTypeName == null) {
distsetTypeNameComboBox.addStyleName(SPUIStyleDefinitions.SP_COMBOFIELD_ERROR);
}
notificationMessage.displayValidationError(i18n.get("message.mandatory.check"));
return false;
}
return true;
}
private void discardDistribution() {
/* Just close this window */
distsetTypeNameComboBox.removeValueChangeListener(distsetTypeNameComboBoxListener);
closeThisWindow();
}
/** /**
* clear all the fields. * clear all the fields.
*/ */
@@ -398,139 +292,52 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
distsetTypeNameComboBox.removeStyleName(SPUIStyleDefinitions.SP_COMBOFIELD_ERROR); distsetTypeNameComboBox.removeStyleName(SPUIStyleDefinitions.SP_COMBOFIELD_ERROR);
descTextArea.clear(); descTextArea.clear();
reqMigStepCheckbox.clear(); reqMigStepCheckbox.clear();
if (addDistributionWindow != null) {
addDistributionWindow.setSaveButtonEnabled(true);
}
removeListeners();
changedComponents.clear();
} }
private void populateRequiredComponents() { private void populateValuesOfDistribution(final Long editDistId) {
populateDistSetTypeNameCombo();
}
private void removeListeners() {
reqMigStepCheckbox.removeValueChangeListener(reqMigStepCheckboxListerner);
descTextArea.removeTextChangeListener(descTextAreaListener);
distNameTextField.removeTextChangeListener(distNameTextFieldListener);
distVersionTextField.removeTextChangeListener(distVersionTextFieldListener);
}
public void setOriginalDistName(final String originalDistName) {
this.originalDistName = originalDistName;
}
public void setOriginalDistVersion(final String originalDistVersion) {
this.originalDistVersion = originalDistVersion;
}
public void setOriginalDistDescription(final String originalDistDescription) {
this.originalDistDescription = originalDistDescription;
}
private void checkValueChanged(final String originalValue, final TextChangeEvent event) {
if (editDistribution) {
final String newValue = event.getText();
if (!originalValue.equalsIgnoreCase(newValue)) {
changedComponents.add(event.getComponent());
} else {
changedComponents.remove(event.getComponent());
}
enableDisableSaveButton();
}
}
private void checkValueChanged(final Boolean originalValue, final ValueChangeEvent event) {
if (editDistribution) {
if (!originalValue.equals(event.getProperty().getValue())) {
changedComponents.add(reqMigStepCheckbox);
} else {
changedComponents.remove(reqMigStepCheckbox);
}
enableDisableSaveButton();
}
}
private void checkValueChanged(final String originalValue, final ValueChangeEvent event) {
if (editDistribution) {
if (!originalValue.equals(event.getProperty().getValue())) {
changedComponents.add(distsetTypeNameComboBox);
} else {
changedComponents.remove(distsetTypeNameComboBox);
}
enableDisableSaveButton();
}
}
private void enableDisableSaveButton() {
if (changedComponents.isEmpty()) {
disableSaveButton();
} else {
enableSaveButton();
}
}
private void setOriginalReqMigStep(final Boolean originalReqMigStep) {
this.originalReqMigStep = originalReqMigStep;
}
/**
* populate data.
*
* @param editDistId
*/
public void populateValuesOfDistribution(final Long editDistId) {
this.editDistId = editDistId; this.editDistId = editDistId;
editDistribution = Boolean.TRUE;
addDistributionWindow.setSaveButtonEnabled(false); if (editDistId == null) {
return;
}
final DistributionSet distSet = distributionSetManagement.findDistributionSetByIdWithDetails(editDistId); final DistributionSet distSet = distributionSetManagement.findDistributionSetByIdWithDetails(editDistId);
if (distSet != null) { if (distSet == null) {
distNameTextField.setValue(distSet.getName()); return;
distVersionTextField.setValue(distSet.getVersion()); }
if (distSet.getType().isDeleted()) {
distsetTypeNameComboBox.addItem(distSet.getType().getName()); editDistribution = Boolean.TRUE;
} distNameTextField.setValue(distSet.getName());
distsetTypeNameComboBox.setValue(distSet.getType().getName()); distVersionTextField.setValue(distSet.getVersion());
reqMigStepCheckbox.setValue(distSet.isRequiredMigrationStep()); if (distSet.getType().isDeleted()) {
if (distSet.getDescription() != null) { distsetTypeNameComboBox.addItem(distSet.getType().getName());
descTextArea.setValue(distSet.getDescription()); }
} distsetTypeNameComboBox.setValue(distSet.getType().getName());
setOriginalDistName(distSet.getName()); reqMigStepCheckbox.setValue(distSet.isRequiredMigrationStep());
setOriginalDistVersion(distSet.getVersion()); if (distSet.getDescription() != null) {
setOriginalDistDescription(distSet.getDescription()); descTextArea.setValue(distSet.getDescription());
setOriginalReqMigStep(distSet.isRequiredMigrationStep());
setOriginalDistSetTYpe(distSet.getType().getName());
addListeners();
} }
} }
public CommonDialogWindow getWindow() { public CommonDialogWindow getWindow(final Long editDistId) {
eventBus.publish(this, DragEvent.HIDE_DROP_HINT); eventBus.publish(this, DragEvent.HIDE_DROP_HINT);
populateRequiredComponents();
resetComponents(); resetComponents();
addDistributionWindow = SPUIComponentProvider.getWindow(i18n.get("caption.add.new.dist"), null, populateDistSetTypeNameCombo();
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> saveDistribution(), event -> discardDistribution(), populateValuesOfDistribution(editDistId);
null); window = SPUIWindowDecorator.getWindow(i18n.get("caption.add.new.dist"), null,
addDistributionWindow.getButtonsLayout().removeStyleName("actionButtonsMargin"); SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> saveDistribution(), null, null, formLayout, i18n);
window.getButtonsLayout().removeStyleName("actionButtonsMargin");
return addDistributionWindow; return window;
} }
/** /**
* Populate DistributionSet Type name combo. * Populate DistributionSet Type name combo.
*/ */
public void populateDistSetTypeNameCombo() { private void populateDistSetTypeNameCombo() {
distsetTypeNameComboBox.setContainerDataSource(getDistSetTypeLazyQueryContainer()); distsetTypeNameComboBox.setContainerDataSource(getDistSetTypeLazyQueryContainer());
distsetTypeNameComboBox.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME); distsetTypeNameComboBox.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME);
distsetTypeNameComboBox.setValue(getDefaultDistributionSetType().getName()); distsetTypeNameComboBox.setValue(getDefaultDistributionSetType().getName());
} }
/**
* @param originalDistSetTYpe
* the originalDistSetTYpe to set
*/
public void setOriginalDistSetTYpe(final String originalDistSetType) {
this.originalDistSetType = originalDistSetType;
}
} }

View File

@@ -117,8 +117,7 @@ public class DistributionDetails extends AbstractNamedVersionedEntityTableDetail
@Override @Override
protected void onEdit(final ClickEvent event) { protected void onEdit(final ClickEvent event) {
final Window newDistWindow = distributionAddUpdateWindowLayout.getWindow(); final Window newDistWindow = distributionAddUpdateWindowLayout.getWindow(getSelectedBaseEntityId());
distributionAddUpdateWindowLayout.populateValuesOfDistribution(getSelectedBaseEntityId());
newDistWindow.setCaption(getI18n().get("caption.update.dist")); newDistWindow.setCaption(getI18n().get("caption.update.dist"));
UI.getCurrent().addWindow(newDistWindow); UI.getCurrent().addWindow(newDistWindow);
newDistWindow.setVisible(Boolean.TRUE); newDistWindow.setVisible(Boolean.TRUE);

View File

@@ -154,7 +154,7 @@ public class DistributionTableHeader extends AbstractTableHeader {
@Override @Override
protected void addNewItem(final ClickEvent event) { protected void addNewItem(final ClickEvent event) {
final Window newDistWindow = distributionAddUpdateWindowLayout.getWindow(); final Window newDistWindow = distributionAddUpdateWindowLayout.getWindow(null);
newDistWindow.setCaption(i18n.get("caption.add.new.dist")); newDistWindow.setCaption(i18n.get("caption.add.new.dist"));
UI.getCurrent().addWindow(newDistWindow); UI.getCurrent().addWindow(newDistWindow);
newDistWindow.setVisible(Boolean.TRUE); newDistWindow.setVisible(Boolean.TRUE);

View File

@@ -32,9 +32,7 @@ import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.UI; import com.vaadin.ui.UI;
/** /**
*
* Class for Create/Update Tag Layout of distribution set * Class for Create/Update Tag Layout of distribution set
*
*/ */
@SpringComponent @SpringComponent
@ViewScope @ViewScope
@@ -87,16 +85,13 @@ public class CreateUpdateDistributionTagLayoutWindow extends AbstractCreateUpdat
*/ */
@Override @Override
public void save(final ClickEvent event) { public void save(final ClickEvent event) {
if (mandatoryValuesPresent()) { final DistributionSetTag existingDistTag = tagManagement.findDistributionSetTag(tagName.getValue());
final DistributionSetTag existingDistTag = tagManagement.findDistributionSetTag(tagName.getValue()); if (optiongroup.getValue().equals(createTagStr)) {
if (optiongroup.getValue().equals(createTagStr)) { if (!checkIsDuplicate(existingDistTag)) {
if (!checkIsDuplicate(existingDistTag)) { createNewTag();
createNewTag();
}
} else {
updateExistingTag(existingDistTag);
} }
} else {
updateExistingTag(existingDistTag);
} }
} }
@@ -181,4 +176,9 @@ public class CreateUpdateDistributionTagLayoutWindow extends AbstractCreateUpdat
setOptionGroupDefaultValue(permChecker.hasCreateDistributionPermission(), setOptionGroupDefaultValue(permChecker.hasCreateDistributionPermission(),
permChecker.hasUpdateDistributionPermission()); permChecker.hasUpdateDistributionPermission());
} }
@Override
protected String getWindowCaption() {
return i18n.get("caption.add.tag");
}
} }

View File

@@ -17,6 +17,7 @@ import javax.annotation.PostConstruct;
import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.ui.utils.I18N; import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil; import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.hene.flexibleoptiongroup.FlexibleOptionGroup; import org.vaadin.hene.flexibleoptiongroup.FlexibleOptionGroup;
import org.vaadin.hene.flexibleoptiongroup.FlexibleOptionGroupItemComponent; import org.vaadin.hene.flexibleoptiongroup.FlexibleOptionGroupItemComponent;
@@ -78,6 +79,7 @@ public class ActionTypeOptionGroupLayout extends HorizontalLayout {
private void createOptionGroup() { private void createOptionGroup() {
actionTypeOptionGroup = new FlexibleOptionGroup(); actionTypeOptionGroup = new FlexibleOptionGroup();
actionTypeOptionGroup.setId(SPUIComponentIdProvider.ROLLOUT_ACTION_BUTTON_ID);
actionTypeOptionGroup.addItem(ActionTypeOption.SOFT); actionTypeOptionGroup.addItem(ActionTypeOption.SOFT);
actionTypeOptionGroup.addItem(ActionTypeOption.FORCED); actionTypeOptionGroup.addItem(ActionTypeOption.FORCED);
actionTypeOptionGroup.addItem(ActionTypeOption.AUTO_FORCED); actionTypeOptionGroup.addItem(ActionTypeOption.AUTO_FORCED);

View File

@@ -10,6 +10,8 @@ package org.eclipse.hawkbit.ui.management.tag;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.vaadin.data.Property; import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeEvent;
@@ -44,7 +46,7 @@ public final class SpColorPickerPreview extends ColorPickerPreview implements Te
try { try {
final Field textField = ColorPickerPreview.class.getDeclaredField("field"); final Field textField = ColorPickerPreview.class.getDeclaredField("field");
textField.setAccessible(true); textField.setAccessible(true);
((TextField) textField.get(this)).setId("color-preview-field"); ((TextField) textField.get(this)).setId(SPUIComponentIdProvider.COLOR_PREVIEW_FIELD);
((TextField) textField.get(this)).addTextChangeListener(this); ((TextField) textField.get(this)).addTextChangeListener(this);
} catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) { } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
Throwables.propagate(e); Throwables.propagate(e);

View File

@@ -18,6 +18,7 @@ import org.eclipse.hawkbit.repository.model.TargetIdName;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow; import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIWindowDecorator;
import org.eclipse.hawkbit.ui.management.event.DragEvent; import org.eclipse.hawkbit.ui.management.event.DragEvent;
import org.eclipse.hawkbit.ui.management.event.TargetTableEvent; import org.eclipse.hawkbit.ui.management.event.TargetTableEvent;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
@@ -31,24 +32,17 @@ import org.eclipse.hawkbit.ui.utils.UINotification;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.spring.events.EventBus; import org.vaadin.spring.events.EventBus;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.event.FieldEvents.TextChangeListener;
import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.VaadinSessionScope; import com.vaadin.spring.annotation.VaadinSessionScope;
import com.vaadin.ui.CustomComponent; import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.FormLayout; import com.vaadin.ui.FormLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextArea; import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField; import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.Window; import com.vaadin.ui.Window;
import com.vaadin.ui.themes.ValoTheme; import com.vaadin.ui.themes.ValoTheme;
/** /**
* Add and Update Target. * Add and Update Target.
*
*
*
*/ */
@SpringComponent @SpringComponent
@VaadinSessionScope @VaadinSessionScope
@@ -73,48 +67,37 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
private TextField controllerIDTextField; private TextField controllerIDTextField;
private TextField nameTextField; private TextField nameTextField;
private TextArea descTextArea; private TextArea descTextArea;
private Label madatoryLabel;
private boolean editTarget = Boolean.FALSE; private boolean editTarget = Boolean.FALSE;
private String controllerId; private String controllerId;
private FormLayout formLayout; private FormLayout formLayout;
private CommonDialogWindow window; private CommonDialogWindow window;
private String oldTargetName;
private String oldTargetDesc;
/** /**
* Initialize the Add Update Window Component for Target. * Initialize the Add Update Window Component for Target.
*/ */
public void init() { public void init() {
/* create components */
createRequiredComponents(); createRequiredComponents();
/* display components in layout */
buildLayout(); buildLayout();
/* register all listeners related to the Window */
addListeners();
setCompositionRoot(formLayout); setCompositionRoot(formLayout);
} }
private void createRequiredComponents() { private void createRequiredComponents() {
/* Textfield for controller Id */ /* Textfield for controller Id */
controllerIDTextField = SPUIComponentProvider.getTextField( i18n.get("prompt.target.id"), "", ValoTheme.TEXTFIELD_TINY, true, null, controllerIDTextField = SPUIComponentProvider.getTextField(i18n.get("prompt.target.id"), "",
i18n.get("prompt.target.id"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH); ValoTheme.TEXTFIELD_TINY, true, null, i18n.get("prompt.target.id"), true,
SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
controllerIDTextField.setId(SPUIComponentIdProvider.TARGET_ADD_CONTROLLER_ID); controllerIDTextField.setId(SPUIComponentIdProvider.TARGET_ADD_CONTROLLER_ID);
/* Textfield for target name */ /* Textfield for target name */
nameTextField = SPUIComponentProvider.getTextField( i18n.get("textfield.name"), "", ValoTheme.TEXTFIELD_TINY, false, null, nameTextField = SPUIComponentProvider.getTextField(i18n.get("textfield.name"), "", ValoTheme.TEXTFIELD_TINY,
i18n.get("textfield.name"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH); false, null, i18n.get("textfield.name"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
nameTextField.setId(SPUIComponentIdProvider.TARGET_ADD_NAME); nameTextField.setId(SPUIComponentIdProvider.TARGET_ADD_NAME);
/* Textarea for target description */ /* Textarea for target description */
descTextArea = SPUIComponentProvider.getTextArea( i18n.get("textfield.description"), "text-area-style", ValoTheme.TEXTFIELD_TINY, false, null, descTextArea = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "text-area-style",
i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH); ValoTheme.TEXTFIELD_TINY, false, null, i18n.get("textfield.description"),
SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
descTextArea.setId(SPUIComponentIdProvider.TARGET_ADD_DESC); descTextArea.setId(SPUIComponentIdProvider.TARGET_ADD_DESC);
descTextArea.setNullRepresentation(HawkbitCommonUtil.SP_STRING_EMPTY); descTextArea.setNullRepresentation(HawkbitCommonUtil.SP_STRING_EMPTY);
/* Label for mandatory symbol */
madatoryLabel = new Label(i18n.get("label.mandatory.field"));
madatoryLabel.setStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR + " " + ValoTheme.LABEL_SMALL);
} }
private void buildLayout() { private void buildLayout() {
@@ -125,63 +108,13 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
*/ */
setSizeUndefined(); setSizeUndefined();
formLayout = new FormLayout(); formLayout = new FormLayout();
formLayout.addComponent(madatoryLabel);
formLayout.addComponent(controllerIDTextField); formLayout.addComponent(controllerIDTextField);
formLayout.addComponent(nameTextField); formLayout.addComponent(nameTextField);
formLayout.addComponent(descTextArea); formLayout.addComponent(descTextArea);
if (Boolean.TRUE.equals(editTarget)) {
madatoryLabel.setVisible(Boolean.FALSE);
}
controllerIDTextField.focus(); controllerIDTextField.focus();
} }
private void addListeners() {
addTargetNameChangeListner();
addTargetDescChangeListner();
}
private void addTargetNameChangeListner() {
nameTextField.addTextChangeListener(new TextChangeListener() {
/**
*
*/
private static final long serialVersionUID = 1761855781481115921L;
@Override
public void textChange(final TextChangeEvent event) {
if (event.getText().equals(oldTargetName) && descTextArea.getValue().equals(oldTargetDesc)) {
window.setSaveButtonEnabled(false);
} else {
window.setSaveButtonEnabled(true);
}
}
});
}
private void addTargetDescChangeListner() {
descTextArea.addTextChangeListener(new TextChangeListener() {
/**
*
*/
private static final long serialVersionUID = 5770734934988115068L;
@Override
public void textChange(final TextChangeEvent event) {
if (event.getText().equals(oldTargetDesc) && nameTextField.getValue().equals(oldTargetName)) {
window.setSaveButtonEnabled(false);
} else {
window.setSaveButtonEnabled(true);
}
}
});
}
/** /**
* Update the Target if modified. * Update the Target if modified.
*/ */
@@ -199,10 +132,6 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
uINotification.displaySuccess(i18n.get("message.update.success", new Object[] { latestTarget.getName() })); uINotification.displaySuccess(i18n.get("message.update.success", new Object[] { latestTarget.getName() }));
// publishing through event bus // publishing through event bus
eventBus.publish(this, new TargetTableEvent(BaseEntityEventType.UPDATED_ENTITY, latestTarget)); eventBus.publish(this, new TargetTableEvent(BaseEntityEventType.UPDATED_ENTITY, latestTarget));
/* close the window */
closeThisWindow();
/* update details in table */
} }
private void saveTargetListner() { private void saveTargetListner() {
@@ -213,13 +142,9 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
} }
} }
private void discardTargetListner() {
closeThisWindow();
}
private void addNewTarget() { private void addNewTarget() {
final String newControlllerId = HawkbitCommonUtil.trimAndNullIfEmpty(controllerIDTextField.getValue()); final String newControlllerId = HawkbitCommonUtil.trimAndNullIfEmpty(controllerIDTextField.getValue());
if (mandatoryCheck(newControlllerId) && duplicateCheck(newControlllerId)) { if (duplicateCheck(newControlllerId)) {
final String newName = HawkbitCommonUtil.trimAndNullIfEmpty(nameTextField.getValue()); final String newName = HawkbitCommonUtil.trimAndNullIfEmpty(nameTextField.getValue());
final String newDesc = HawkbitCommonUtil.trimAndNullIfEmpty(descTextArea.getValue()); final String newDesc = HawkbitCommonUtil.trimAndNullIfEmpty(descTextArea.getValue());
@@ -236,15 +161,20 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
/* display success msg */ /* display success msg */
uINotification.displaySuccess(i18n.get("message.save.success", new Object[] { newTarget.getName() })); uINotification.displaySuccess(i18n.get("message.save.success", new Object[] { newTarget.getName() }));
/* close the window */
closeThisWindow();
} }
} }
public Window getWindow() { public Window getWindow() {
eventBus.publish(this, DragEvent.HIDE_DROP_HINT); eventBus.publish(this, DragEvent.HIDE_DROP_HINT);
window = SPUIComponentProvider.getWindow(i18n.get("caption.add.new.target"), null, window = SPUIWindowDecorator.getWindow(i18n.get("caption.add.new.target"), null,
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> saveTargetListner(), event -> discardTargetListner(), null); SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> saveTargetListner(), null, null, formLayout, i18n);
return window;
}
public Window getWindow(final String entityId) {
populateValuesOfTarget(entityId);
getWindow();
window.addStyleName("target-update-window");
return window; return window;
} }
@@ -254,39 +184,23 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
public void resetComponents() { public void resetComponents() {
nameTextField.clear(); nameTextField.clear();
nameTextField.removeStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR); nameTextField.removeStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR);
controllerIDTextField.setEnabled(true); controllerIDTextField.setEnabled(Boolean.TRUE);
controllerIDTextField.setReadOnly(false);
controllerIDTextField.removeStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR); controllerIDTextField.removeStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR);
controllerIDTextField.clear(); controllerIDTextField.clear();
descTextArea.clear(); descTextArea.clear();
editTarget = Boolean.FALSE; editTarget = Boolean.FALSE;
} }
private void closeThisWindow() {
editTarget = Boolean.FALSE;
window.close();
UI.getCurrent().removeWindow(window);
}
private void setTargetValues(final Target target, final String name, final String description) { private void setTargetValues(final Target target, final String name, final String description) {
target.setName(name == null ? target.getControllerId() : name); target.setName(name == null ? target.getControllerId() : name);
target.setDescription(description); target.setDescription(description);
} }
private boolean mandatoryCheck(final String newControlllerId) {
if (newControlllerId == null) {
controllerIDTextField.addStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR);
uINotification.displayValidationError("Mandatory details are missing");
return false;
} else {
return true;
}
}
private boolean duplicateCheck(final String newControlllerId) { private boolean duplicateCheck(final String newControlllerId) {
final Target existingTarget = targetManagement.findTargetByControllerID(newControlllerId.trim()); final Target existingTarget = targetManagement.findTargetByControllerID(newControlllerId.trim());
if (existingTarget != null) { if (existingTarget != null) {
uINotification.displayValidationError(i18n.get("message.target.duplicate.check")); uINotification.displayValidationError(
i18n.get("message.target.duplicate.check", new Object[] { newControlllerId }));
return false; return false;
} else { } else {
return true; return true;
@@ -296,22 +210,21 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
/** /**
* @param controllerId * @param controllerId
*/ */
public void populateValuesOfTarget(final String controllerId) { private void populateValuesOfTarget(final String controllerId) {
resetComponents(); resetComponents();
this.controllerId = controllerId; this.controllerId = controllerId;
editTarget = Boolean.TRUE; editTarget = Boolean.TRUE;
final Target target = targetManagement.findTargetByControllerID(controllerId); final Target target = targetManagement.findTargetByControllerID(controllerId);
controllerIDTextField.setValue(target.getControllerId()); controllerIDTextField.setValue(target.getControllerId());
controllerIDTextField.setReadOnly(Boolean.TRUE); controllerIDTextField.setEnabled(Boolean.FALSE);
nameTextField.setValue(target.getName()); nameTextField.setValue(target.getName());
if (target.getDescription() != null) { if (target.getDescription() != null) {
descTextArea.setValue(target.getDescription()); descTextArea.setValue(target.getDescription());
} }
window.setSaveButtonEnabled(Boolean.FALSE); }
oldTargetDesc = descTextArea.getValue(); public FormLayout getFormLayout() {
oldTargetName = nameTextField.getValue(); return formLayout;
window.addStyleName("target-update-window");
} }
} }

View File

@@ -44,7 +44,7 @@ import com.google.common.base.Strings;
public class TargetBeanQuery extends AbstractBeanQuery<ProxyTarget> { public class TargetBeanQuery extends AbstractBeanQuery<ProxyTarget> {
private static final long serialVersionUID = -5645680058303167558L; private static final long serialVersionUID = -5645680058303167558L;
private Sort sort = new Sort(SPUIDefinitions.TARGET_TABLE_CREATE_AT_SORT_ORDER, "createdAt"); private Sort sort = new Sort(SPUIDefinitions.TARGET_TABLE_CREATE_AT_SORT_ORDER, "createdAt");
private Collection<TargetUpdateStatus> status = null; private transient Collection<TargetUpdateStatus> status = null;
private String[] targetTags = null; private String[] targetTags = null;
private Long distributionId = null; private Long distributionId = null;
private String searchText = null; private String searchText = null;

View File

@@ -106,8 +106,13 @@ public class TargetDetails extends AbstractTableDetailsLayout<Target> {
if (getSelectedBaseEntity() == null) { if (getSelectedBaseEntity() == null) {
return; return;
} }
targetAddUpdateWindowLayout.getWindow(getSelectedBaseEntity().getControllerId());
// targetAddUpdateWindowLayout.populateValuesOfTarget(getSelectedBaseEntity().getControllerId());
openWindow();
}
private void openWindow() {
final Window newDistWindow = targetAddUpdateWindowLayout.getWindow(); final Window newDistWindow = targetAddUpdateWindowLayout.getWindow();
targetAddUpdateWindowLayout.populateValuesOfTarget(getSelectedBaseEntity().getControllerId());
newDistWindow.setCaption(getI18n().get("caption.update.dist")); newDistWindow.setCaption(getI18n().get("caption.update.dist"));
UI.getCurrent().addWindow(newDistWindow); UI.getCurrent().addWindow(newDistWindow);
newDistWindow.setVisible(Boolean.TRUE); newDistWindow.setVisible(Boolean.TRUE);

View File

@@ -102,15 +102,13 @@ public class CreateUpdateTargetTagLayoutWindow extends AbstractCreateUpdateTagLa
@Override @Override
public void save(final ClickEvent event) { public void save(final ClickEvent event) {
if (mandatoryValuesPresent()) { final TargetTag existingTag = tagManagement.findTargetTag(tagName.getValue());
final TargetTag existingTag = tagManagement.findTargetTag(tagName.getValue()); if (optiongroup.getValue().equals(createTagStr)) {
if (optiongroup.getValue().equals(createTagStr)) { if (!checkIsDuplicate(existingTag)) {
if (!checkIsDuplicate(existingTag)) { createNewTag();
createNewTag();
}
} else {
updateExistingTag(existingTag);
} }
} else {
updateExistingTag(existingTag);
} }
} }
@@ -131,7 +129,6 @@ public class CreateUpdateTargetTagLayoutWindow extends AbstractCreateUpdateTagLa
} }
newTargetTag = tagManagement.createTargetTag(newTargetTag); newTargetTag = tagManagement.createTargetTag(newTargetTag);
displaySuccess(newTargetTag.getName()); displaySuccess(newTargetTag.getName());
closeWindow();
} else { } else {
displayValidationError(i18n.get(MESSAGE_ERROR_MISSING_TAGNAME)); displayValidationError(i18n.get(MESSAGE_ERROR_MISSING_TAGNAME));
} }
@@ -150,4 +147,9 @@ public class CreateUpdateTargetTagLayoutWindow extends AbstractCreateUpdateTagLa
setOptionGroupDefaultValue(permChecker.hasCreateTargetPermission(), permChecker.hasUpdateTargetPermission()); setOptionGroupDefaultValue(permChecker.hasCreateTargetPermission(), permChecker.hasUpdateTargetPermission());
} }
@Override
protected String getWindowCaption() {
return i18n.get("caption.add.tag");
}
} }

View File

@@ -31,6 +31,7 @@ import org.eclipse.hawkbit.ui.UiProperties;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow; import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.DistributionSetIdName; import org.eclipse.hawkbit.ui.common.DistributionSetIdName;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIWindowDecorator;
import org.eclipse.hawkbit.ui.filtermanagement.TargetFilterBeanQuery; import org.eclipse.hawkbit.ui.filtermanagement.TargetFilterBeanQuery;
import org.eclipse.hawkbit.ui.management.footer.ActionTypeOptionGroupLayout; import org.eclipse.hawkbit.ui.management.footer.ActionTypeOptionGroupLayout;
import org.eclipse.hawkbit.ui.management.footer.ActionTypeOptionGroupLayout.ActionTypeOption; import org.eclipse.hawkbit.ui.management.footer.ActionTypeOptionGroupLayout.ActionTypeOption;
@@ -56,8 +57,10 @@ import com.vaadin.data.Container;
import com.vaadin.data.Item; import com.vaadin.data.Item;
import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Validator; import com.vaadin.data.Validator;
import com.vaadin.data.util.converter.StringToIntegerConverter;
import com.vaadin.data.validator.IntegerRangeValidator; import com.vaadin.data.validator.IntegerRangeValidator;
import com.vaadin.data.validator.RegexpValidator; import com.vaadin.data.validator.NullValidator;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope; import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.ComboBox; import com.vaadin.ui.ComboBox;
@@ -66,13 +69,10 @@ import com.vaadin.ui.Label;
import com.vaadin.ui.OptionGroup; import com.vaadin.ui.OptionGroup;
import com.vaadin.ui.TextArea; import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField; import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.themes.ValoTheme; import com.vaadin.ui.themes.ValoTheme;
/** /**
*
* Rollout add or update popup layout. * Rollout add or update popup layout.
*
*/ */
@SpringComponent @SpringComponent
@ViewScope @ViewScope
@@ -86,8 +86,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
private static final String MESSAGE_ENTER_NUMBER = "message.enter.number"; private static final String MESSAGE_ENTER_NUMBER = "message.enter.number";
private static final String NUMBER_REGEXP = "[-]?[0-9]*\\.?,?[0-9]+";
@Autowired @Autowired
private ActionTypeOptionGroupLayout actionTypeOptionGroupLayout; private ActionTypeOptionGroupLayout actionTypeOptionGroupLayout;
@@ -115,8 +113,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
@Autowired @Autowired
private transient EventBus.SessionEventBus eventBus; private transient EventBus.SessionEventBus eventBus;
private Label mandatoryLabel;
private TextField rolloutName; private TextField rolloutName;
private ComboBox distributionSet; private ComboBox distributionSet;
@@ -135,7 +131,7 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
private OptionGroup errorThresholdOptionGroup; private OptionGroup errorThresholdOptionGroup;
private CommonDialogWindow addUpdateRolloutWindow; private CommonDialogWindow window;
private Boolean editRolloutEnabled; private Boolean editRolloutEnabled;
@@ -147,22 +143,28 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
private TextArea targetFilterQuery; private TextArea targetFilterQuery;
private final NullValidator nullValidator = new NullValidator(null, false);
/** /**
* Create components and layout. * Create components and layout.
*/ */
public void init() { public void init() {
setSizeUndefined(); setSizeUndefined();
createRequiredComponents(); createRequiredComponents();
buildLayout(); buildLayout();
} }
public CommonDialogWindow getWindow() { public CommonDialogWindow getWindow(final Long rolloutId) {
window = getWindow();
populateData(rolloutId);
return window;
}
addUpdateRolloutWindow = SPUIComponentProvider.getWindow(i18n.get("caption.configure.rollout"), null, public CommonDialogWindow getWindow() {
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> onRolloutSave(), event -> onDiscard(), resetComponents();
uiProperties.getLinks().getDocumentation().getRolloutView()); return SPUIWindowDecorator.getWindow(i18n.get("caption.configure.rollout"), null,
return addUpdateRolloutWindow; SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> onRolloutSave(), null,
uiProperties.getLinks().getDocumentation().getRolloutView(), this, i18n);
} }
/** /**
@@ -179,10 +181,8 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
setDefaultSaveStartGroupOption(); setDefaultSaveStartGroupOption();
totalTargetsLabel.setVisible(false); totalTargetsLabel.setVisible(false);
groupSizeLabel.setVisible(false); groupSizeLabel.setVisible(false);
removeComponent(targetFilterQuery); removeComponent(1, 2);
if (getComponent(1, 3) == null) { addComponent(targetFilterQueryCombo, 1, 2);
addComponent(targetFilterQueryCombo, 1, 3);
}
actionTypeOptionGroupLayout.selectDefaultOption(); actionTypeOptionGroupLayout.selectDefaultOption();
totalTargetsCount = 0L; totalTargetsCount = 0L;
rolloutForEdit = null; rolloutForEdit = null;
@@ -206,37 +206,60 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
setSizeUndefined(); setSizeUndefined();
setRows(9); setRows(9);
setColumns(3); setColumns(3);
setStyleName("marginTop");
addComponent(mandatoryLabel, 1, 0, 2, 0); addComponent(getMandatoryLabel("textfield.name"), 0, 0);
addComponent(getLabel("textfield.name"), 0, 1); addComponent(rolloutName, 1, 0);
addComponent(rolloutName, 1, 1); rolloutName.addValidator(nullValidator);
addComponent(getLabel("prompt.distribution.set"), 0, 2);
addComponent(distributionSet, 1, 2); addComponent(getMandatoryLabel("prompt.distribution.set"), 0, 1);
addComponent(getLabel("prompt.target.filter"), 0, 3); addComponent(distributionSet, 1, 1);
addComponent(targetFilterQueryCombo, 1, 3); distributionSet.addValidator(nullValidator);
addComponent(totalTargetsLabel, 2, 3);
addComponent(getLabel("prompt.number.of.groups"), 0, 4); addComponent(getMandatoryLabel("prompt.target.filter"), 0, 2);
addComponent(noOfGroups, 1, 4); addComponent(targetFilterQueryCombo, 1, 2);
addComponent(groupSizeLabel, 2, 4); targetFilterQueryCombo.addValidator(nullValidator);
addComponent(getLabel("prompt.tigger.threshold"), 0, 5); targetFilterQuery.removeValidator(nullValidator);
addComponent(triggerThreshold, 1, 5);
addComponent(getPercentHintLabel(), 2, 5); addComponent(totalTargetsLabel, 2, 2);
addComponent(getLabel("prompt.error.threshold"), 0, 6);
addComponent(errorThreshold, 1, 6); addComponent(getMandatoryLabel("prompt.number.of.groups"), 0, 3);
addComponent(errorThresholdOptionGroup, 2, 6); addComponent(noOfGroups, 1, 3);
addComponent(getLabel("textfield.description"), 0, 7); noOfGroups.addValidator(nullValidator);
addComponent(description, 1, 7, 2, 7);
addComponent(actionTypeOptionGroupLayout, 0, 8, 2, 8); addComponent(groupSizeLabel, 2, 3);
addComponent(getMandatoryLabel("prompt.tigger.threshold"), 0, 4);
addComponent(triggerThreshold, 1, 4);
triggerThreshold.addValidator(nullValidator);
addComponent(getPercentHintLabel(), 2, 4);
addComponent(getMandatoryLabel("prompt.error.threshold"), 0, 5);
addComponent(errorThreshold, 1, 5);
errorThreshold.addValidator(nullValidator);
addComponent(errorThresholdOptionGroup, 2, 5);
addComponent(getLabel("textfield.description"), 0, 6);
addComponent(description, 1, 6, 2, 6);
addComponent(actionTypeOptionGroupLayout, 0, 7, 2, 7);
rolloutName.focus(); rolloutName.focus();
} }
private Label getMandatoryLabel(final String key) {
final Label mandatoryLabel = getLabel(i18n.get(key));
mandatoryLabel.setContentMode(ContentMode.HTML);
mandatoryLabel.setValue(mandatoryLabel.getValue().concat(" <span style='color:#ed473b'>*</span>"));
return mandatoryLabel;
}
private Label getLabel(final String key) { private Label getLabel(final String key) {
return SPUIComponentProvider.getLabel(i18n.get(key), SPUILabelDefinitions.SP_LABEL_SIMPLE); return SPUIComponentProvider.getLabel(i18n.get(key), SPUILabelDefinitions.SP_LABEL_SIMPLE);
} }
private TextField getTextfield(final String key) { private TextField getTextfield(final String key) {
return SPUIComponentProvider.getTextField(null, "", ValoTheme.TEXTFIELD_TINY, true, null, i18n.get(key), true, return SPUIComponentProvider.getTextField(null, "", ValoTheme.TEXTFIELD_TINY, false, null, i18n.get(key), true,
SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH); SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
} }
@@ -248,7 +271,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
} }
private void createRequiredComponents() { private void createRequiredComponents() {
mandatoryLabel = createMandatoryLabel();
rolloutName = createRolloutNameField(); rolloutName = createRolloutNameField();
distributionSet = createDistributionSetCombo(); distributionSet = createDistributionSetCombo();
populateDistributionSet(); populateDistributionSet();
@@ -258,7 +280,7 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
noOfGroups = createNoOfGroupsField(); noOfGroups = createNoOfGroupsField();
groupSizeLabel = createGroupSizeLabel(); groupSizeLabel = createGroupSizeLabel();
triggerThreshold = createTriggerThresold(); triggerThreshold = createTriggerThreshold();
errorThreshold = createErrorThreshold(); errorThreshold = createErrorThreshold();
description = createDescription(); description = createDescription();
errorThresholdOptionGroup = createErrorThresholdOptionGroup(); errorThresholdOptionGroup = createErrorThresholdOptionGroup();
@@ -307,11 +329,11 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
errorThresoldOptions.addStyleName(ValoTheme.OPTIONGROUP_HORIZONTAL); errorThresoldOptions.addStyleName(ValoTheme.OPTIONGROUP_HORIZONTAL);
errorThresoldOptions.addStyleName(SPUIStyleDefinitions.ROLLOUT_OPTION_GROUP); errorThresoldOptions.addStyleName(SPUIStyleDefinitions.ROLLOUT_OPTION_GROUP);
errorThresoldOptions.setSizeUndefined(); errorThresoldOptions.setSizeUndefined();
errorThresoldOptions.addValueChangeListener(this::onErrorThresoldOptionChange); errorThresoldOptions.addValueChangeListener(this::listenerOnErrorThresoldOptionChange);
return errorThresoldOptions; return errorThresoldOptions;
} }
private void onErrorThresoldOptionChange(final ValueChangeEvent event) { private void listenerOnErrorThresoldOptionChange(final ValueChangeEvent event) {
errorThreshold.clear(); errorThreshold.clear();
errorThreshold.removeAllValidators(); errorThreshold.removeAllValidators();
if (event.getProperty().getValue().equals(ERRORTHRESOLDOPTIONS.COUNT.getValue())) { if (event.getProperty().getValue().equals(ERRORTHRESOLDOPTIONS.COUNT.getValue())) {
@@ -324,17 +346,17 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
private ComboBox createTargetFilterQueryCombo() { private ComboBox createTargetFilterQueryCombo() {
final ComboBox targetFilter = SPUIComponentProvider.getComboBox(null, "", "", null, ValoTheme.COMBOBOX_SMALL, final ComboBox targetFilter = SPUIComponentProvider.getComboBox(null, "", "", null, ValoTheme.COMBOBOX_SMALL,
true, "", i18n.get("prompt.target.filter")); false, "", i18n.get("prompt.target.filter"));
targetFilter.setImmediate(true); targetFilter.setImmediate(true);
targetFilter.setPageLength(7); targetFilter.setPageLength(7);
targetFilter.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME); targetFilter.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME);
targetFilter.setId(SPUIComponentIdProvider.ROLLOUT_TARGET_FILTER_COMBO_ID); targetFilter.setId(SPUIComponentIdProvider.ROLLOUT_TARGET_FILTER_COMBO_ID);
targetFilter.setSizeUndefined(); targetFilter.setSizeUndefined();
targetFilter.addValueChangeListener(event -> onTargetFilterChange()); targetFilter.addValueChangeListener(this::onTargetFilterChange);
return targetFilter; return targetFilter;
} }
private void onTargetFilterChange() { private void onTargetFilterChange(final ValueChangeEvent event) {
final String filterQueryString = getTargetFilterQuery(); final String filterQueryString = getTargetFilterQuery();
if (!Strings.isNullOrEmpty(filterQueryString)) { if (!Strings.isNullOrEmpty(filterQueryString)) {
totalTargetsCount = targetManagement.countTargetByTargetFilterQuery(filterQueryString); totalTargetsCount = targetManagement.countTargetByTargetFilterQuery(filterQueryString);
@@ -344,7 +366,7 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
totalTargetsCount = 0L; totalTargetsCount = 0L;
totalTargetsLabel.setVisible(false); totalTargetsLabel.setVisible(false);
} }
onGroupNumberChange(); onGroupNumberChange(event);
} }
private String getTotalTargetMessage() { private String getTotalTargetMessage() {
@@ -368,10 +390,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
targetFilterQF); targetFilterQF);
} }
private void onDiscard() {
closeThisWindow();
}
private void onRolloutSave() { private void onRolloutSave() {
if (editRolloutEnabled) { if (editRolloutEnabled) {
editRollout(); editRollout();
@@ -381,7 +399,7 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
} }
private void editRollout() { private void editRollout() {
if (mandatoryCheckForEdit() && validateFields() && duplicateCheckForEdit() && null != rolloutForEdit) { if (duplicateCheckForEdit() && rolloutForEdit != null) {
rolloutForEdit.setName(rolloutName.getValue()); rolloutForEdit.setName(rolloutName.getValue());
rolloutForEdit.setDescription(description.getValue()); rolloutForEdit.setDescription(description.getValue());
final DistributionSetIdName distributionSetIdName = (DistributionSetIdName) distributionSet.getValue(); final DistributionSetIdName distributionSetIdName = (DistributionSetIdName) distributionSet.getValue();
@@ -399,7 +417,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
final Rollout updatedRollout = rolloutManagement.updateRollout(rolloutForEdit); final Rollout updatedRollout = rolloutManagement.updateRollout(rolloutForEdit);
uiNotification uiNotification
.displaySuccess(i18n.get("message.update.success", new Object[] { updatedRollout.getName() })); .displaySuccess(i18n.get("message.update.success", new Object[] { updatedRollout.getName() }));
closeThisWindow();
eventBus.publish(this, RolloutEvent.UPDATE_ROLLOUT); eventBus.publish(this, RolloutEvent.UPDATE_ROLLOUT);
} }
} }
@@ -427,11 +444,10 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
} }
private void createRollout() { private void createRollout() {
if (mandatoryCheck() && validateFields() && duplicateCheck()) { if (duplicateCheck()) {
final Rollout rolloutToCreate = saveRollout(); final Rollout rolloutToCreate = saveRollout();
uiNotification.displaySuccess(i18n.get("message.save.success", new Object[] { rolloutToCreate.getName() })); uiNotification.displaySuccess(i18n.get("message.save.success", new Object[] { rolloutToCreate.getName() }));
eventBus.publish(this, RolloutEvent.CREATE_ROLLOUT); eventBus.publish(this, RolloutEvent.CREATE_ROLLOUT);
closeThisWindow();
} }
} }
@@ -488,48 +504,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
return true; return true;
} }
private void closeThisWindow() {
addUpdateRolloutWindow.close();
UI.getCurrent().removeWindow(addUpdateRolloutWindow);
}
private boolean mandatoryCheck() {
final DistributionSetIdName ds = getDistributionSetSelected();
final String targetFilter = (String) targetFilterQueryCombo.getValue();
final String triggerThresoldValue = triggerThreshold.getValue();
final String errorThresoldValue = errorThreshold.getValue();
if (hasNoNameOrTargetFilter(targetFilter) || ds == null
|| HawkbitCommonUtil.trimAndNullIfEmpty(noOfGroups.getValue()) == null
|| isThresholdValueMissing(triggerThresoldValue, errorThresoldValue)) {
uiNotification.displayValidationError(i18n.get("message.mandatory.check"));
return false;
}
return true;
}
private boolean mandatoryCheckForEdit() {
final DistributionSetIdName ds = getDistributionSetSelected();
final String targetFilter = targetFilterQuery.getValue();
final String triggerThresoldValue = triggerThreshold.getValue();
final String errorThresoldValue = errorThreshold.getValue();
if (hasNoNameOrTargetFilter(targetFilter) || ds == null
|| HawkbitCommonUtil.trimAndNullIfEmpty(noOfGroups.getValue()) == null
|| isThresholdValueMissing(triggerThresoldValue, errorThresoldValue)) {
uiNotification.displayValidationError(i18n.get("message.mandatory.check"));
return false;
}
return true;
}
private boolean hasNoNameOrTargetFilter(final String targetFilter) {
return getRolloutName() == null || targetFilter == null;
}
private boolean isThresholdValueMissing(final String triggerThresoldValue, final String errorThresoldValue) {
return HawkbitCommonUtil.trimAndNullIfEmpty(triggerThresoldValue) == null
|| HawkbitCommonUtil.trimAndNullIfEmpty(errorThresoldValue) == null;
}
private boolean duplicateCheck() { private boolean duplicateCheck() {
if (rolloutManagement.findRolloutByName(getRolloutName()) != null) { if (rolloutManagement.findRolloutByName(getRolloutName()) != null) {
uiNotification.displayValidationError( uiNotification.displayValidationError(
@@ -555,17 +529,23 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
private TextField createErrorThreshold() { private TextField createErrorThreshold() {
final TextField errorField = getTextfield("prompt.error.threshold"); final TextField errorField = getTextfield("prompt.error.threshold");
errorField.setNullRepresentation("");
errorField.addValidator(new ThresholdFieldValidator()); errorField.addValidator(new ThresholdFieldValidator());
errorField.setConverter(new StringToIntegerConverter());
errorField.setConversionError(i18n.get(MESSAGE_ENTER_NUMBER));
errorField.setId(SPUIComponentIdProvider.ROLLOUT_ERROR_THRESOLD_ID); errorField.setId(SPUIComponentIdProvider.ROLLOUT_ERROR_THRESOLD_ID);
errorField.setMaxLength(7); errorField.setMaxLength(7);
errorField.setSizeUndefined(); errorField.setSizeUndefined();
return errorField; return errorField;
} }
private TextField createTriggerThresold() { private TextField createTriggerThreshold() {
final TextField thresholdField = getTextfield("prompt.tigger.threshold"); final TextField thresholdField = getTextfield("prompt.tigger.threshold");
thresholdField.setId(SPUIComponentIdProvider.ROLLOUT_TRIGGER_THRESOLD_ID); thresholdField.setId(SPUIComponentIdProvider.ROLLOUT_TRIGGER_THRESOLD_ID);
thresholdField.setNullRepresentation("");
thresholdField.addValidator(new ThresholdFieldValidator()); thresholdField.addValidator(new ThresholdFieldValidator());
thresholdField.setConverter(new StringToIntegerConverter());
thresholdField.setConversionError(i18n.get(MESSAGE_ENTER_NUMBER));
thresholdField.setSizeUndefined(); thresholdField.setSizeUndefined();
thresholdField.setMaxLength(3); thresholdField.setMaxLength(3);
return thresholdField; return thresholdField;
@@ -577,12 +557,15 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
noOfGroupsField.addValidator(new GroupNumberValidator()); noOfGroupsField.addValidator(new GroupNumberValidator());
noOfGroupsField.setSizeUndefined(); noOfGroupsField.setSizeUndefined();
noOfGroupsField.setMaxLength(3); noOfGroupsField.setMaxLength(3);
noOfGroupsField.addValueChangeListener(evevt -> onGroupNumberChange()); noOfGroupsField.setConverter(new StringToIntegerConverter());
noOfGroupsField.setConversionError(i18n.get(MESSAGE_ENTER_NUMBER));
noOfGroupsField.addValueChangeListener(this::onGroupNumberChange);
noOfGroupsField.setNullRepresentation("");
return noOfGroupsField; return noOfGroupsField;
} }
private void onGroupNumberChange() { private void onGroupNumberChange(final ValueChangeEvent event) {
if (noOfGroups.isValid() && !Strings.isNullOrEmpty(noOfGroups.getValue())) { if (event.getProperty().getValue() != null && noOfGroups.isValid()) {
groupSizeLabel.setValue(getTargetPerGroupMessage(String.valueOf(getGroupSize()))); groupSizeLabel.setValue(getTargetPerGroupMessage(String.valueOf(getGroupSize())));
groupSizeLabel.setVisible(true); groupSizeLabel.setVisible(true);
} else { } else {
@@ -591,8 +574,8 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
} }
private ComboBox createDistributionSetCombo() { private ComboBox createDistributionSetCombo() {
final ComboBox dsSet = SPUIComponentProvider.getComboBox(null, "", "", null, ValoTheme.COMBOBOX_SMALL, true, "", final ComboBox dsSet = SPUIComponentProvider.getComboBox(null, "", "", null, ValoTheme.COMBOBOX_SMALL, false,
i18n.get("prompt.distribution.set")); "", i18n.get("prompt.distribution.set"));
dsSet.setImmediate(true); dsSet.setImmediate(true);
dsSet.setPageLength(7); dsSet.setPageLength(7);
dsSet.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME); dsSet.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME);
@@ -612,7 +595,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
return new LazyQueryContainer( return new LazyQueryContainer(
new LazyQueryDefinition(true, SPUIDefinitions.PAGE_SIZE, SPUILabelDefinitions.VAR_DIST_ID_NAME), new LazyQueryDefinition(true, SPUIDefinitions.PAGE_SIZE, SPUILabelDefinitions.VAR_DIST_ID_NAME),
distributionQF); distributionQF);
} }
private TextField createRolloutNameField() { private TextField createRolloutNameField() {
@@ -622,44 +604,42 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
return rolloutNameField; return rolloutNameField;
} }
private Label createMandatoryLabel() {
final Label madatoryLbl = new Label(i18n.get("label.mandatory.field"));
madatoryLbl.addStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR + " " + ValoTheme.LABEL_SMALL);
return madatoryLbl;
}
private String getRolloutName() { private String getRolloutName() {
return HawkbitCommonUtil.trimAndNullIfEmpty(rolloutName.getValue()); return HawkbitCommonUtil.trimAndNullIfEmpty(rolloutName.getValue());
} }
private DistributionSetIdName getDistributionSetSelected() {
return (DistributionSetIdName) distributionSet.getValue();
}
class ErrorThresoldOptionValidator implements Validator { class ErrorThresoldOptionValidator implements Validator {
private static final long serialVersionUID = 9049939751976326550L; private static final long serialVersionUID = 9049939751976326550L;
@Override @Override
public void validate(final Object value) { public void validate(final Object value) {
try { try {
if (HawkbitCommonUtil.trimAndNullIfEmpty(noOfGroups.getValue()) == null if (isNoOfGroupsOrTargetFilterEmpty()) {
|| HawkbitCommonUtil.trimAndNullIfEmpty((String) targetFilterQueryCombo.getValue()) == null) {
uiNotification uiNotification
.displayValidationError(i18n.get("message.rollout.noofgroups.or.targetfilter.missing")); .displayValidationError(i18n.get("message.rollout.noofgroups.or.targetfilter.missing"));
} else { } else {
new RegexpValidator(NUMBER_REGEXP, i18n.get(MESSAGE_ENTER_NUMBER)).validate(value); if (value != null) {
final int groupSize = getGroupSize(); final int groupSize = getGroupSize();
new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, groupSize), 0, groupSize) new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, groupSize), 0,
.validate(Integer.valueOf(value.toString())); groupSize).validate(Integer.valueOf(value.toString()));
}
} }
} }
// suppress the need of preserve original exception, will blow // suppress the need of preserve original exception, will blow
// up the // up the
// log and not necessary here // log and not necessary here
catch (@SuppressWarnings("squid:S1166") final InvalidValueException ex) { catch (final InvalidValueException ex) {
LOG.error(ex.getMessage()); // we have to throw the exception here, otherwise the UI won't
// show the vaadin validation error!
throw ex;
} }
} }
private boolean isNoOfGroupsOrTargetFilterEmpty() {
return HawkbitCommonUtil.trimAndNullIfEmpty(noOfGroups.getValue()) == null
|| (HawkbitCommonUtil.trimAndNullIfEmpty((String) targetFilterQueryCombo.getValue()) == null
&& targetFilterQuery.getValue() == null);
}
} }
private int getGroupSize() { private int getGroupSize() {
@@ -672,15 +652,18 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
@Override @Override
public void validate(final Object value) { public void validate(final Object value) {
try { try {
new RegexpValidator(NUMBER_REGEXP, i18n.get(MESSAGE_ENTER_NUMBER)).validate(value); if (value != null) {
new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, 100), 0, 100) new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, 100), 0, 100)
.validate(Integer.valueOf(value.toString())); .validate(Integer.valueOf(value.toString()));
}
} }
// suppress the need of preserve original exception, will blow // suppress the need of preserve original exception, will blow
// up the // up the
// log and not necessary here // log and not necessary here
catch (@SuppressWarnings("squid:S1166") final InvalidValueException ex) { catch (final InvalidValueException ex) {
LOG.error(ex.getMessage()); // we have to throw the exception here, otherwise the UI won't
// show the vaadin validation error!
throw ex;
} }
} }
} }
@@ -691,15 +674,18 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
@Override @Override
public void validate(final Object value) { public void validate(final Object value) {
try { try {
new RegexpValidator(NUMBER_REGEXP, i18n.get(MESSAGE_ENTER_NUMBER)).validate(value); if (value != null) {
new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, 500), 0, 500) new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, 500), 0, 500)
.validate(Integer.valueOf(value.toString())); .validate(Integer.valueOf(value.toString()));
}
} }
// suppress the need of preserve original exception, will blow // suppress the need of preserve original exception, will blow
// up the // up the
// log and not necessary here // log and not necessary here
catch (@SuppressWarnings("squid:S1166") final InvalidValueException ex) { catch (final InvalidValueException ex) {
LOG.error(ex.getMessage()); // we have to throw the exception here, otherwise the UI won't
// show the vaadin validation error!
throw ex;
} }
} }
} }
@@ -711,15 +697,18 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
* @param rolloutId * @param rolloutId
* rollout id * rollout id
*/ */
public void populateData(final Long rolloutId) { private void populateData(final Long rolloutId) {
resetComponents(); if (rolloutId == null) {
return;
}
editRolloutEnabled = Boolean.TRUE; editRolloutEnabled = Boolean.TRUE;
rolloutForEdit = rolloutManagement.findRolloutById(rolloutId); rolloutForEdit = rolloutManagement.findRolloutById(rolloutId);
rolloutName.setValue(rolloutForEdit.getName()); rolloutName.setValue(rolloutForEdit.getName());
description.setValue(rolloutForEdit.getDescription()); description.setValue(rolloutForEdit.getDescription());
distributionSet.setValue(DistributionSetIdName.generate(rolloutForEdit.getDistributionSet())); distributionSet.setValue(DistributionSetIdName.generate(rolloutForEdit.getDistributionSet()));
final List<RolloutGroup> rolloutGroups = rolloutForEdit.getRolloutGroups(); final List<RolloutGroup> rolloutGroups = rolloutForEdit.getRolloutGroups();
setThresoldValues(rolloutGroups); setThresholdValues(rolloutGroups);
setActionType(rolloutForEdit); setActionType(rolloutForEdit);
if (rolloutForEdit.getStatus() != RolloutStatus.READY) { if (rolloutForEdit.getStatus() != RolloutStatus.READY) {
disableRequiredFieldsOnEdit(); disableRequiredFieldsOnEdit();
@@ -727,12 +716,16 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
noOfGroups.setEnabled(false); noOfGroups.setEnabled(false);
targetFilterQuery.setValue(rolloutForEdit.getTargetFilterQuery()); targetFilterQuery.setValue(rolloutForEdit.getTargetFilterQuery());
removeComponent(targetFilterQueryCombo); removeComponent(1, 2);
addComponent(targetFilterQuery, 1, 3); targetFilterQueryCombo.removeValidator(nullValidator);
addComponent(targetFilterQuery, 1, 2);
targetFilterQuery.addValidator(nullValidator);
totalTargetsCount = targetManagement.countTargetByTargetFilterQuery(rolloutForEdit.getTargetFilterQuery()); totalTargetsCount = targetManagement.countTargetByTargetFilterQuery(rolloutForEdit.getTargetFilterQuery());
totalTargetsLabel.setValue(getTotalTargetMessage()); totalTargetsLabel.setValue(getTotalTargetMessage());
totalTargetsLabel.setVisible(true); totalTargetsLabel.setVisible(true);
window.setOrginaleValues();
} }
private void disableRequiredFieldsOnEdit() { private void disableRequiredFieldsOnEdit() {
@@ -771,8 +764,8 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
/** /**
* @param rolloutGroups * @param rolloutGroups
*/ */
private void setThresoldValues(final List<RolloutGroup> rolloutGroups) { private void setThresholdValues(final List<RolloutGroup> rolloutGroups) {
if (null != rolloutGroups && !rolloutGroups.isEmpty()) { if (rolloutGroups != null && !rolloutGroups.isEmpty()) {
errorThreshold.setValue(rolloutGroups.get(0).getErrorConditionExp()); errorThreshold.setValue(rolloutGroups.get(0).getErrorConditionExp());
triggerThreshold.setValue(rolloutGroups.get(0).getSuccessConditionExp()); triggerThreshold.setValue(rolloutGroups.get(0).getSuccessConditionExp());
noOfGroups.setValue(String.valueOf(rolloutGroups.size())); noOfGroups.setValue(String.valueOf(rolloutGroups.size()));
@@ -798,7 +791,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
public String getValue() { public String getValue() {
return value; return value;
} }
} }
enum ERRORTHRESOLDOPTIONS { enum ERRORTHRESOLDOPTIONS {
@@ -816,6 +808,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
public String getValue() { public String getValue() {
return value; return value;
} }
} }
} }

View File

@@ -28,6 +28,7 @@ import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus; import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.grid.AbstractGrid; import org.eclipse.hawkbit.ui.common.grid.AbstractGrid;
import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData; import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData;
import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlButtonRenderer; import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlButtonRenderer;
@@ -62,14 +63,11 @@ import com.vaadin.server.FontAwesome;
import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope; import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.UI; import com.vaadin.ui.UI;
import com.vaadin.ui.Window;
import com.vaadin.ui.renderers.ClickableRenderer.RendererClickEvent; import com.vaadin.ui.renderers.ClickableRenderer.RendererClickEvent;
import com.vaadin.ui.renderers.HtmlRenderer; import com.vaadin.ui.renderers.HtmlRenderer;
/** /**
*
* Rollout list grid component. * Rollout list grid component.
*
*/ */
@SpringComponent @SpringComponent
@ViewScope @ViewScope
@@ -145,6 +143,7 @@ public class RolloutListGrid extends AbstractGrid {
final LazyQueryContainer rolloutContainer = (LazyQueryContainer) getContainerDataSource(); final LazyQueryContainer rolloutContainer = (LazyQueryContainer) getContainerDataSource();
final Item item = rolloutContainer.getItem(rolloutChangeEvent.getRolloutId()); final Item item = rolloutContainer.getItem(rolloutChangeEvent.getRolloutId());
if (item == null) { if (item == null) {
refreshGrid();
return; return;
} }
item.getItemProperty(SPUILabelDefinitions.VAR_STATUS).setValue(rollout.getStatus()); item.getItemProperty(SPUILabelDefinitions.VAR_STATUS).setValue(rollout.getStatus());
@@ -159,7 +158,6 @@ public class RolloutListGrid extends AbstractGrid {
} }
item.getItemProperty(ROLLOUT_RENDERER_DATA) item.getItemProperty(ROLLOUT_RENDERER_DATA)
.setValue(new RolloutRendererData(rollout.getName(), rollout.getStatus().toString())); .setValue(new RolloutRendererData(rollout.getName(), rollout.getStatus().toString()));
} }
@Override @Override
@@ -200,7 +198,6 @@ public class RolloutListGrid extends AbstractGrid {
rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.ACTION, String.class, rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.ACTION, String.class,
FontAwesome.CIRCLE_O.getHtml(), false, false); FontAwesome.CIRCLE_O.getHtml(), false, false);
} }
@Override @Override
@@ -292,7 +289,6 @@ public class RolloutListGrid extends AbstractGrid {
for (final Object propertyId : columnsToBeHidden) { for (final Object propertyId : columnsToBeHidden) {
getColumn(propertyId).setHidden(true); getColumn(propertyId).setHidden(true);
} }
} }
@Override @Override
@@ -315,7 +311,6 @@ public class RolloutListGrid extends AbstractGrid {
final RolloutRenderer customObjectRenderer = new RolloutRenderer(RolloutRendererData.class); final RolloutRenderer customObjectRenderer = new RolloutRenderer(RolloutRendererData.class);
customObjectRenderer.addClickListener(this::onClickOfRolloutName); customObjectRenderer.addClickListener(this::onClickOfRolloutName);
getColumn(ROLLOUT_RENDERER_DATA).setRenderer(customObjectRenderer); getColumn(ROLLOUT_RENDERER_DATA).setRenderer(customObjectRenderer);
} }
private void createRolloutStatusToFontMap() { private void createRolloutStatusToFontMap() {
@@ -437,8 +432,7 @@ public class RolloutListGrid extends AbstractGrid {
} }
private void onUpdate(final ContextMenuData contextMenuData) { private void onUpdate(final ContextMenuData contextMenuData) {
addUpdateRolloutWindow.populateData(contextMenuData.getRolloutId()); final CommonDialogWindow addTargetWindow = addUpdateRolloutWindow.getWindow(contextMenuData.getRolloutId());
final Window addTargetWindow = addUpdateRolloutWindow.getWindow();
addTargetWindow.setCaption(i18n.get("caption.update.rollout")); addTargetWindow.setCaption(i18n.get("caption.update.rollout"));
UI.getCurrent().addWindow(addTargetWindow); UI.getCurrent().addWindow(addTargetWindow);
addTargetWindow.setVisible(Boolean.TRUE); addTargetWindow.setVisible(Boolean.TRUE);
@@ -684,7 +678,6 @@ public class RolloutListGrid extends AbstractGrid {
public Class<String> getPresentationType() { public Class<String> getPresentationType() {
return String.class; return String.class;
} }
} }
} }

View File

@@ -91,7 +91,6 @@ public class RolloutListHeader extends AbstractGridHeader {
@Override @Override
protected void addNewItem(final ClickEvent event) { protected void addNewItem(final ClickEvent event) {
addUpdateRolloutWindow.resetComponents();
final Window addTargetWindow = addUpdateRolloutWindow.getWindow(); final Window addTargetWindow = addUpdateRolloutWindow.getWindow();
UI.getCurrent().addWindow(addTargetWindow); UI.getCurrent().addWindow(addTargetWindow);
addTargetWindow.setVisible(Boolean.TRUE); addTargetWindow.setVisible(Boolean.TRUE);

View File

@@ -176,6 +176,10 @@ public final class SPUIComponentIdProvider {
* ID - Dist jvm combo. * ID - Dist jvm combo.
*/ */
public static final String DIST_MODULE_COMBO = "dist.module.combo."; public static final String DIST_MODULE_COMBO = "dist.module.combo.";
/**
* ID for Distribution Tag ComboBox
*/
public static final String DIST_TAG_COMBO = "dist.tag.combo";
/** /**
* ID-Dist.PIN. * ID-Dist.PIN.
*/ */
@@ -302,6 +306,22 @@ public final class SPUIComponentIdProvider {
* tag color preview button id. * tag color preview button id.
*/ */
public static final String TAG_COLOR_PREVIEW_ID = "tag.color.preview"; public static final String TAG_COLOR_PREVIEW_ID = "tag.color.preview";
/**
* Id for ColorPickerLayout
*/
public static final String COLOR_PICKER_LAYOUT = "color.picker.layout";
/**
* Id for ColorPickerLayout's red slider
*/
public static final String COLOR_PICKER_RED_SLIDER = "color.picker.red.slider";
/**
* Id for Color preview field with the color code
*/
public static final String COLOR_PREVIEW_FIELD = "color-preview-field";
/**
* Id for OptionGroup Create/Update tag
*/
public static final String OPTION_GROUP = "create.update.tag";
/** /**
* Confirmation dialogue OK button id. * Confirmation dialogue OK button id.
*/ */
@@ -979,6 +999,11 @@ public final class SPUIComponentIdProvider {
*/ */
public static final String SW_METADATA_DETAIL_LINK = "softwaremodule.metadata.detail.link"; public static final String SW_METADATA_DETAIL_LINK = "softwaremodule.metadata.detail.link";
/**
* Table multiselect for selecting DistType
*/
public static final String SELECT_DIST_TYPE = "select-dist-type";
/** /**
* /* Private Constructor. * /* Private Constructor.
*/ */

View File

@@ -344,15 +344,6 @@ public final class SPUIDefinitions {
* New Target tag color lable id. * New Target tag color lable id.
*/ */
public static final String NEW_TARGET_TAG_COLOR = "target.tag.add.color"; public static final String NEW_TARGET_TAG_COLOR = "target.tag.add.color";
/**
* New Target tag save icon id.
*/
// public static final String NEW_TARGET_TAG_SAVE = "target.tag.add.save";
/**
* New Target tag discard icon id.
*/
// public static final String NEW_TARGET_TAG_DISRACD =
// "target.tag.add.discard";
/** /**
* New Target tag add icon id. * New Target tag add icon id.
*/ */
@@ -1027,6 +1018,11 @@ public final class SPUIDefinitions {
*/ */
public static final String SOFTWAREMODULE_METADATA_TAB_ID = "swModule.metadata.tab.id"; public static final String SOFTWAREMODULE_METADATA_TAB_ID = "swModule.metadata.tab.id";
/***
* Custom window for metadata.
*/
public static final String CUSTOM_METADATA_WINDOW = "custom.metadata.window";
/** /**
* /** Constructor. * /** Constructor.
*/ */

View File

@@ -53,4 +53,7 @@
font-size: 16px; font-size: 16px;
} }
.marginTop {
margin-top: 20px !important;
}
} }

View File

@@ -81,18 +81,18 @@ caption.delete.swmodule.accordion.tab = Delete SW Modules
caption.delete.dist.set.type.accordion.tab = Delete Distribution Set Type caption.delete.dist.set.type.accordion.tab = Delete Distribution Set Type
caption.delete.sw.module.type.accordion.tab = Delete Software Module Type caption.delete.sw.module.type.accordion.tab = Delete Software Module Type
caption.attributes = Attributes caption.attributes = Attributes
caption.panel.dist.installed = Installed distribution set caption.panel.dist.installed = Installed Distribution Set
caption.panel.dist.assigned = Assigned distribution set caption.panel.dist.assigned = Assigned Distribution Set
caption.soft.delete.confirmbox = Confirm Software Module Delete Action caption.soft.delete.confirmbox = Confirm Software Module Delete Action
caption.cancel.action.confirmbox = Confirm action cancel caption.cancel.action.confirmbox = Confirm Action Cancellation
caption.forcequit.action.confirmbox = Confirm force quit action caption.forcequit.action.confirmbox = Confirm force quit action
caption.forced.datefield = Force update at time caption.forced.datefield = Force update at time
caption.force.action.confirmbox = Confirm Force Active Action caption.force.action.confirmbox = Confirm Force Active Action
caption.confirm.abort.action = Confirm abort action caption.confirm.abort.action = Confirm Abort Action
caption.filter.delete.confirmbox = Confirm Filter Delete Action caption.filter.delete.confirmbox = Confirm Filter Delete Action
caption.metadata.popup = Metadata of caption.metadata.popup = Metadata of
caption.metadata.delete.action.confirmbox = Confirm metadata delete action caption.metadata.delete.action.confirmbox = Confirm Metadata Delete Action
# Labels prefix with - label # Labels prefix with - label
@@ -200,7 +200,7 @@ tooltip.timeforced.item=Soft update until a specific time and then the action wi
tooltip.check.for.mandatory=Check to make Mandatory tooltip.check.for.mandatory=Check to make Mandatory
tooltip.artifact.icon=Show Artifact Details tooltip.artifact.icon=Show Artifact Details
tooltip.click.to.edit = Click to edit tooltip.click.to.edit = Click to edit
tooltip.metadata.icon = Manage metadata tooltip.metadata.icon = Manage Metadata
# Notification messages prefix with - message # Notification messages prefix with - message
message.save.success = {0} saved successfully message.save.success = {0} saved successfully
@@ -227,7 +227,7 @@ message.duplicate.softwaremodule = {0} : {1} already exists!
message.tag.delete = Please unclick the tag {0}, then try to delete message.tag.delete = Please unclick the tag {0}, then try to delete
message.dist.type.check.delete = Please unclick the distribution type {0}, then try to delete message.dist.type.check.delete = Please unclick the distribution type {0}, then try to delete
message.cannot.delete.default.dstype = Default distribution set type cannot be deleted message.cannot.delete.default.dstype = Default distribution set type cannot be deleted
message.swmodule.type.check.delete = Please unclick the software module type {0}, then try to delete message.swmodule.type.check.delete = Please unclick the Software Module type {0}, then try to delete
message.targets.already.deleted = Few Target(s) are already deleted.Pending for action message.targets.already.deleted = Few Target(s) are already deleted.Pending for action
message.dists.already.deleted = Few distribution(s) are already deleted.Pending for action message.dists.already.deleted = Few distribution(s) are already deleted.Pending for action
message.target.deleted.pending = Target(s) already deleted.Pending for action message.target.deleted.pending = Target(s) already deleted.Pending for action
@@ -269,10 +269,10 @@ message.dists.assign.tag.alreadyassigned = Few of the DistributionSet's are alre
message.dists.tag.assigned = {0} DistributionSet's assigned to Tag {1} message.dists.tag.assigned = {0} DistributionSet's assigned to Tag {1}
message.dists.tag.unassigned = {0} DistributionSet's un-assigned from Tag {1} message.dists.tag.unassigned = {0} DistributionSet's un-assigned from Tag {1}
message.dist.no.operation = {0} - already assigned/installed, No operation message.dist.no.operation = {0} - already assigned/installed, No operation
message.sm.delete.confirm = Are you sure that you want to delete the selected {0} software module? message.sm.delete.confirm = Are you sure that you want to delete the selected {0} Software Module?
message.error.os.softmodule = Please select the OS to delete message.error.os.softmodule = Please select the OS to delete
message.error.ah.softmodule = Please select the Application to delete message.error.ah.softmodule = Please select the Application to delete
message.error.softmodule.deleted = The selected software module is already deleted message.error.softmodule.deleted = The selected Software Module is already deleted
message.cancel.action = Cancel.. message.cancel.action = Cancel..
message.cancel.action.success = Action cancelled successfully ! message.cancel.action.success = Action cancelled successfully !
message.cancel.action.failed = Unable to cancel the action ! message.cancel.action.failed = Unable to cancel the action !
@@ -291,7 +291,7 @@ message.action.not.allowed = Action not allowed
message.onlyone.distribution.assigned = Only one distribution set can be assigned message.onlyone.distribution.assigned = Only one distribution set can be assigned
message.onlyone.distribution.dropallowed = Only one distribution set can be dropped message.onlyone.distribution.dropallowed = Only one distribution set can be dropped
message.error.missing.typename = Missing Type Name message.error.missing.typename = Missing Type Name
message.error.missing.typenameorkey = Missing Type Name or Key or software module type message.error.missing.typenameorkey = Missing Type Name or Key or Software Module type
message.tag.cannot.be.assigned = Target/DS cannot be assigned to {0} message.tag.cannot.be.assigned = Target/DS cannot be assigned to {0}
message.no.targets.assiged.fortag = No targets are assigned to tag {0} message.no.targets.assiged.fortag = No targets are assigned to tag {0}
message.error.missing.tagname = Please select tag name message.error.missing.tagname = Please select tag name
@@ -321,12 +321,12 @@ soft.module.os =OS
#Artifact upload #Artifact upload
message.error.noFileSelected = No file selected for upload message.error.noFileSelected = No file selected for upload
message.error.noProvidedName = Please provide custom file name message.error.noProvidedName = Please provide custom file name
message.error.noSwModuleSelected = Please select a software module message.error.noSwModuleSelected = Please select a Software Module
message.no.duplicateFiles = Duplicate files selected message.no.duplicateFiles = Duplicate files selected
message.no.duplicateFile = Duplicate file selected : message.no.duplicateFile = Duplicate file selected :
message.delete.artifact = Are you sure that you want to delete artifact {0} ? message.delete.artifact = Are you sure that you want to delete artifact {0} ?
message.duplicate.filename = Duplicate file name message.duplicate.filename = Duplicate file name
message.swModule.deleted = {0} Software module(s) deleted message.swModule.deleted = {0} Software Module(s) deleted
message.upload.failed = Streaming Failed message.upload.failed = Streaming Failed
message.uploadedfile.size.exceeded = File size exceeded .Allowed size {0} bytes message.uploadedfile.size.exceeded = File size exceeded .Allowed size {0} bytes
message.uploadedfile.aborted = File upload aborted message.uploadedfile.aborted = File upload aborted
@@ -336,7 +336,7 @@ message.abort.upload = Are you sure that you want to abort the upload?
upload.swModuleTable.header = Software module upload.swModuleTable.header = Software Module
upload.selectedfile.name = file selected for upload upload.selectedfile.name = file selected for upload
upload.file.name = File name upload.file.name = File name
upload.sha1 = SHA1 checksum upload.sha1 = SHA1 checksum
@@ -354,7 +354,7 @@ upload.reason = Reason
upload.action = Action upload.action = Action
upload.result.status = Upload status upload.result.status = Upload status
upload.file = Upload File upload.file = Upload File
upload.caption.update.swmodule = Update software module upload.caption.update.swmodule = Update Software Module
caption.tab.details = Details caption.tab.details = Details
caption.tab.description = Description caption.tab.description = Description
@@ -370,8 +370,8 @@ label.no.tag.assigned = NO TAG
caption.assign.software.dist.accordion.tab = Assign Software Modules caption.assign.software.dist.accordion.tab = Assign Software Modules
message.software.assignment = {0} Software Module(s) Assignment(s) done message.software.assignment = {0} Software Module(s) Assignment(s) done
message.dist.inuse = {0} Distribution is already assigned to target message.dist.inuse = {0} Distribution is already assigned to target
message.software.dist.already.assigned = {0} Distribution already has software module {1} message.software.dist.already.assigned = {0} Distribution already has Software Module {1}
message.software.dist.type.notallowed = {0} Software module type can not assign to Distribution {1} message.software.dist.type.notallowed = {0} Software Module type can not assign to Distribution {1}
message.target.assigned = {0} is assigned to {1} message.target.assigned = {0} is assigned to {1}
message.dist.type.delete = {0} DistributionType(s) Deleted successfully. message.dist.type.delete = {0} DistributionType(s) Deleted successfully.
message.sw.module.type.delete = {0} Software Module Type(s) deleted successfully. message.sw.module.type.delete = {0} Software Module Type(s) deleted successfully.
@@ -461,7 +461,7 @@ header.caption.mandatory = Mandatory
header.caption.typename = SoftwareModuleType header.caption.typename = SoftwareModuleType
header.caption.softwaremodule = SoftwareModule header.caption.softwaremodule = SoftwareModule
header.caption.unassign = Unassign header.caption.unassign = Unassign
message.sw.unassigned = Software module {0} successfully unassigned message.sw.unassigned = Software Module {0} successfully unassigned
header.caption.upload.details = Upload details header.caption.upload.details = Upload details
combo.type.tag.name = Type tag name combo.type.tag.name = Type tag name
@@ -484,10 +484,10 @@ rollout.group.label.target.truncated = {0} targets has been truncated in the lis
prompt.number.of.groups = Number of groups prompt.number.of.groups = Number of groups
prompt.tigger.threshold = Trigger threshold prompt.tigger.threshold = Trigger threshold
prompt.error.threshold = Error threshold prompt.error.threshold = Error threshold
prompt.distribution.set = Distribution set prompt.distribution.set = Distribution Set
caption.configure.rollout = Configure rollout caption.configure.rollout = Configure Rollout
caption.update.rollout = Update rollout caption.update.rollout = Update Rollout
prompt.target.filter = Custom target filter prompt.target.filter = Custom Target Filter
message.rollout.nonzero.group.number = Number of groups must be greater than zero message.rollout.nonzero.group.number = Number of groups must be greater than zero
message.rollout.max.group.number = Number of groups must not be greater than 500 message.rollout.max.group.number = Number of groups must not be greater than 500
message.rollout.duplicate.check = Rollout [ {0} ] must be unique, entered value already exists. message.rollout.duplicate.check = Rollout [ {0} ] must be unique, entered value already exists.
@@ -501,8 +501,8 @@ message.rollout.noofgroups.or.targetfilter.missing = Please enter number of grou
message.rollouts = Rollouts message.rollouts = Rollouts
label.target.per.group = Targets per group : label.target.per.group = Targets per group :
message.dist.already.assigned = Distribution {0} is already assigned to target message.dist.already.assigned = Distribution {0} is already assigned to target
message.error.creating.rollout = Server error. Error creating rollout. Please contact the administrator message.error.creating.rollout = Server error. Error creating Rollout. Please contact the administrator
message.error.starting.rollout = Server error. Error starting rollout. Please contact the administrator message.error.starting.rollout = Server error. Error starting Rollout. Please contact the administrator
#rollout - end #rollout - end
#Menu #Menu

View File

@@ -80,19 +80,19 @@ caption.delete.swmodule.accordion.tab = Delete SW Modules
caption.delete.dist.set.type.accordion.tab = Delete Distribution Set Type caption.delete.dist.set.type.accordion.tab = Delete Distribution Set Type
caption.delete.sw.module.type.accordion.tab = Delete Software Module Type caption.delete.sw.module.type.accordion.tab = Delete Software Module Type
caption.attributes = Attributes caption.attributes = Attributes
caption.panel.dist.installed = Installed distribution set caption.panel.dist.installed = Installed Distribution Set
caption.panel.dist.assigned = Assigned distribution set caption.panel.dist.assigned = Assigned Distribution Set
caption.soft.delete.confirmbox = Confirm Software Module Delete Action caption.soft.delete.confirmbox = Confirm Software Module Delete Action
caption.cancel.action.confirmbox = Confirm action cancellation caption.cancel.action.confirmbox = Confirm Action Cancellation
caption.forced.datefield = Force update at time caption.forced.datefield = Force update at time
caption.force.action.confirmbox = Confirm Force Active Action caption.force.action.confirmbox = Confirm Force Active Action
caption.filter.simple = Simple Filter caption.filter.simple = Simple Filter
caption.filter.custom = Custom Filter caption.filter.custom = Custom Filter
caption.filter.delete.confirmbox = Confirm Filter Delete Action caption.filter.delete.confirmbox = Confirm Filter Delete Action
caption.confirm.abort.action = Confirm abort action caption.confirm.abort.action = Confirm Abort Action
caption.metadata.popup = Metadata of caption.metadata.popup = Metadata of
caption.metadata.delete.action.confirmbox = Confirm metadata delete action caption.metadata.delete.action.confirmbox = Confirm Metadata Delete Action
# Labels prefix with - label # Labels prefix with - label
label.dist.details.type = Type : label.dist.details.type = Type :
@@ -198,7 +198,7 @@ tooltip.timeforced.item=Soft update until a specific time and then the action wi
tooltip.check.for.mandatory=Check to make Mandatory tooltip.check.for.mandatory=Check to make Mandatory
tooltip.artifact.icon=Show Artifact Details tooltip.artifact.icon=Show Artifact Details
tooltip.click.to.edit = Click to edit tooltip.click.to.edit = Click to edit
tooltip.metadata.icon = Manage metadata tooltip.metadata.icon = Manage Metadata
# Notification messages prefix with - message # Notification messages prefix with - message
@@ -221,13 +221,13 @@ message.target.unassigned.one = {0} is unassigned from {1}
message.target.unassigned.many = {0} Targets are unassigned from {1} message.target.unassigned.many = {0} Targets are unassigned from {1}
message.target.assigned.pending = Some target(s) are already assigned.Pending for action message.target.assigned.pending = Some target(s) are already assigned.Pending for action
message.cannot.delete = Cannot be deleted message.cannot.delete = Cannot be deleted
message.check.softwaremodule = Please provide both name and verion! message.check.softwaremodule = Please provide both name and version!
message.cannot.delete.default.dstype = Default distribution set type cannot be deleted message.cannot.delete.default.dstype = Default distribution set type cannot be deleted
message.duplicate.softwaremodule = {0} : {1} already exists! message.duplicate.softwaremodule = {0} : {1} already exists!
message.cannot.delete.default.dstype = Default distribution set type cannot be deleted message.cannot.delete.default.dstype = Default distribution set type cannot be deleted
message.tag.delete = Please unclick the tag {0}, then try to delete message.tag.delete = Please unclick the tag {0}, then try to delete
message.dist.type.check.delete = Please unclick the distribution type {0}, then try to delete message.dist.type.check.delete = Please unclick the distribution type {0}, then try to delete
message.swmodule.type.check.delete = Please unclick the software module type {0}, then try to delete message.swmodule.type.check.delete = Please unclick the Software Module type {0}, then try to delete
message.targets.already.deleted = Few Target(s) are already deleted.Pending for action message.targets.already.deleted = Few Target(s) are already deleted.Pending for action
message.dists.already.deleted = Few distribution(s) are already deleted.Pending for action message.dists.already.deleted = Few distribution(s) are already deleted.Pending for action
message.target.deleted.pending = Target(s) already deleted.Pending for action message.target.deleted.pending = Target(s) already deleted.Pending for action
@@ -250,7 +250,7 @@ message.accessdenied.view = No access to view: {0}
message.no.data = No data available message.no.data = No data available
message.target.assignment = {0} Assignment(s) done message.target.assignment = {0} Assignment(s) done
message.target.deleted = {0} Target(s) deleted message.target.deleted = {0} Target(s) deleted
message.dist.deleted = {0} Distribution set(s) deleted message.dist.deleted = {0} Distribution Set(s) deleted
message.tag.update.mandatory = Please select the Tag to update message.tag.update.mandatory = Please select the Tag to update
message.tag.duplicate.check = {0} already exists, please enter another value message.tag.duplicate.check = {0} already exists, please enter another value
message.type.key.duplicate.check = Distribution type with key {0} already exists, please give another value message.type.key.duplicate.check = Distribution type with key {0} already exists, please give another value
@@ -269,10 +269,10 @@ message.dists.assign.tag.alreadyassigned = Few of the DistributionSet's are alre
message.dists.tag.assigned = {0} DistributionSet's assigned to Tag {1} message.dists.tag.assigned = {0} DistributionSet's assigned to Tag {1}
message.dists.tag.unassigned = {0} DistributionSet's un-assigned from Tag {1} message.dists.tag.unassigned = {0} DistributionSet's un-assigned from Tag {1}
message.dist.no.operation = {0} - already assigned/installed, No operation message.dist.no.operation = {0} - already assigned/installed, No operation
message.sm.delete.confirm = Are you sure that you want to delete the selected {0} software module? message.sm.delete.confirm = Are you sure that you want to delete the selected {0} Software Module?
message.error.os.softmodule = Please select the OS to delete message.error.os.softmodule = Please select the OS to delete
message.error.ah.softmodule = Please select the Application to delete message.error.ah.softmodule = Please select the Application to delete
message.error.softmodule.deleted = The selected software module is already deleted message.error.softmodule.deleted = The selected Software Module is already deleted
message.cancel.action = Cancel message.cancel.action = Cancel
message.cancel.action.success = Action cancelled successfully ! message.cancel.action.success = Action cancelled successfully !
message.cancel.action.failed = Unable to cancel the action ! message.cancel.action.failed = Unable to cancel the action !
@@ -314,12 +314,12 @@ soft.module.os =OS
#Artifact upload #Artifact upload
message.error.noFileSelected = No file selected for upload message.error.noFileSelected = No file selected for upload
message.error.noProvidedName = Please provide custom file name message.error.noProvidedName = Please provide custom file name
message.error.noSwModuleSelected = Please select a software module message.error.noSwModuleSelected = Please select a Software Module
message.no.duplicateFiles = Duplicate files selected message.no.duplicateFiles = Duplicate files selected
message.no.duplicateFile = Duplicate file selected : message.no.duplicateFile = Duplicate file selected :
message.delete.artifact = Are you sure that you want to delete artifact {0} ? message.delete.artifact = Are you sure that you want to delete artifact {0} ?
message.duplicate.filename = Duplicate file name message.duplicate.filename = Duplicate file name
message.swModule.deleted = {0} Software module(s) deleted message.swModule.deleted = {0} Software Module(s) deleted
message.error.missing.tagname = Please select tag name message.error.missing.tagname = Please select tag name
message.upload.failed = Streaming Failed message.upload.failed = Streaming Failed
message.uploadedfile.size.exceeded = File size exceeded .Allowed size {0} bytes message.uploadedfile.size.exceeded = File size exceeded .Allowed size {0} bytes
@@ -330,7 +330,7 @@ message.abort.upload = Are you sure that you want to abort the upload?
upload.swModuleTable.header = Software module upload.swModuleTable.header = Software Module
upload.selectedfile.name = file selected for upload upload.selectedfile.name = file selected for upload
upload.file.name = File name upload.file.name = File name
upload.sha1 = SHA1 checksum upload.sha1 = SHA1 checksum
@@ -348,7 +348,7 @@ upload.reason = Reason
upload.action = Action upload.action = Action
upload.result.status = Upload status upload.result.status = Upload status
upload.file = Upload File upload.file = Upload File
upload.caption.update.swmodule = Update software module upload.caption.update.swmodule = Update Software Module
caption.tab.details = Details caption.tab.details = Details
caption.tab.description = Description caption.tab.description = Description
@@ -359,8 +359,8 @@ label.drop.dist.delete.area = Drop here<br>to delete
caption.assign.software.dist.accordion.tab = Assign Software Modules caption.assign.software.dist.accordion.tab = Assign Software Modules
message.software.assignment = {0} Assignment(s) done message.software.assignment = {0} Assignment(s) done
message.dist.inuse = {0} Distribution is already assigned to target message.dist.inuse = {0} Distribution is already assigned to target
message.software.dist.already.assigned = {0} Distribution already has software module {1} message.software.dist.already.assigned = {0} Distribution already has Software Module {1}
message.software.dist.type.notallowed = {0} Software module type can not assign to Distribution {1} message.software.dist.type.notallowed = {0} Software Module type can not assign to Distribution {1}
message.target.assigned = {0} is assigned to {1} message.target.assigned = {0} is assigned to {1}
message.dist.type.delete = {0} DistributionType(s) Deleted successfully. message.dist.type.delete = {0} DistributionType(s) Deleted successfully.
message.sw.module.type.delete = {0} Software Module Type(s) deleted successfully. message.sw.module.type.delete = {0} Software Module Type(s) deleted successfully.
@@ -447,13 +447,13 @@ header.rolloutgroup.target.message = Messages
rollout.group.label.target.truncated = {0} targets has been truncated in the list due the target size limit of {1} rollout.group.label.target.truncated = {0} targets has been truncated in the list due the target size limit of {1}
distribution.details.header = Distribution set distribution.details.header = Distribution Set
target.details.header = Target target.details.header = Target
header.caption.mandatory = Mandatory header.caption.mandatory = Mandatory
header.caption.typename = SoftwareModuleType header.caption.typename = SoftwareModuleType
header.caption.softwaremodule = SoftwareModule header.caption.softwaremodule = SoftwareModule
header.caption.unassign = Unassign header.caption.unassign = Unassign
message.sw.unassigned = Software module {0} successfully unassigned message.sw.unassigned = Software Module {0} successfully unassigned
header.caption.upload.details = Upload details header.caption.upload.details = Upload details
header.key = Key header.key = Key
header.value = Value header.value = Value
@@ -471,10 +471,10 @@ menu.title = Software Provisioning
prompt.number.of.groups = Number of groups prompt.number.of.groups = Number of groups
prompt.tigger.threshold = Trigger threshold prompt.tigger.threshold = Trigger threshold
prompt.error.threshold = Error threshold prompt.error.threshold = Error threshold
prompt.distribution.set = Distribution set prompt.distribution.set = Distribution Set
caption.configure.rollout = Configure rollout caption.configure.rollout = Configure Rollout
caption.update.rollout = Update rollout caption.update.rollout = Update Rollout
prompt.target.filter = Custom target filter prompt.target.filter = Custom Target Filter
message.rollout.nonzero.group.number = Number of groups must be greater than zero message.rollout.nonzero.group.number = Number of groups must be greater than zero
message.rollout.max.group.number = Number of groups must not be greater than 500 message.rollout.max.group.number = Number of groups must not be greater than 500
message.rollout.duplicate.check = Rollout [ {0} ] must be unique, entered value already exists. message.rollout.duplicate.check = Rollout [ {0} ] must be unique, entered value already exists.
@@ -488,8 +488,8 @@ message.rollout.noofgroups.or.targetfilter.missing = Please enter number of grou
message.rollouts = Rollouts message.rollouts = Rollouts
label.target.per.group = Targets per group : label.target.per.group = Targets per group :
message.dist.already.assigned = Distribution {0} is already assigned to target message.dist.already.assigned = Distribution {0} is already assigned to target
message.error.creating.rollout = Server error. Error creating rollout. Please contact the administrator message.error.creating.rollout = Server error. Error creating Rollout. Please contact the administrator
message.error.starting.rollout = Server error. Error starting rollout. Please contact the administrator message.error.starting.rollout = Server error. Error starting Rollout. Please contact the administrator
#Target Filter Management #Target Filter Management
breadcrumb.target.filter.custom.filters = Custom Filters breadcrumb.target.filter.custom.filters = Custom Filters

View File

@@ -81,17 +81,17 @@ caption.delete.swmodule.accordion.tab = Delete SW Modules
caption.delete.dist.set.type.accordion.tab = Delete Distribution Set Type caption.delete.dist.set.type.accordion.tab = Delete Distribution Set Type
caption.delete.sw.module.type.accordion.tab = Delete Software Module Type caption.delete.sw.module.type.accordion.tab = Delete Software Module Type
caption.attributes = Attributes caption.attributes = Attributes
caption.panel.dist.installed = Installed distribution set caption.panel.dist.installed = Installed Distribution Set
caption.panel.dist.assigned = Assigned distribution set caption.panel.dist.assigned = Assigned Distribution Set
caption.soft.delete.confirmbox = Confirm Software Module Delete Action caption.soft.delete.confirmbox = Confirm Software Module Delete Action
caption.cancel.action.confirmbox = Confirm action cancellation caption.cancel.action.confirmbox = Confirm Action Cancellation
caption.forced.datefield = Force update at time caption.forced.datefield = Force update at time
caption.force.action.confirmbox = Confirm Force Active Action caption.force.action.confirmbox = Confirm Force Active Action
caption.filter.delete.confirmbox = Confirm Filter Delete Action caption.filter.delete.confirmbox = Confirm Filter Delete Action
caption.metadata.popup = Metadata of caption.metadata.popup = Metadata of
caption.metadata.delete.action.confirmbox = Confirm metadata delete action caption.metadata.delete.action.confirmbox = Confirm Metadata Delete Action
caption.confirm.abort.action = Confirm abort action caption.confirm.abort.action = Confirm Abort Action
# Labels prefix with - label # Labels prefix with - label
label.dist.details.type = Type : label.dist.details.type = Type :
@@ -198,7 +198,7 @@ tooltip.timeforced.item=Soft update until a specific time and then the action wi
tooltip.check.for.mandatory=Check to make Mandatory tooltip.check.for.mandatory=Check to make Mandatory
tooltip.artifact.icon=Show Artifact Details tooltip.artifact.icon=Show Artifact Details
tooltip.click.to.edit = Click to edit tooltip.click.to.edit = Click to edit
tooltip.metadata.icon = Manage metadata tooltip.metadata.icon = Manage Metadata
# Notification messages prefix with - message # Notification messages prefix with - message
@@ -221,11 +221,11 @@ message.target.unassigned.one = {0} is unassigned from {1}
message.target.unassigned.many = {0} Targets are unassigned from {1} message.target.unassigned.many = {0} Targets are unassigned from {1}
message.target.assigned.pending = Some target(s) are already assigned.Pending for action message.target.assigned.pending = Some target(s) are already assigned.Pending for action
message.cannot.delete = Cannot be deleted message.cannot.delete = Cannot be deleted
message.check.softwaremodule = Please provide both name and verion! message.check.softwaremodule = Please provide both name and version!
message.duplicate.softwaremodule = {0} : {1} already exists! message.duplicate.softwaremodule = {0} : {1} already exists!
message.tag.delete = Please unclick the tag {0}, then try to delete message.tag.delete = Please unclick the tag {0}, then try to delete
message.dist.type.check.delete = Please unclick the distribution type {0}, then try to delete message.dist.type.check.delete = Please unclick the distribution type {0}, then try to delete
message.swmodule.type.check.delete = Please unclick the software module type {0}, then try to delete message.swmodule.type.check.delete = Please unclick the Software Module type {0}, then try to delete
message.targets.already.deleted = Few Target(s) are already deleted.Pending for action message.targets.already.deleted = Few Target(s) are already deleted.Pending for action
message.dists.already.deleted = Few distribution(s) are already deleted.Pending for action message.dists.already.deleted = Few distribution(s) are already deleted.Pending for action
message.target.deleted.pending = Target(s) already deleted.Pending for action message.target.deleted.pending = Target(s) already deleted.Pending for action
@@ -267,10 +267,10 @@ message.dists.assign.tag.alreadyassigned = Few of the DistributionSet's are alre
message.dists.tag.assigned = {0} DistributionSet's assigned to Tag {1} message.dists.tag.assigned = {0} DistributionSet's assigned to Tag {1}
message.dists.tag.unassigned = {0} DistributionSet's un-assigned from Tag {1} message.dists.tag.unassigned = {0} DistributionSet's un-assigned from Tag {1}
message.dist.no.operation = {0} - already assigned/installed, No operation message.dist.no.operation = {0} - already assigned/installed, No operation
message.sm.delete.confirm = Are you sure that you want to delete the selected {0} software module? message.sm.delete.confirm = Are you sure that you want to delete the selected {0} Software Module?
message.error.os.softmodule = Please select the OS to delete message.error.os.softmodule = Please select the OS to delete
message.error.ah.softmodule = Please select the Application to delete message.error.ah.softmodule = Please select the Application to delete
message.error.softmodule.deleted = The selected software module is already deleted message.error.softmodule.deleted = The selected Software Module is already deleted
message.cancel.action = Cancel message.cancel.action = Cancel
message.cancel.action.success = Action cancelled successfully ! message.cancel.action.success = Action cancelled successfully !
message.cancel.action.failed = Unable to cancel the action ! message.cancel.action.failed = Unable to cancel the action !
@@ -285,7 +285,7 @@ message.action.not.allowed = Action not allowed
message.onlyone.distribution.assigned = Only one distribution set can be assigned message.onlyone.distribution.assigned = Only one distribution set can be assigned
message.onlyone.distribution.dropallowed = Only one distribution set can be dropped message.onlyone.distribution.dropallowed = Only one distribution set can be dropped
message.error.missing.typename = Missing Type Name message.error.missing.typename = Missing Type Name
message.error.missing.typenameorkey = Missing Type Name or Key or software module type message.error.missing.typenameorkey = Missing Type Name or Key or Software Module type
message.tag.cannot.be.assigned = Target/DS cannot be assigned to {0} message.tag.cannot.be.assigned = Target/DS cannot be assigned to {0}
message.no.targets.assiged.fortag = No targets are assigned to tag {0} message.no.targets.assiged.fortag = No targets are assigned to tag {0}
message.error.missing.tagname = Please select tag name message.error.missing.tagname = Please select tag name
@@ -313,12 +313,12 @@ soft.module.os =OS
#Artifact upload #Artifact upload
message.error.noFileSelected = No file selected for upload message.error.noFileSelected = No file selected for upload
message.error.noProvidedName = Please provide custom file name message.error.noProvidedName = Please provide custom file name
message.error.noSwModuleSelected = Please select a software module message.error.noSwModuleSelected = Please select a Software Module
message.no.duplicateFiles = Duplicate files selected message.no.duplicateFiles = Duplicate files selected
message.no.duplicateFile = Duplicate file selected : message.no.duplicateFile = Duplicate file selected :
message.delete.artifact = Are you sure that you want to delete artifact {0} ? message.delete.artifact = Are you sure that you want to delete artifact {0} ?
message.duplicate.filename = Duplicate file name message.duplicate.filename = Duplicate file name
message.swModule.deleted = {0} Software module(s) deleted message.swModule.deleted = {0} Software Module(s) deleted
message.upload.failed = Streaming Failed message.upload.failed = Streaming Failed
message.uploadedfile.size.exceeded = File size exceeded .Allowed size {0} bytes message.uploadedfile.size.exceeded = File size exceeded .Allowed size {0} bytes
message.uploadedfile.aborted = File upload aborted message.uploadedfile.aborted = File upload aborted
@@ -326,7 +326,7 @@ message.file.not.found = File not found
message.abort.upload = Are you sure that you want to abort the upload? message.abort.upload = Are you sure that you want to abort the upload?
upload.swModuleTable.header = Software module upload.swModuleTable.header = Software Module
upload.selectedfile.name = file selected for upload upload.selectedfile.name = file selected for upload
upload.file.name = File name upload.file.name = File name
upload.sha1 = SHA1 checksum upload.sha1 = SHA1 checksum
@@ -344,7 +344,7 @@ upload.reason = Reason
upload.action = Action upload.action = Action
upload.result.status = Upload status upload.result.status = Upload status
upload.file = Upload File upload.file = Upload File
upload.caption.update.swmodule = Update software module upload.caption.update.swmodule = Update Software Module
caption.tab.details = Details caption.tab.details = Details
caption.tab.description = Description caption.tab.description = Description
@@ -356,8 +356,8 @@ label.drop.dist.delete.area = Drop here<br>to delete
caption.assign.software.dist.accordion.tab = Assign Software Modules caption.assign.software.dist.accordion.tab = Assign Software Modules
message.software.assignment = {0} Software Module(s) Assignment(s) done message.software.assignment = {0} Software Module(s) Assignment(s) done
message.dist.inuse = {0} Distribution is already assigned to target message.dist.inuse = {0} Distribution is already assigned to target
message.software.dist.already.assigned = {0} Distribution already has software module {1} message.software.dist.already.assigned = {0} Distribution already has Software Module {1}
message.software.dist.type.notallowed = {0} Software module type can not assign to Distribution {1} message.software.dist.type.notallowed = {0} Software Module type can not assign to Distribution {1}
message.target.assigned = {0} is assigned to {1} message.target.assigned = {0} is assigned to {1}
message.dist.type.delete = {0} DistributionType(s) Deleted successfully. message.dist.type.delete = {0} DistributionType(s) Deleted successfully.
message.sw.module.type.delete = {0} Software Module Type(s) deleted successfully. message.sw.module.type.delete = {0} Software Module Type(s) deleted successfully.
@@ -430,7 +430,7 @@ header.assigned.ds = Assigned DS
header.installed.ds = Installed DS header.installed.ds = Installed DS
header.status = Status header.status = Status
header.target.tags = Tags header.target.tags = Tags
header.distributionset = Distribution set header.distributionset = Distribution Set
header.numberofgroups = No. of groups header.numberofgroups = No. of groups
header.detail.status = Detail status header.detail.status = Detail status
header.total.targets = Total targets header.total.targets = Total targets
@@ -444,7 +444,7 @@ header.rolloutgroup.target.message = Messages
rollout.group.label.target.truncated = {0} targets has been truncated in the list due the target size limit of {1} rollout.group.label.target.truncated = {0} targets has been truncated in the list due the target size limit of {1}
distribution.details.header = Distribution set distribution.details.header = Distribution Set
target.details.header = Target target.details.header = Target
header.caption.mandatory = Mandatory header.caption.mandatory = Mandatory
header.caption.typename = SoftwareModuleType header.caption.typename = SoftwareModuleType
@@ -465,10 +465,10 @@ menu.title = Software Provisioning
prompt.number.of.groups = Number of groups prompt.number.of.groups = Number of groups
prompt.tigger.threshold = Trigger threshold prompt.tigger.threshold = Trigger threshold
prompt.error.threshold = Error threshold prompt.error.threshold = Error threshold
prompt.distribution.set = Distribution set prompt.distribution.set = Distribution Set
caption.configure.rollout = Configure rollout caption.configure.rollout = Configure Rollout
caption.update.rollout = Update rollout caption.update.rollout = Update Rollout
prompt.target.filter = Custom target filter prompt.target.filter = Custom Target Filter
message.rollout.nonzero.group.number = Number of groups must be greater than zero message.rollout.nonzero.group.number = Number of groups must be greater than zero
message.rollout.max.group.number = Number of groups must not be greater than 500 message.rollout.max.group.number = Number of groups must not be greater than 500
message.rollout.duplicate.check = Rollout [ {0} ] must be unique, entered value already exists. message.rollout.duplicate.check = Rollout [ {0} ] must be unique, entered value already exists.
@@ -482,8 +482,8 @@ message.rollout.noofgroups.or.targetfilter.missing = Please enter number of grou
message.rollouts = Rollouts message.rollouts = Rollouts
label.target.per.group = Targets per group : label.target.per.group = Targets per group :
message.dist.already.assigned = Distribution {0} is already assigned to target message.dist.already.assigned = Distribution {0} is already assigned to target
message.error.creating.rollout = Server error. Error creating rollout. Please contact the administrator message.error.creating.rollout = Server error. Error creating Rollout. Please contact the administrator
message.error.starting.rollout = Server error. Error starting rollout. Please contact the administrator message.error.starting.rollout = Server error. Error starting Rollout. Please contact the administrator
#Target Filter Management #Target Filter Management
breadcrumb.target.filter.custom.filters = Custom Filters breadcrumb.target.filter.custom.filters = Custom Filters

View File

@@ -111,6 +111,7 @@
<jlorem.version>1.1</jlorem.version> <jlorem.version>1.1</jlorem.version>
<json-simple.version>1.1.1</json-simple.version> <json-simple.version>1.1.1</json-simple.version>
<commons-lang3.version>3.4</commons-lang3.version> <commons-lang3.version>3.4</commons-lang3.version>
<commons-collections4.version>4.0</commons-collections4.version>
<json.version>20141113</json.version> <json.version>20141113</json.version>
<rsql-parser.version>2.0.0</rsql-parser.version> <rsql-parser.version>2.0.0</rsql-parser.version>
<!-- Misc libraries versions - END --> <!-- Misc libraries versions - END -->
@@ -560,6 +561,11 @@
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version> <version>${commons-lang3.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>${commons-collections4.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>