diff --git a/core/che-core-api-jdbc/src/main/java/org/eclipse/che/api/core/jdbc/jpa/eclipselink/DescriptorEventAdapter.java b/core/che-core-api-jdbc/src/main/java/org/eclipse/che/api/core/jdbc/jpa/eclipselink/DescriptorEventAdapter.java new file mode 100644 index 0000000000..19577ebb8d --- /dev/null +++ b/core/che-core-api-jdbc/src/main/java/org/eclipse/che/api/core/jdbc/jpa/eclipselink/DescriptorEventAdapter.java @@ -0,0 +1,73 @@ +package org.eclipse.che.api.core.jdbc.jpa.eclipselink; + +import org.eclipse.persistence.descriptors.DescriptorEvent; +import org.eclipse.persistence.descriptors.DescriptorEventListener; + +import java.util.Vector; + +/** + * Adapter class for receiving EclipseLink events. + * The methods are empty, this class allows to implement + * only needed methods. + * + * @author Yevhenii Voevodin + */ +public abstract class DescriptorEventAdapter implements DescriptorEventListener { + + @Override + public void aboutToDelete(DescriptorEvent event) {} + + @Override + public void aboutToInsert(DescriptorEvent event) {} + + @Override + public void aboutToUpdate(DescriptorEvent event) {} + + @Override + public boolean isOverriddenEvent(DescriptorEvent event, Vector eventManagers) { return false; } + + @Override + public void postBuild(DescriptorEvent event) {} + + @Override + public void postClone(DescriptorEvent event) {} + + @Override + public void postDelete(DescriptorEvent event) {} + + @Override + public void postInsert(DescriptorEvent event) {} + + @Override + public void postMerge(DescriptorEvent event) {} + + @Override + public void postRefresh(DescriptorEvent event) {} + + @Override + public void postUpdate(DescriptorEvent event) {} + + @Override + public void postWrite(DescriptorEvent event) {} + + @Override + public void preDelete(DescriptorEvent event) {} + + @Override + public void preInsert(DescriptorEvent event) {} + + @Override + public void prePersist(DescriptorEvent event) {} + + @Override + public void preRemove(DescriptorEvent event) {} + + @Override + public void preUpdate(DescriptorEvent event) {} + + @Override + public void preUpdateWithChanges(DescriptorEvent event) {} + + @Override + public void preWrite(DescriptorEvent event) {} +} diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/Workspace.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/Workspace.java index 9ce8041fc5..b8460e53d2 100644 --- a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/Workspace.java +++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/Workspace.java @@ -36,12 +36,6 @@ public interface Workspace { */ String getNamespace(); - /** - * Returns the name of the current workspace instance. - * Workspace name is unique per namespace. - */ - String getName(); - /** * Returns the status of the current workspace instance. * diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/WorkspaceConfig.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/WorkspaceConfig.java index beb0e2c12a..4c0580e9e3 100644 --- a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/WorkspaceConfig.java +++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/WorkspaceConfig.java @@ -26,11 +26,8 @@ import java.util.Map; public interface WorkspaceConfig { /** - * Optional. - * Returns possible name of the workspace created from this configuration. - * If name doesn't conflict then the target workspace - * will have exactly the same name, but if the name conflicts or it is absent - * then any other name will be chose for the workspace. + * Returns the name of the current workspace instance. + * Workspace name is unique per namespace. */ String getName(); diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/WorkspaceImpl.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/WorkspaceImpl.java index 380b36bdd7..d42f8d868a 100644 --- a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/WorkspaceImpl.java +++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/WorkspaceImpl.java @@ -25,7 +25,6 @@ import java.util.Map; public class WorkspaceImpl implements Workspace { private final String id; - private final String name; private final WorkspaceRuntime workspaceRuntime; private final String namespace; private final WorkspaceStatus status; @@ -36,7 +35,6 @@ public class WorkspaceImpl implements Workspace { public WorkspaceImpl(Workspace workspace) { id = workspace.getId(); - name = workspace.getName(); workspaceRuntime = workspace.getRuntime(); namespace = workspace.getNamespace(); status = workspace.getStatus(); @@ -56,11 +54,6 @@ public class WorkspaceImpl implements Workspace { return namespace; } - @Override - public String getName() { - return name; - } - @Override public WorkspaceStatus getStatus() { return status; diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/jpa/JpaWorkspaceDao.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/jpa/JpaWorkspaceDao.java index fafcb56fd7..d71710078f 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/jpa/JpaWorkspaceDao.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/jpa/JpaWorkspaceDao.java @@ -60,7 +60,7 @@ public class JpaWorkspaceDao implements WorkspaceDao { } catch (DuplicateKeyException dkEx) { throw new ConflictException(format("Workspace with id '%s' or name '%s' in namespace '%s' already exists", workspace.getId(), - workspace.getName(), + workspace.getConfig().getName(), workspace.getNamespace())); } catch (RuntimeException x) { throw new ServerException(x.getMessage(), x); @@ -75,7 +75,7 @@ public class JpaWorkspaceDao implements WorkspaceDao { return doUpdate(update); } catch (DuplicateKeyException dkEx) { throw new ConflictException(format("Workspace with name '%s' in namespace '%s' already exists", - update.getName(), + update.getConfig().getName(), update.getNamespace())); } catch (RuntimeException x) { throw new ServerException(x.getMessage(), x); diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/WorkspaceImpl.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/WorkspaceImpl.java index 92c250270b..e95050bfc3 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/WorkspaceImpl.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/WorkspaceImpl.java @@ -12,6 +12,7 @@ package org.eclipse.che.api.workspace.server.model.impl; import org.eclipse.che.account.shared.model.Account; import org.eclipse.che.account.spi.AccountImpl; +import org.eclipse.che.api.core.jdbc.jpa.eclipselink.DescriptorEventAdapter; import org.eclipse.che.api.core.model.workspace.Workspace; import org.eclipse.che.api.core.model.workspace.WorkspaceConfig; import org.eclipse.che.api.core.model.workspace.WorkspaceRuntime; @@ -19,6 +20,7 @@ import org.eclipse.che.api.core.model.workspace.WorkspaceStatus; import org.eclipse.che.api.machine.server.model.impl.SnapshotImpl; import org.eclipse.che.api.workspace.server.jpa.WorkspaceEntityListener; import org.eclipse.che.commons.lang.NameGenerator; +import org.eclipse.persistence.descriptors.DescriptorEvent; import javax.persistence.Basic; import javax.persistence.CascadeType; @@ -34,6 +36,8 @@ import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.OneToOne; +import javax.persistence.PrePersist; +import javax.persistence.PreUpdate; import javax.persistence.Table; import javax.persistence.Transient; import javax.persistence.UniqueConstraint; @@ -42,9 +46,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import static com.google.common.base.MoreObjects.firstNonNull; -import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.STOPPED; - /** * Data object for {@link Workspace}. * @@ -62,7 +63,7 @@ import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.STOPPED; query = "SELECT w FROM Workspace w") } ) -@EntityListeners(WorkspaceEntityListener.class) +@EntityListeners({WorkspaceEntityListener.class, WorkspaceImpl.SyncNameOnUpdateAndPersistEventListener.class}) public class WorkspaceImpl implements Workspace { public static WorkspaceImplBuilder builder() { @@ -72,7 +73,12 @@ public class WorkspaceImpl implements Workspace { @Id private String id; - @Column(nullable = false) + /** + * The original workspace name is workspace.config.name + * this attribute is stored for unique constraint with account id. + * See {@link #syncName()}. + */ + @Column private String name; @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true) @@ -96,7 +102,7 @@ public class WorkspaceImpl implements Workspace { private AccountImpl account; @Transient - private WorkspaceStatus status = STOPPED; + private WorkspaceStatus status; @Transient private WorkspaceRuntimeImpl runtime; @@ -104,19 +110,17 @@ public class WorkspaceImpl implements Workspace { public WorkspaceImpl() {} public WorkspaceImpl(String id, Account account, WorkspaceConfig config) { - this(id, account, config.getName(), config, null, null, false, STOPPED); + this(id, account, config, null, null, false, null); } public WorkspaceImpl(String id, Account account, - String name, WorkspaceConfig config, WorkspaceRuntime runtime, Map attributes, boolean isTemporary, WorkspaceStatus status) { this.id = id; - this.name = name; if (account != null) { this.account = new AccountImpl(account); } @@ -129,14 +133,13 @@ public class WorkspaceImpl implements Workspace { if (attributes != null) { this.attributes = new HashMap<>(attributes); } - this.status = firstNonNull(status, STOPPED); this.isTemporary = isTemporary; + this.status = status; } public WorkspaceImpl(Workspace workspace, Account account) { this(workspace.getId(), account, - workspace.getConfig().getName(), workspace.getConfig(), workspace.getRuntime(), workspace.getAttributes(), @@ -169,14 +172,6 @@ public class WorkspaceImpl implements Workspace { return account; } - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - @Override public WorkspaceConfigImpl getConfig() { return config; @@ -232,7 +227,6 @@ public class WorkspaceImpl implements Workspace { final WorkspaceImpl other = (WorkspaceImpl)obj; return Objects.equals(id, other.id) && Objects.equals(getNamespace(), other.getNamespace()) - && Objects.equals(name, other.name) && Objects.equals(status, other.status) && isTemporary == other.isTemporary && getAttributes().equals(other.getAttributes()) @@ -245,7 +239,6 @@ public class WorkspaceImpl implements Workspace { int hash = 7; hash = 31 * hash + Objects.hashCode(id); hash = 31 * hash + Objects.hashCode(getNamespace()); - hash = 31 * hash + Objects.hashCode(name); hash = 31 * hash + Objects.hashCode(status); hash = 31 * hash + Objects.hashCode(config); hash = 31 * hash + getAttributes().hashCode(); @@ -268,6 +261,33 @@ public class WorkspaceImpl implements Workspace { '}'; } + /** Syncs {@link #name} with config name. */ + private void syncName() { + name = config == null ? null : config.getName(); + } + + /** + * {@link PreUpdate} and {@link PrePersist} methods are not called when + * the configuration is updated and workspace object is not, while listener + * methods are always called, even if workspace instance is not changed. + */ + public static class SyncNameOnUpdateAndPersistEventListener extends DescriptorEventAdapter { + @Override + public void preUpdate(DescriptorEvent event) { + ((WorkspaceImpl)event.getObject()).syncName(); + } + + @Override + public void prePersist(DescriptorEvent event) { + ((WorkspaceImpl)event.getObject()).syncName(); + } + + @Override + public void preUpdateWithChanges(DescriptorEvent event) { + ((WorkspaceImpl)event.getObject()).syncName(); + } + } + /** * Helps to build complex {@link WorkspaceImpl workspace} instance. * @@ -277,7 +297,6 @@ public class WorkspaceImpl implements Workspace { private String id; private Account account; - private String name; private boolean isTemporary; private WorkspaceStatus status; private WorkspaceConfig config; @@ -287,7 +306,7 @@ public class WorkspaceImpl implements Workspace { private WorkspaceImplBuilder() {} public WorkspaceImpl build() { - return new WorkspaceImpl(id, account, name, config, runtime, attributes, isTemporary, status); + return new WorkspaceImpl(id, account, config, runtime, attributes, isTemporary, status); } public WorkspaceImplBuilder generateId() { @@ -297,7 +316,6 @@ public class WorkspaceImpl implements Workspace { public WorkspaceImplBuilder setConfig(WorkspaceConfig workspaceConfig) { this.config = workspaceConfig; - this.name = workspaceConfig.getName(); return this; } @@ -330,10 +348,5 @@ public class WorkspaceImpl implements Workspace { this.runtime = runtime; return this; } - - public WorkspaceImplBuilder setName(String name) { - this.name = name; - return this; - } } } diff --git a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/jpa/JpaWorkspaceDaoTest.java b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/jpa/JpaWorkspaceDaoTest.java index 1c92e08778..c8f211e1f7 100644 --- a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/jpa/JpaWorkspaceDaoTest.java +++ b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/jpa/JpaWorkspaceDaoTest.java @@ -13,6 +13,7 @@ package org.eclipse.che.api.workspace.server.jpa; import com.google.inject.Guice; import org.eclipse.che.account.spi.AccountImpl; +import org.eclipse.che.api.core.jdbc.jpa.DuplicateKeyException; import org.eclipse.che.api.workspace.server.model.impl.ProjectConfigImpl; import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl; import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl; @@ -45,6 +46,10 @@ public class JpaWorkspaceDaoTest { @AfterMethod private void cleanup() { + manager.getTransaction().begin(); + manager.createQuery("DELETE FROM Workspace workspaces"); + manager.createQuery("DELETE FROM Account accounts"); + manager.getTransaction().commit(); manager.getEntityManagerFactory().close(); } @@ -82,6 +87,26 @@ public class JpaWorkspaceDaoTest { assertEquals(asLong("SELECT COUNT(e) FROM Environment e"), 0L, "Environments"); } + @Test(expectedExceptions = DuplicateKeyException.class) + public void shouldSynchronizeWorkspaceNameWithConfigNameWhenConfigIsUpdated() throws Exception { + final AccountImpl account = new AccountImpl("accountId", "namespace", "test"); + final WorkspaceImpl workspace1 = createWorkspace("id", account, "name1"); + final WorkspaceImpl workspace2 = createWorkspace("id2", account, "name2"); + + // persist prepared data + manager.getTransaction().begin(); + manager.persist(account); + manager.persist(workspace1); + manager.persist(workspace2); + manager.getTransaction().commit(); + + // make conflict update + workspace2.getConfig().setName(workspace1.getConfig().getName()); + manager.getTransaction().begin(); + manager.merge(workspace2); + manager.getTransaction().commit(); + } + private long asLong(String query) { return manager.createQuery(query, Long.class).getSingleResult(); } diff --git a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/spi/tck/WorkspaceDaoTest.java b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/spi/tck/WorkspaceDaoTest.java index f4e8b32ecb..8e5a52bb9a 100644 --- a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/spi/tck/WorkspaceDaoTest.java +++ b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/spi/tck/WorkspaceDaoTest.java @@ -16,7 +16,6 @@ import com.google.common.collect.ImmutableMap; import org.eclipse.che.account.spi.AccountImpl; import org.eclipse.che.api.core.ConflictException; import org.eclipse.che.api.core.NotFoundException; -import org.eclipse.che.api.core.model.workspace.WorkspaceStatus; import org.eclipse.che.api.machine.server.model.impl.CommandImpl; import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl; import org.eclipse.che.api.workspace.server.model.impl.EnvironmentRecipeImpl; @@ -41,6 +40,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import static java.util.Arrays.asList; import static java.util.Collections.singletonMap; @@ -137,7 +137,7 @@ public class WorkspaceDaoTest { public void shouldGetWorkspaceByNameAndNamespace() throws Exception { final WorkspaceImpl workspace = workspaces[0]; - assertEquals(workspaceDao.get(workspace.getName(), workspace.getNamespace()), workspace); + assertEquals(workspaceDao.get(workspace.getConfig().getName(), workspace.getNamespace()), workspace); } @Test(expectedExceptions = NotFoundException.class) @@ -151,7 +151,7 @@ public class WorkspaceDaoTest { public void shouldThrowNotFoundExceptionWhenWorkspaceWithSuchNamespaceDoesNotExist() throws Exception { final WorkspaceImpl workspace = workspaces[0]; - workspaceDao.get(workspace.getName(), "non-existing-namespace"); + workspaceDao.get(workspace.getConfig().getName(), "non-existing-namespace"); } @Test(expectedExceptions = NotFoundException.class) @@ -159,7 +159,7 @@ public class WorkspaceDaoTest { final WorkspaceImpl workspace1 = workspaces[0]; final WorkspaceImpl workspace2 = workspaces[2]; - workspaceDao.get(workspace1.getName(), workspace2.getNamespace()); + workspaceDao.get(workspace1.getConfig().getName(), workspace2.getNamespace()); } @Test(expectedExceptions = NullPointerException.class) @@ -169,7 +169,7 @@ public class WorkspaceDaoTest { @Test(expectedExceptions = NullPointerException.class) public void shouldThrowNpeWhenGettingWorkspaceByNameAndNamespaceWhereNamespaceIsNull() throws Exception { - workspaceDao.get(workspaces[0].getName(), null); + workspaceDao.get(workspaces[0].getConfig().getName(), null); } @Test(expectedExceptions = NotFoundException.class, @@ -204,7 +204,7 @@ public class WorkspaceDaoTest { public void shouldNotCreateWorkspaceWithANameWhichAlreadyExistsInGivenNamespace() throws Exception { final WorkspaceImpl workspace = workspaces[0]; - final WorkspaceImpl newWorkspace = createWorkspace("new-id", workspace.getAccount(), workspace.getName()); + final WorkspaceImpl newWorkspace = createWorkspace("new-id", workspace.getAccount(), workspace.getConfig().getName()); workspaceDao.create(newWorkspace); } @@ -214,7 +214,7 @@ public class WorkspaceDaoTest { final WorkspaceImpl workspace = workspaces[0]; final WorkspaceImpl workspace2 = workspaces[4]; - final WorkspaceImpl newWorkspace = createWorkspace("new-id", workspace.getAccount(), workspace2.getName()); + final WorkspaceImpl newWorkspace = createWorkspace("new-id", workspace.getAccount(), workspace2.getConfig().getName()); final WorkspaceImpl expected = new WorkspaceImpl(newWorkspace, newWorkspace.getAccount()); expected.setAccount(newWorkspace.getAccount()); assertEquals(workspaceDao.create(newWorkspace), expected); @@ -231,115 +231,118 @@ public class WorkspaceDaoTest { @Test(dependsOnMethods = "shouldGetWorkspaceById") public void shouldUpdateWorkspace() throws Exception { -// final WorkspaceImpl workspace = new WorkspaceImpl(workspaces[0], workspaces[0].getAccount()); -// -// // Remove an existing project configuration from workspace -// workspace.getConfig().getProjects().remove(1); -// -// // Add new project to the workspace configuration -// final SourceStorageImpl source3 = new SourceStorageImpl(); -// source3.setType("type3"); -// source3.setLocation("location3"); -// source3.setParameters(new HashMap<>(ImmutableMap.of("param1", "value1", -// "param2", "value2", -// "param3", "value3"))); -// final ProjectConfigImpl newProjectCfg = new ProjectConfigImpl(); -// newProjectCfg.setPath("/path3"); -// newProjectCfg.setType("type3"); -// newProjectCfg.setName("project3"); -// newProjectCfg.setDescription("description3"); -// newProjectCfg.getMixins().addAll(asList("mixin3", "mixin4")); -// newProjectCfg.setSource(source3); -// newProjectCfg.getAttributes().put("new-key", asList("1", "2")); -// workspace.getConfig().getProjects().add(newProjectCfg); -// -// // Update an existing project configuration -// final ProjectConfigImpl projectCfg = workspace.getConfig().getProjects().get(0); -// projectCfg.getAttributes().clear(); -// projectCfg.getSource().setLocation("new-location"); -// projectCfg.getSource().setType("new-type"); -// projectCfg.getSource().getParameters().put("new-param", "new-param-value"); -// projectCfg.getMixins().add("new-mixin"); -// projectCfg.setPath("/new-path"); -// projectCfg.setDescription("new project description"); -// -// // Remove an existing command -// workspace.getConfig().getCommands().remove(1); -// -// // Add a new command -// final CommandImpl newCmd = new CommandImpl(); -// newCmd.setName("name3"); -// newCmd.setType("type3"); -// newCmd.setCommandLine("cmd3"); -// newCmd.getAttributes().putAll(ImmutableMap.of("attr1", "value1", -// "attr2", "value2", -// "attr3", "value3")); -// workspace.getConfig().getCommands().add(newCmd); -// -// // Update an existing command -// final CommandImpl command = workspace.getConfig().getCommands().get(0); -// command.setName("new-name"); -// command.setType("new-type"); -// command.setCommandLine("new-command-line"); -// command.getAttributes().clear(); -// -// // Remove an existing machine config -// workspace.getConfig().getEnvironments().get(0).getMachineConfigs().remove(1); -// -// // Add a new machine config -// final MachineConfigImpl newMachineCfg = new MachineConfigImpl(); -// newMachineCfg.setName("name3"); -// newMachineCfg.setDev(false); -// newMachineCfg.setType("type3"); -// newMachineCfg.setLimits(new MachineLimitsImpl(2048)); -// newMachineCfg.getEnvVariables().putAll(ImmutableMap.of("env4", "value4", -// "env5", "value5", -// "env6", "value6")); -// newMachineCfg.setServers(new ArrayList<>(singleton(new ServerConfImpl("ref", "port", "protocol", "path")))); -// newMachineCfg.setSource(new MachineSourceImpl("type", "location", "content")); -// workspace.getConfig().getEnvironments().get(0).getMachineConfigs().add(newMachineCfg); -// -// // Update an existing machine configuration -// final MachineConfigImpl machineCfg = workspace.getConfig().getEnvironments().get(0).getMachineConfigs().get(0); -// machineCfg.getEnvVariables().clear(); -// machineCfg.setType("new-type"); -// machineCfg.setName("new-name"); -// machineCfg.getLimits().setRam(512); -// machineCfg.getServers().clear(); -// machineCfg.getServers().add(new ServerConfImpl("new-ref", "new-port", "new-protocol", "new-path")); -// machineCfg.getSource().setType("new-type"); -// machineCfg.getSource().setLocation("new-location"); -// machineCfg.getSource().setContent("new-content"); -// -// // Remove an existing environment -// workspace.getConfig().getEnvironments().remove(1); -// -// // Add a new environment -// final EnvironmentImpl newEnv = new EnvironmentImpl(); -// newEnv.setName("new-env"); -// final MachineConfigImpl newEnvMachineCfg = new MachineConfigImpl(newMachineCfg); -// newEnvMachineCfg.setDev(true); -// newEnv.getMachineConfigs().add(newEnvMachineCfg); -// workspace.getConfig().getEnvironments().add(newEnv); -// -// // Update an existing environment -// final EnvironmentImpl environment = workspace.getConfig().getEnvironments().get(0); -// environment.setName("new-name"); -// -// // Update workspace configuration -// final WorkspaceConfigImpl wCfg = workspace.getConfig(); -// wCfg.setDefaultEnv(newEnv.getName()); -// wCfg.setName("new-name"); -// wCfg.setDescription("This is a new description"); -// -// // Update workspace object -// workspace.setName("new-name"); -// workspace.setAccount(new AccountImpl("accId", "new-namespace", "test")); -// workspace.getAttributes().clear(); -// -// workspaceDao.update(workspace); -// -// assertEquals(workspaceDao.get(workspace.getId()), new WorkspaceImpl(workspace, workspace.getAccount())); + final WorkspaceImpl workspace = new WorkspaceImpl(workspaces[0], workspaces[0].getAccount()); + + // Remove an existing project configuration from workspace + workspace.getConfig().getProjects().remove(1); + + // Add new project to the workspace configuration + final SourceStorageImpl source3 = new SourceStorageImpl(); + source3.setType("type3"); + source3.setLocation("location3"); + source3.setParameters(new HashMap<>(ImmutableMap.of("param1", "value1", + "param2", "value2", + "param3", "value3"))); + final ProjectConfigImpl newProjectCfg = new ProjectConfigImpl(); + newProjectCfg.setPath("/path3"); + newProjectCfg.setType("type3"); + newProjectCfg.setName("project3"); + newProjectCfg.setDescription("description3"); + newProjectCfg.getMixins().addAll(asList("mixin3", "mixin4")); + newProjectCfg.setSource(source3); + newProjectCfg.getAttributes().put("new-key", asList("1", "2")); + workspace.getConfig().getProjects().add(newProjectCfg); + + // Update an existing project configuration + final ProjectConfigImpl projectCfg = workspace.getConfig().getProjects().get(0); + projectCfg.getAttributes().clear(); + projectCfg.getSource().setLocation("new-location"); + projectCfg.getSource().setType("new-type"); + projectCfg.getSource().getParameters().put("new-param", "new-param-value"); + projectCfg.getMixins().add("new-mixin"); + projectCfg.setPath("/new-path"); + projectCfg.setDescription("new project description"); + + // Remove an existing command + workspace.getConfig().getCommands().remove(1); + + // Add a new command + final CommandImpl newCmd = new CommandImpl(); + newCmd.setName("name3"); + newCmd.setType("type3"); + newCmd.setCommandLine("cmd3"); + newCmd.getAttributes().putAll(ImmutableMap.of("attr1", "value1", + "attr2", "value2", + "attr3", "value3")); + workspace.getConfig().getCommands().add(newCmd); + + // Update an existing command + final CommandImpl command = workspace.getConfig().getCommands().get(0); + command.setName("new-name"); + command.setType("new-type"); + command.setCommandLine("new-command-line"); + command.getAttributes().clear(); + + // Add a new environment + final EnvironmentRecipeImpl newRecipe = new EnvironmentRecipeImpl(); + newRecipe.setLocation("new-location"); + newRecipe.setType("new-type"); + newRecipe.setContentType("new-content-type"); + newRecipe.setContent("new-content"); + final ExtendedMachineImpl newMachine = new ExtendedMachineImpl(); + final ServerConf2Impl serverConf1 = new ServerConf2Impl("2265", "http", singletonMap("prop1", "val")); + final ServerConf2Impl serverConf2 = new ServerConf2Impl("2266", "ftp", singletonMap("prop1", "val")); + newMachine.setServers(ImmutableMap.of("ref1", serverConf1, "ref2", serverConf2)); + newMachine.setAgents(ImmutableList.of("agent5", "agent4")); + newMachine.setAttributes(singletonMap("att1", "val")); + final EnvironmentImpl newEnv = new EnvironmentImpl(); + newEnv.setMachines(ImmutableMap.of("new-machine", newMachine)); + newEnv.setRecipe(newRecipe); + workspace.getConfig().getEnvironments().put("new-env", newEnv); + + // Update an existing environment + final EnvironmentImpl defaultEnv = workspace.getConfig().getEnvironments().get(workspace.getConfig().getDefaultEnv()); + // Remove an existing machine config + final List machineNames = new ArrayList<>(defaultEnv.getMachines().keySet()); + // Update an existing machine + final ExtendedMachineImpl existingMachine = defaultEnv.getMachines().get(machineNames.get(1)); + existingMachine.setAgents(asList("new-agent1", "new-agent2")); + existingMachine.setAttributes(ImmutableMap.of("attr1", "value1", + "attr2", "value2", + "attr3", "value3")); + existingMachine.getServers().clear(); + existingMachine.getServers().put("new-ref", new ServerConf2Impl("new-port", + "new-protocol", + ImmutableMap.of("prop1", "value"))); + defaultEnv.getMachines().remove(machineNames.get(0)); + defaultEnv.getRecipe().setContent("updated-content"); + defaultEnv.getRecipe().setContentType("updated-content-type"); + defaultEnv.getRecipe().setLocation("updated-location"); + defaultEnv.getRecipe().setType("updated-type"); + + // Remove an existing environment + final Optional nonDefaultEnv = workspace.getConfig() + .getEnvironments() + .keySet() + .stream() + .filter(key -> !key.equals(workspace.getConfig().getDefaultEnv())) + .findAny(); + assertTrue(nonDefaultEnv.isPresent()); + workspace.getConfig().getEnvironments().remove(nonDefaultEnv.get()); + + // Update workspace configuration + final WorkspaceConfigImpl wCfg = workspace.getConfig(); + wCfg.setDefaultEnv("new-env"); + wCfg.setName("new-name"); + wCfg.setDescription("This is a new description"); + + // Update workspace object + workspace.setAccount(new AccountImpl("accId", "new-namespace", "test")); + workspace.getAttributes().clear(); + + workspaceDao.update(workspace); + + assertEquals(workspaceDao.get(workspace.getId()), new WorkspaceImpl(workspace, workspace.getAccount())); } @Test(expectedExceptions = NotFoundException.class) @@ -355,7 +358,7 @@ public class WorkspaceDaoTest { final WorkspaceImpl workspace1 = workspaces[0]; final WorkspaceImpl workspace2 = workspaces[1]; - workspace1.setName(workspace2.getName()); + workspace1.getConfig().setName(workspace2.getConfig().getName()); workspaceDao.update(workspace1); } @@ -453,7 +456,7 @@ public class WorkspaceDaoTest { recipe2.setContent("content"); final EnvironmentImpl env2 = new EnvironmentImpl(); env2.setMachines(new HashMap<>(ImmutableMap.of("machine1", exMachine1, - "machine3", exMachine3))); + "machine3", exMachine3))); env2.setRecipe(recipe2); final Map environments = ImmutableMap.of("env1", env1, "env2", env2); @@ -473,10 +476,11 @@ public class WorkspaceDaoTest { final WorkspaceConfigImpl wCfg = createWorkspaceConfig(name); // Workspace final WorkspaceImpl workspace = new WorkspaceImpl(); - workspace.setStatus(WorkspaceStatus.STOPPED); workspace.setId(id); workspace.setAccount(account); - workspace.setName(name); + final WorkspaceConfigImpl cfg = new WorkspaceConfigImpl(); + cfg.setName(name); + workspace.setConfig(cfg); workspace.setAttributes(new HashMap<>(ImmutableMap.of("attr1", "value1", "attr2", "value2", "attr3", "value3"))); diff --git a/wsmaster/wsmaster-local/src/main/java/org/eclipse/che/api/local/LocalDataMigrator.java b/wsmaster/wsmaster-local/src/main/java/org/eclipse/che/api/local/LocalDataMigrator.java index fca166c185..3cf889e453 100644 --- a/wsmaster/wsmaster-local/src/main/java/org/eclipse/che/api/local/LocalDataMigrator.java +++ b/wsmaster/wsmaster-local/src/main/java/org/eclipse/che/api/local/LocalDataMigrator.java @@ -363,7 +363,7 @@ public class LocalDataMigrator { @Override public void migrate(WorkspaceImpl entity) throws Exception { entity.setAccount(userDao.getByName(entity.getNamespace()).getAccount()); - entity.setName(entity.getConfig().getName()); + entity.getConfig().setName(entity.getConfig().getName()); workspaceDao.create(entity); } diff --git a/wsmaster/wsmaster-local/src/main/java/org/eclipse/che/api/local/LocalWorkspaceDaoImpl.java b/wsmaster/wsmaster-local/src/main/java/org/eclipse/che/api/local/LocalWorkspaceDaoImpl.java index 00eaee5498..b5d0970067 100644 --- a/wsmaster/wsmaster-local/src/main/java/org/eclipse/che/api/local/LocalWorkspaceDaoImpl.java +++ b/wsmaster/wsmaster-local/src/main/java/org/eclipse/che/api/local/LocalWorkspaceDaoImpl.java @@ -89,7 +89,7 @@ public class LocalWorkspaceDaoImpl implements WorkspaceDao { if (workspaces.containsKey(workspace.getId())) { throw new ConflictException("Workspace with id " + workspace.getId() + " already exists"); } - if (find(workspace.getName(), workspace.getNamespace()).isPresent()) { + if (find(workspace.getConfig().getName(), workspace.getNamespace()).isPresent()) { throw new ConflictException(format("Workspace with name %s and owner %s already exists", workspace.getConfig().getName(), workspace.getNamespace())); @@ -109,7 +109,7 @@ public class LocalWorkspaceDaoImpl implements WorkspaceDao { if (!workspaces.containsKey(workspace.getId())) { throw new NotFoundException("Workspace with id " + workspace.getId() + " was not found"); } - if (find(workspace.getName(), workspace.getNamespace()).isPresent()) { + if (find(workspace.getConfig().getName(), workspace.getNamespace()).isPresent()) { throw new ConflictException(format("Workspace with name %s and owner %s already exists", workspace.getConfig().getName(), workspace.getNamespace())); diff --git a/wsmaster/wsmaster-local/src/test/java/org/eclipse/che/api/local/LocalDataMigratorTest.java b/wsmaster/wsmaster-local/src/test/java/org/eclipse/che/api/local/LocalDataMigratorTest.java index 05f1f6b104..92f204f063 100644 --- a/wsmaster/wsmaster-local/src/test/java/org/eclipse/che/api/local/LocalDataMigratorTest.java +++ b/wsmaster/wsmaster-local/src/test/java/org/eclipse/che/api/local/LocalDataMigratorTest.java @@ -54,6 +54,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Map; +import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; @@ -225,7 +226,12 @@ public class LocalDataMigratorTest { final ProfileImpl profile = new ProfileImpl(user.getId()); final Map prefs = singletonMap("key", "value"); final SshPairImpl sshPair = new SshPairImpl(user.getId(), "service", "name", "public", "private"); - final WorkspaceImpl workspace = new WorkspaceImpl("id", user.getAccount(), new WorkspaceConfigImpl()); + final WorkspaceImpl workspace = new WorkspaceImpl("id", user.getAccount(), new WorkspaceConfigImpl("name", + "description", + "env", + emptyList(), + emptyList(), + emptyMap())); final SnapshotImpl snapshot = new SnapshotImpl(); snapshot.setId("snapshotId"); snapshot.setWorkspaceId(workspace.getId());