+ *
+ * @author Yevhenii Voevodin
+ */
+@Singleton
+public class GuiceEntityListenerInjectionManager implements EntityListenerInjectionManager {
+
+ @Inject
+ private Injector injector;
+
+ @Override
+ public Object createEntityListenerAndInjectDependancies(Class entityListenerClass) throws NamingException {
+ try {
+ return injector.getInstance(entityListenerClass);
+ } catch (RuntimeException x) {
+ throw new NamingException(x.getLocalizedMessage());
+ }
+ }
+
+ @Override
+ public void cleanUp(AbstractSession session) {
+ // EntityListener objects are managed by Guice, nothing to cleanup
+ }
+}
diff --git a/core/che-core-api-jdbc/src/main/java/org/eclipse/che/api/core/jdbc/jpa/guice/JpaInitializer.java b/core/che-core-api-jdbc/src/main/java/org/eclipse/che/api/core/jdbc/jpa/guice/JpaInitializer.java
new file mode 100644
index 0000000000..9686210ba9
--- /dev/null
+++ b/core/che-core-api-jdbc/src/main/java/org/eclipse/che/api/core/jdbc/jpa/guice/JpaInitializer.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.core.jdbc.jpa.guice;
+
+import com.google.inject.Inject;
+import com.google.inject.persist.PersistService;
+
+/**
+ * Should be bound as eager singleton.
+ * See doc
+ *
+ * @author Yevhenii Voevodin
+ */
+public class JpaInitializer {
+
+ @Inject
+ public JpaInitializer(PersistService persistService) {
+ persistService.start();
+ }
+}
diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Action.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Action.java
new file mode 100644
index 0000000000..0a9331b2b7
--- /dev/null
+++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Action.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.core.model.factory;
+
+import java.util.Map;
+
+/**
+ * Defines the contract for the factory action instance.
+ *
+ * @author Anton Korneta
+ */
+public interface Action {
+
+ /**
+ * Returns the IDE specific identifier of action e.g. ('openFile', 'editFile')
+ */
+ String getId();
+
+ /**
+ * Returns properties of this action instance
+ */
+ Map getProperties();
+}
diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Author.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Author.java
new file mode 100644
index 0000000000..ef9f5062ff
--- /dev/null
+++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Author.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.core.model.factory;
+
+/**
+ * Defines the contract for the factory creator instance.
+ *
+ * @author Anton Korneta
+ */
+public interface Author {
+
+ /**
+ * Identifier of the user who created factory, it is mandatory
+ */
+ String getUserId();
+
+ /**
+ * Creation time of factory, set by the server (in milliseconds, from Unix epoch, no timezone)
+ */
+ Long getCreated();
+}
diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Button.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Button.java
new file mode 100644
index 0000000000..74a9b76351
--- /dev/null
+++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Button.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.core.model.factory;
+
+/**
+ * Defines factory button.
+ *
+ * @author Anton Korneta
+ */
+public interface Button {
+
+ enum Type {
+ LOGO {
+ @Override
+ public String toString() {
+ return "logo";
+ }
+ },
+ NOLOGO {
+ @Override
+ public String toString() {
+ return "nologo";
+ }
+ };
+
+ public static Type getIgnoreCase(String name) {
+ for (Type type : values()) {
+ if (name.equalsIgnoreCase(type.toString())) {
+ return type;
+ }
+ }
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Returns type of this button instance
+ */
+ Type getType();
+
+ /**
+ * Returns attributes of this button instance
+ */
+ ButtonAttributes getAttributes();
+}
diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/ButtonAttributes.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/ButtonAttributes.java
new file mode 100644
index 0000000000..e85bfdbe85
--- /dev/null
+++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/ButtonAttributes.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.core.model.factory;
+
+/**
+ * Defines factory button attributes.
+ *
+ * @author Anton Korneta
+ */
+public interface ButtonAttributes {
+
+ /**
+ * Returns factory button color
+ */
+ String getColor();
+
+ /**
+ * Returns factory button counter
+ */
+ Boolean getCounter();
+
+ /**
+ * Returns factory button logo
+ */
+ String getLogo();
+
+ /**
+ * Returns factory button style
+ */
+ String getStyle();
+}
diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Factory.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Factory.java
new file mode 100644
index 0000000000..ca463426b0
--- /dev/null
+++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Factory.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.core.model.factory;
+
+import org.eclipse.che.api.core.model.workspace.WorkspaceConfig;
+
+/**
+ * Defines the contract for the factory instance.
+ *
+ * @author Anton Korneta
+ */
+public interface Factory {
+
+ /**
+ * Returns the identifier of this factory instance,
+ * it is mandatory and unique.
+ */
+ String getId();
+
+ /**
+ * Returns the version of this factory instance,
+ * it is mandatory.
+ */
+ String getV();
+
+ /**
+ * Returns a name of this factory instance,
+ * the name is unique for creator.
+ */
+ String getName();
+
+ /**
+ * Returns creator of this factory instance.
+ */
+ Author getCreator();
+
+ /**
+ * Returns a workspace configuration of this factory instance,
+ * it is mandatory for every factory instance.
+ */
+ WorkspaceConfig getWorkspace();
+
+ /**
+ * Returns restrictions of this factory instance.
+ */
+ Policies getPolicies();
+
+ /**
+ * Returns factory button for this instance.
+ */
+ Button getButton();
+
+ /**
+ * Returns IDE for this factory instance.
+ */
+ Ide getIde();
+}
diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Ide.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Ide.java
new file mode 100644
index 0000000000..71379727d5
--- /dev/null
+++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Ide.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.core.model.factory;
+
+/**
+ * Defines the contract for the factory IDE instance.
+ *
+ * @author Anton Korneta
+ */
+public interface Ide {
+
+ /**
+ * Returns configuration of IDE on application loaded event
+ */
+ OnAppLoaded getOnAppLoaded();
+
+ /**
+ * Returns configuration of IDE on application closed event
+ */
+ OnAppClosed getOnAppClosed();
+
+ /**
+ * Returns configuration of IDE on projects loaded event
+ */
+ OnProjectsLoaded getOnProjectsLoaded();
+}
diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/OnAppClosed.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/OnAppClosed.java
new file mode 100644
index 0000000000..c79dae836b
--- /dev/null
+++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/OnAppClosed.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.core.model.factory;
+
+import java.util.List;
+
+/**
+ * Defines IDE look and feel on application closed event.
+ *
+ * @author Anton Korneta
+ */
+public interface OnAppClosed {
+
+ /**
+ * Returns actions for current event.
+ */
+ List extends Action> getActions();
+}
diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/OnAppLoaded.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/OnAppLoaded.java
new file mode 100644
index 0000000000..e2965ff7c8
--- /dev/null
+++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/OnAppLoaded.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.core.model.factory;
+
+import java.util.List;
+
+/**
+ * Defines IDE look and feel on application loaded event.
+ *
+ * @author Anton Korneta
+ */
+public interface OnAppLoaded {
+
+ /**
+ * Returns actions for current event.
+ */
+ List extends Action> getActions();
+}
diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/OnProjectsLoaded.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/OnProjectsLoaded.java
new file mode 100644
index 0000000000..438bc89ea6
--- /dev/null
+++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/OnProjectsLoaded.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.core.model.factory;
+
+import java.util.List;
+
+/**
+ * Defines IDE look and feel on project opened event.
+ *
+ * @author Anton Korneta
+ */
+public interface OnProjectsLoaded {
+
+ /**
+ * Returns actions for current event.
+ */
+ List extends Action> getActions();
+}
diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Policies.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Policies.java
new file mode 100644
index 0000000000..e5e54affed
--- /dev/null
+++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/factory/Policies.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.core.model.factory;
+
+/**
+ * Defines the contract for the factory restrictions.
+ *
+ * @author Anton Korneta
+ */
+public interface Policies {
+
+ /**
+ * Restrict access if referer header doesn't match this field
+ */
+ String getReferer();
+
+ /**
+ * Restrict access for factories used earlier then author supposes
+ */
+ Long getSince();
+
+ /**
+ * Restrict access for factories used later then author supposes
+ */
+ Long getUntil();
+
+ /**
+ * Re-open projects on factory 2-nd click
+ */
+ String getMatch();
+
+ /**
+ * Workspace creation strategy
+ */
+ String getCreate();
+}
diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/machine/Snapshot.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/machine/Snapshot.java
index fe3ab10fed..f87bacf11c 100644
--- a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/machine/Snapshot.java
+++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/machine/Snapshot.java
@@ -28,12 +28,6 @@ public interface Snapshot {
*/
String getType();
- /**
- * Snapshot namespace, which allows snapshot to be
- * related to the certain workspace machine.
- */
- String getNamespace();
-
/**
* Creation date of the snapshot
*/
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 b8460e53d2..9ce8041fc5 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,6 +36,12 @@ 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 8ae987457a..beb0e2c12a 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,7 +26,11 @@ import java.util.Map;
public interface WorkspaceConfig {
/**
- * Returns workspace name.
+ * 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.
*/
String getName();
diff --git a/core/commons/che-core-commons-test/pom.xml b/core/commons/che-core-commons-test/pom.xml
index 66b588ce32..e9a5ecc115 100644
--- a/core/commons/che-core-commons-test/pom.xml
+++ b/core/commons/che-core-commons-test/pom.xml
@@ -43,10 +43,20 @@
guiceprovided
+
+ com.google.inject.extensions
+ guice-persist
+ provided
+ javax.injectjavax.injectprovided
+
+ org.eclipse.persistence
+ javax.persistence
+ provided
+
diff --git a/core/commons/che-core-commons-test/src/main/java/org/eclipse/che/commons/test/tck/AbstractTestListener.java b/core/commons/che-core-commons-test/src/main/java/org/eclipse/che/commons/test/tck/AbstractTestListener.java
new file mode 100644
index 0000000000..a02e977a23
--- /dev/null
+++ b/core/commons/che-core-commons-test/src/main/java/org/eclipse/che/commons/test/tck/AbstractTestListener.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.commons.test.tck;
+
+import org.testng.ITestContext;
+import org.testng.ITestListener;
+import org.testng.ITestResult;
+
+/**
+ * Skeletal implementation of the {@link ITestListener}.
+ * In most cases only 2 methods are needed {@link #onStart(ITestContext)} and {@link #onFinish(ITestContext)}.
+ *
+ * @author Yevhenii Voevodin
+ */
+public abstract class AbstractTestListener implements ITestListener {
+
+ @Override
+ public void onTestStart(ITestResult result) {}
+
+ @Override
+ public void onTestSuccess(ITestResult result) {}
+
+ @Override
+ public void onTestFailure(ITestResult result) {}
+
+ @Override
+ public void onTestSkipped(ITestResult result) {}
+
+ @Override
+ public void onTestFailedButWithinSuccessPercentage(ITestResult result) {}
+
+ @Override
+ public void onStart(ITestContext context) {}
+
+ @Override
+ public void onFinish(ITestContext context) {}
+}
diff --git a/core/commons/che-core-commons-test/src/main/java/org/eclipse/che/commons/test/tck/repository/JpaTckRepository.java b/core/commons/che-core-commons-test/src/main/java/org/eclipse/che/commons/test/tck/repository/JpaTckRepository.java
new file mode 100644
index 0000000000..3f2eecff4b
--- /dev/null
+++ b/core/commons/che-core-commons-test/src/main/java/org/eclipse/che/commons/test/tck/repository/JpaTckRepository.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.commons.test.tck.repository;
+
+import com.google.inject.Inject;
+import com.google.inject.persist.UnitOfWork;
+
+import javax.inject.Provider;
+import javax.persistence.Entity;
+import javax.persistence.EntityManager;
+import java.util.Collection;
+
+import static java.lang.String.format;
+
+/**
+ * Simplifies implementation for Jpa repository in general case.
+ *
+ * Expected usage:
+ *
+ *
+ * @param
+ * type of the entity
+ * @author Yevhenii Voevodin
+ */
+public class JpaTckRepository implements TckRepository {
+
+ @Inject
+ protected Provider managerProvider;
+
+ @Inject
+ protected UnitOfWork uow;
+
+ private final Class entityClass;
+
+ public JpaTckRepository(Class entityClass) {
+ this.entityClass = entityClass;
+ }
+
+ @Override
+ public void createAll(Collection extends T> entities) throws TckRepositoryException {
+ uow.begin();
+ final EntityManager manager = managerProvider.get();
+ try {
+ manager.getTransaction().begin();
+ entities.forEach(manager::persist);
+ manager.getTransaction().commit();
+ } catch (RuntimeException x) {
+ if (manager.getTransaction().isActive()) {
+ manager.getTransaction().rollback();
+ }
+ throw new TckRepositoryException(x.getLocalizedMessage(), x);
+ } finally {
+ uow.end();
+ }
+ }
+
+ @Override
+ public void removeAll() throws TckRepositoryException {
+ uow.begin();
+ final EntityManager manager = managerProvider.get();
+ try {
+ manager.getTransaction().begin();
+ // The query 'DELETE FROM Entity' won't be correct as it will ignore orphanRemoval
+ // and may also ignore some configuration options, while EntityManager#remove won't
+ manager.createQuery(format("SELECT e FROM %s e", getEntityName(entityClass)), entityClass)
+ .getResultList()
+ .forEach(manager::remove);
+ manager.getTransaction().commit();
+ } catch (RuntimeException x) {
+ if (manager.getTransaction().isActive()) {
+ manager.getTransaction().rollback();
+ }
+ throw new TckRepositoryException(x.getLocalizedMessage(), x);
+ } finally {
+ uow.end();
+ }
+ }
+
+ private String getEntityName(Class> clazz) {
+ if (!clazz.isAnnotationPresent(Entity.class)) {
+ return clazz.getSimpleName();
+ }
+ final Entity entity = clazz.getAnnotation(Entity.class);
+ if (entity.name().isEmpty()) {
+ return clazz.getSimpleName();
+ }
+ return entity.name();
+ }
+}
diff --git a/core/commons/che-core-commons-test/src/test/java/org/eclipse/che/commons/test/tck/DBServerListener.java b/core/commons/che-core-commons-test/src/test/java/org/eclipse/che/commons/test/tck/DBServerListener.java
index fa4f585f74..9930b24a4f 100644
--- a/core/commons/che-core-commons-test/src/test/java/org/eclipse/che/commons/test/tck/DBServerListener.java
+++ b/core/commons/che-core-commons-test/src/test/java/org/eclipse/che/commons/test/tck/DBServerListener.java
@@ -20,7 +20,7 @@ import org.testng.ITestResult;
*
* @author Yevhenii Voevodin
*/
-public class DBServerListener implements ITestListener {
+public class DBServerListener extends AbstractTestListener {
public static final String DB_SERVER_URL_ATTRIBUTE_NAME = "db_server_url";
public static final String DB_SERVER_URL = "localhost:12345";
@@ -29,22 +29,4 @@ public class DBServerListener implements ITestListener {
public void onStart(ITestContext context) {
context.setAttribute(DB_SERVER_URL_ATTRIBUTE_NAME, DB_SERVER_URL);
}
-
- @Override
- public void onFinish(ITestContext context) {}
-
- @Override
- public void onTestStart(ITestResult result) {}
-
- @Override
- public void onTestSuccess(ITestResult result) {}
-
- @Override
- public void onTestFailure(ITestResult result) {}
-
- @Override
- public void onTestSkipped(ITestResult result) {}
-
- @Override
- public void onTestFailedButWithinSuccessPercentage(ITestResult result) {}
}
diff --git a/core/pom.xml b/core/pom.xml
index aa1b3e881d..3e92509a16 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -30,5 +30,7 @@
che-core-api-dto-maven-pluginche-core-api-coreche-core-api-model
+ che-core-api-jdbc
+ che-core-api-jdbc-vendor-h2
diff --git a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/app/AppContext.java b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/app/AppContext.java
index 5e7a97bbb9..35fe132bef 100644
--- a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/app/AppContext.java
+++ b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/app/AppContext.java
@@ -12,7 +12,8 @@ package org.eclipse.che.ide.api.app;
import com.google.common.annotations.Beta;
-import org.eclipse.che.api.factory.shared.dto.Factory;
+import org.eclipse.che.api.core.model.factory.Factory;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto;
import org.eclipse.che.ide.api.machine.DevMachine;
import org.eclipse.che.ide.api.resources.Container;
@@ -175,12 +176,15 @@ public interface AppContext {
void setStartUpActions(List startUpActions);
/**
- * Returns {@link Factory} instance which id was set on startup, or {@code null} if no factory was specified.
+ * Returns {@link Factory} instance which id was set on startup,
+ * or {@code null} if no factory was specified.
*
* @return loaded factory or {@code null}
*/
- Factory getFactory();
+ FactoryDto getFactory();
+ void setFactory(FactoryDto factory);
+
String getWorkspaceId();
/* Deprecated methods */
diff --git a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/factory/FactoryAcceptedEvent.java b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/factory/FactoryAcceptedEvent.java
index 2535f6459c..86163dfbd1 100644
--- a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/factory/FactoryAcceptedEvent.java
+++ b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/factory/FactoryAcceptedEvent.java
@@ -12,7 +12,7 @@ package org.eclipse.che.ide.api.factory;
import com.google.gwt.event.shared.GwtEvent;
-import org.eclipse.che.api.factory.shared.dto.Factory;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
/**
@@ -22,9 +22,9 @@ import org.eclipse.che.api.factory.shared.dto.Factory;
*/
public class FactoryAcceptedEvent extends GwtEvent {
- private Factory factory;
+ private FactoryDto factory;
- public FactoryAcceptedEvent(Factory factory) {
+ public FactoryAcceptedEvent(FactoryDto factory) {
this.factory = factory;
}
@@ -41,7 +41,7 @@ public class FactoryAcceptedEvent extends GwtEvent {
}
- public Factory getFactory() {
+ public FactoryDto getFactory() {
return factory;
}
}
diff --git a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/factory/FactoryServiceClient.java b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/factory/FactoryServiceClient.java
index 37e0a5a61b..5e33a86fd3 100644
--- a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/factory/FactoryServiceClient.java
+++ b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/factory/FactoryServiceClient.java
@@ -10,7 +10,7 @@
*******************************************************************************/
package org.eclipse.che.ide.api.factory;
-import org.eclipse.che.api.factory.shared.dto.Factory;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.ide.rest.AsyncRequestCallback;
@@ -36,7 +36,7 @@ public interface FactoryServiceClient {
* indicates whether or not factory should be validated by accept validator
* @return Factory through a Promise
*/
- Promise getFactory(@NotNull String factoryId, boolean validate);
+ Promise getFactory(@NotNull String factoryId, boolean validate);
/**
* @param factoryId
@@ -58,7 +58,7 @@ public interface FactoryServiceClient {
* @param callback
* callback which returns snippet of the factory or exception if occurred
*/
- void getFactoryJson(@NotNull String workspaceId, @NotNull String path, @NotNull AsyncRequestCallback callback);
+ void getFactoryJson(@NotNull String workspaceId, @NotNull String path, @NotNull AsyncRequestCallback callback);
/**
* Get factory as JSON.
@@ -67,18 +67,18 @@ public interface FactoryServiceClient {
* workspace id
* @param path
* project path
- * @return a promise that resolves to the {@link Factory}, or rejects with an error
+ * @return a promise that resolves to the {@link FactoryDto}, or rejects with an error
*/
- Promise getFactoryJson(@NotNull String workspaceId, @Nullable String path);
+ Promise getFactoryJson(@NotNull String workspaceId, @Nullable String path);
/**
* Save factory to storage.
*
* @param factory
* factory to save
- * @return a promise that resolves to the {@link Factory}, or rejects with an error
+ * @return a promise that resolves to the {@link FactoryDto}, or rejects with an error
*/
- Promise saveFactory(@NotNull Factory factory);
+ Promise saveFactory(@NotNull FactoryDto factory);
/**
* Save factory to storage.
@@ -87,9 +87,9 @@ public interface FactoryServiceClient {
* the number of the items to skip
* @param maxItems
* the limit of the items in the response, default is 30
- * @return a promise that will provide a list of {@link Factory}s, or rejects with an error
+ * @return a promise that will provide a list of {@link FactoryDto}s, or rejects with an error
*/
- Promise> findFactory(Integer skipCount, Integer maxItems, List> params);
+ Promise> findFactory(Integer skipCount, Integer maxItems, List> params);
/**
* Updates factory by id
@@ -100,7 +100,7 @@ public interface FactoryServiceClient {
* update body
* @return updated factory
*/
- Promise updateFactory(String id, Factory factory);
+ Promise updateFactory(String id, FactoryDto factory);
/**
@@ -112,6 +112,6 @@ public interface FactoryServiceClient {
* indicates whether or not factory should be validated by accept validator
* @return Factory through a Promise
*/
- Promise resolveFactory(@NotNull Map factoryParameters, boolean validate);
+ Promise resolveFactory(@NotNull Map factoryParameters, boolean validate);
}
diff --git a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/factory/FactoryServiceClientImpl.java b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/factory/FactoryServiceClientImpl.java
index 46b1500bcf..bf4fc540eb 100644
--- a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/factory/FactoryServiceClientImpl.java
+++ b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/factory/FactoryServiceClientImpl.java
@@ -15,7 +15,7 @@ import com.google.gwt.http.client.RequestBuilder;
import com.google.inject.Inject;
import com.google.inject.Singleton;
-import org.eclipse.che.api.factory.shared.dto.Factory;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.ide.MimeType;
@@ -68,13 +68,13 @@ public class FactoryServiceClientImpl implements FactoryServiceClient {
* @return Factory through a Promise
*/
@Override
- public Promise getFactory(@NotNull String factoryId, boolean validate) {
+ public Promise getFactory(@NotNull String factoryId, boolean validate) {
StringBuilder url = new StringBuilder(API_FACTORY_BASE_URL).append(factoryId);
if (validate) {
url.append("?").append("validate=true");
}
return asyncRequestFactory.createGetRequest(url.toString()).header(HTTPHeader.ACCEPT, MimeType.APPLICATION_JSON)
- .send(unmarshallerFactory.newUnmarshaller(Factory.class));
+ .send(unmarshallerFactory.newUnmarshaller(FactoryDto.class));
}
/**
@@ -90,7 +90,7 @@ public class FactoryServiceClientImpl implements FactoryServiceClient {
* {@inheritDoc}
*/
@Override
- public void getFactoryJson(String workspaceId, String path, AsyncRequestCallback callback) {
+ public void getFactoryJson(String workspaceId, String path, AsyncRequestCallback callback) {
final StringBuilder url = new StringBuilder(API_FACTORY_BASE_URL + "workspace/").append(workspaceId);
if (path != null) {
url.append("?path=").append(path);
@@ -102,7 +102,7 @@ public class FactoryServiceClientImpl implements FactoryServiceClient {
}
@Override
- public Promise getFactoryJson(String workspaceId, String path) {
+ public Promise getFactoryJson(String workspaceId, String path) {
String url = API_FACTORY_BASE_URL + "workspace/" + workspaceId;
if (path != null) {
url += path;
@@ -111,20 +111,20 @@ public class FactoryServiceClientImpl implements FactoryServiceClient {
return asyncRequestFactory.createGetRequest(url)
.header(HTTPHeader.ACCEPT, MimeType.APPLICATION_JSON)
.loader(loaderFactory.newLoader("Getting info about factory..."))
- .send(unmarshallerFactory.newUnmarshaller(Factory.class));
+ .send(unmarshallerFactory.newUnmarshaller(FactoryDto.class));
}
@Override
- public Promise saveFactory(@NotNull Factory factory) {
+ public Promise saveFactory(@NotNull FactoryDto factory) {
return asyncRequestFactory.createPostRequest(API_FACTORY_BASE_URL, factory)
.header(HTTPHeader.ACCEPT, MimeType.APPLICATION_JSON)
.header(HTTPHeader.CONTENT_TYPE, MimeType.APPLICATION_JSON)
.loader(loaderFactory.newLoader("Creating factory..."))
- .send(unmarshallerFactory.newUnmarshaller(Factory.class));
+ .send(unmarshallerFactory.newUnmarshaller(FactoryDto.class));
}
@Override
- public Promise> findFactory(@Nullable Integer skipCount,
+ public Promise> findFactory(@Nullable Integer skipCount,
@Nullable Integer maxItems,
@Nullable List> params) {
final List> allParams = new LinkedList<>();
@@ -141,15 +141,15 @@ public class FactoryServiceClientImpl implements FactoryServiceClient {
.header(HTTPHeader.ACCEPT, MimeType.APPLICATION_JSON)
.header(HTTPHeader.CONTENT_TYPE, MimeType.APPLICATION_JSON)
.loader(loaderFactory.newLoader("Searching factory..."))
- .send(unmarshallerFactory.newListUnmarshaller(Factory.class));
+ .send(unmarshallerFactory.newListUnmarshaller(FactoryDto.class));
}
@Override
- public Promise updateFactory(String id, Factory factory) {
+ public Promise updateFactory(String id, FactoryDto factory) {
return asyncRequestFactory.createRequest(RequestBuilder.PUT, API_FACTORY_BASE_URL + id, factory, false)
.header(HTTPHeader.CONTENT_TYPE, MimeType.APPLICATION_JSON)
.loader(loaderFactory.newLoader("Updating factory..."))
- .send(unmarshallerFactory.newUnmarshaller(Factory.class));
+ .send(unmarshallerFactory.newUnmarshaller(FactoryDto.class));
}
@@ -163,7 +163,7 @@ public class FactoryServiceClientImpl implements FactoryServiceClient {
* @return Factory through a Promise
*/
@Override
- public Promise resolveFactory(@NotNull final Map factoryParameters, boolean validate) {
+ public Promise resolveFactory(@NotNull final Map factoryParameters, boolean validate) {
// Init string with JAX-RS path
StringBuilder url = new StringBuilder(API_FACTORY_BASE_URL + "resolver");
@@ -173,7 +173,7 @@ public class FactoryServiceClientImpl implements FactoryServiceClient {
url.append("?validate=true");
}
return asyncRequestFactory.createPostRequest(url.toString(), toJson(factoryParameters)).header(ACCEPT, APPLICATION_JSON)
- .send(unmarshallerFactory.newUnmarshaller(Factory.class));
+ .send(unmarshallerFactory.newUnmarshaller(FactoryDto.class));
}
/**
diff --git a/ide/che-core-ide-api/src/main/resources/org/eclipse/che/api/core/model/Model.gwt.xml b/ide/che-core-ide-api/src/main/resources/org/eclipse/che/api/core/model/Model.gwt.xml
index dab00cbbdc..6ae4f496d1 100644
--- a/ide/che-core-ide-api/src/main/resources/org/eclipse/che/api/core/model/Model.gwt.xml
+++ b/ide/che-core-ide-api/src/main/resources/org/eclipse/che/api/core/model/Model.gwt.xml
@@ -18,6 +18,7 @@
+
diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/context/AppContextImpl.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/context/AppContextImpl.java
index bd5f441458..2028dc6a2d 100644
--- a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/context/AppContextImpl.java
+++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/context/AppContextImpl.java
@@ -16,7 +16,7 @@ import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.web.bindery.event.shared.EventBus;
-import org.eclipse.che.api.factory.shared.dto.Factory;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.api.promises.client.Operation;
import org.eclipse.che.api.promises.client.OperationException;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceDto;
@@ -82,11 +82,11 @@ public class AppContextImpl implements AppContext,
private final BrowserQueryFieldRenderer browserQueryFieldRenderer;
private final List projectsInImport;
- private WorkspaceDto usersWorkspaceDto;
- private CurrentUser currentUser;
- private Factory factory;
- private DevMachine devMachine;
- private Path projectsRoot;
+ private WorkspaceDto usersWorkspaceDto;
+ private CurrentUser currentUser;
+ private FactoryDto factory;
+ private DevMachine devMachine;
+ private Path projectsRoot;
/**
* List of actions with parameters which comes from startup URL.
* Can be processed after IDE initialization as usual after starting ws-agent.
@@ -170,11 +170,12 @@ public class AppContextImpl implements AppContext,
}
@Override
- public Factory getFactory() {
+ public FactoryDto getFactory() {
return factory;
}
- public void setFactory(Factory factory) {
+ @Override
+ public void setFactory(FactoryDto factory) {
this.factory = factory;
}
diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/FactoryWorkspaceComponent.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/FactoryWorkspaceComponent.java
index cc81cd8e79..c8be4b30a3 100644
--- a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/FactoryWorkspaceComponent.java
+++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/FactoryWorkspaceComponent.java
@@ -17,7 +17,7 @@ import com.google.inject.Singleton;
import com.google.web.bindery.event.shared.EventBus;
import org.eclipse.che.api.core.model.workspace.WorkspaceStatus;
-import org.eclipse.che.api.factory.shared.dto.Factory;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.api.promises.client.Function;
import org.eclipse.che.api.promises.client.FunctionException;
import org.eclipse.che.api.promises.client.Operation;
@@ -119,7 +119,7 @@ public class FactoryWorkspaceComponent extends WorkspaceComponent {
// get workspace ID to use dedicated workspace for this factory
this.workspaceId = browserQueryFieldRenderer.getParameterFromURLByName("workspaceId");
- Promise factoryPromise;
+ Promise factoryPromise;
// now search if it's a factory based on id or from parameters
if (factoryParameters.containsKey("id")) {
factoryPromise = factoryServiceClient.getFactory(factoryParameters.get("id"), true);
@@ -127,9 +127,10 @@ public class FactoryWorkspaceComponent extends WorkspaceComponent {
factoryPromise = factoryServiceClient.resolveFactory(factoryParameters, true);
}
- factoryPromise.then(new Function() {
+ Promise promise = factoryPromise.then(new Function() {
@Override
- public Void apply(final Factory factory) throws FunctionException {
+ public Void apply(final FactoryDto factory) throws FunctionException {
+
if (appContext instanceof AppContextImpl) {
((AppContextImpl)appContext).setFactory(factory);
}
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 9cb7b9d942..380b36bdd7 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,6 +25,7 @@ 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;
@@ -32,8 +33,10 @@ public class WorkspaceImpl implements Workspace {
private final boolean temporary;
private final WorkspaceConfig config;
+
public WorkspaceImpl(Workspace workspace) {
id = workspace.getId();
+ name = workspace.getName();
workspaceRuntime = workspace.getRuntime();
namespace = workspace.getNamespace();
status = workspace.getStatus();
@@ -53,6 +56,11 @@ public class WorkspaceImpl implements Workspace {
return namespace;
}
+ @Override
+ public String getName() {
+ return name;
+ }
+
@Override
public WorkspaceStatus getStatus() {
return status;
diff --git a/ide/che-core-ide-stacks/src/main/resources/stacks.json b/ide/che-core-ide-stacks/src/main/resources/stacks.json
index cafdaafec6..e57e85331c 100644
--- a/ide/che-core-ide-stacks/src/main/resources/stacks.json
+++ b/ide/che-core-ide-stacks/src/main/resources/stacks.json
@@ -63,14 +63,6 @@
}
]
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-java-mysql.svg",
"mediaType": "image/svg+xml"
@@ -163,14 +155,6 @@
]
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-che.svg",
"mediaType": "image/svg+xml"
@@ -240,14 +224,6 @@
}
]
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-java.svg",
"mediaType": "image/svg+xml"
@@ -294,14 +270,6 @@
"defaultEnv": "default",
"description": null
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-blank.svg",
"mediaType": "image/svg+xml"
@@ -367,14 +335,6 @@
}
]
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-android.svg",
"mediaType": "image/svg+xml"
@@ -442,14 +402,6 @@
}
]
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-cpp.svg",
"mediaType": "image/svg+xml"
@@ -522,14 +474,6 @@
}
]
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-dotnet.svg",
"mediaType": "image/svg+xml"
@@ -593,14 +537,6 @@
}
]
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-go.svg",
"mediaType": "image/svg+xml"
@@ -660,14 +596,6 @@
"defaultEnv": "default",
"description": null
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-hadoop.svg",
"mediaType": "image/svg+xml"
@@ -745,14 +673,6 @@
"defaultEnv": "default",
"description": null
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-node.svg",
"mediaType": "image/svg+xml"
@@ -849,14 +769,6 @@
}
]
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-php.svg",
"mediaType": "image/svg+xml"
@@ -922,14 +834,6 @@
}
]
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-python.svg",
"mediaType": "image/svg+xml"
@@ -1008,14 +912,6 @@
}
]
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-ruby.svg",
"mediaType": "image/svg+xml"
@@ -1063,15 +959,7 @@
"name": "default",
"defaultEnv": "default",
"description": null
- },
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ]
+ }
},
{
"id": "java-centos",
@@ -1140,14 +1028,6 @@
}
]
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-java.svg",
"mediaType": "image/svg+xml"
@@ -1220,14 +1100,6 @@
}
]
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-java.svg",
"mediaType": "image/svg+xml"
@@ -1306,14 +1178,6 @@
}
]
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-php.svg",
"mediaType": "image/svg+xml"
@@ -1379,14 +1243,6 @@
}
]
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-python.svg",
"mediaType": "image/svg+xml"
@@ -1449,14 +1305,6 @@
}
]
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-python.svg",
"mediaType": "image/svg+xml"
@@ -1527,15 +1375,7 @@
"name": "default",
"defaultEnv": "default",
"description": null
- },
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ]
+ }
},
{
"id": "tomee-default",
@@ -1595,14 +1435,6 @@
}
]
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-java.svg",
"mediaType": "image/svg+xml"
@@ -1650,15 +1482,7 @@
"source": {
"type": "image",
"origin": "codenvy/ubuntu_jre"
- },
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ]
+ }
},
{
"id": "bitnami-express",
@@ -1723,14 +1547,6 @@
"description": null,
"commands": []
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-bitnami.svg",
"mediaType": "image/svg+xml"
@@ -1809,14 +1625,6 @@
"description": null,
"commands": []
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-bitnami.svg",
"mediaType": "image/svg+xml"
@@ -1886,14 +1694,6 @@
"description": null,
"commands": []
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-bitnami.svg",
"mediaType": "image/svg+xml"
@@ -1962,14 +1762,6 @@
"description": null,
"commands": []
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-bitnami.svg",
"mediaType": "image/svg+xml"
@@ -2038,14 +1830,6 @@
"description": null,
"commands": []
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-bitnami.svg",
"mediaType": "image/svg+xml"
@@ -2114,14 +1898,6 @@
"description": null,
"commands": []
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-bitnami.svg",
"mediaType": "image/svg+xml"
@@ -2190,14 +1966,6 @@
"description": null,
"commands": []
},
- "acl": [
- {
- "user": "*",
- "actions": [
- "search"
- ]
- }
- ],
"stackIcon": {
"name": "type-bitnami.svg",
"mediaType": "image/svg+xml"
diff --git a/plugins/plugin-java/che-plugin-java-ext-jdt/org-eclipse-ui-ide/src/main/java/org/eclipse/ui/wizards/datatransfer/ImportOperation.java b/plugins/plugin-java/che-plugin-java-ext-jdt/org-eclipse-ui-ide/src/main/java/org/eclipse/ui/wizards/datatransfer/ImportOperation.java
index e3cfb87d66..1e301248da 100644
--- a/plugins/plugin-java/che-plugin-java-ext-jdt/org-eclipse-ui-ide/src/main/java/org/eclipse/ui/wizards/datatransfer/ImportOperation.java
+++ b/plugins/plugin-java/che-plugin-java-ext-jdt/org-eclipse-ui-ide/src/main/java/org/eclipse/ui/wizards/datatransfer/ImportOperation.java
@@ -441,7 +441,7 @@ public class ImportOperation extends WorkspaceModifyOperation {
*
* @param resource resource to cast/adapt
* @return the resource either casted to or adapted to an IFile.
- * null if the resource does not adapt to IFile
+ * null if the resource does not adapt to IFile
*/
IFile getFile(IResource resource) {
if (resource instanceof IFile) {
@@ -460,7 +460,7 @@ public class ImportOperation extends WorkspaceModifyOperation {
*
* @param resource resource to cast/adapt
* @return the resource either casted to or adapted to an IFolder.
- * null if the resource does not adapt to IFolder
+ * null if the resource does not adapt to IFolder
*/
IFolder getFolder(IResource resource) {
if (resource instanceof IFolder) {
diff --git a/plugins/plugin-machine/che-plugin-machine-ext-server/src/test/java/org/eclipse/che/ide/ext/machine/server/ssh/KeysInjectorTest.java b/plugins/plugin-machine/che-plugin-machine-ext-server/src/test/java/org/eclipse/che/ide/ext/machine/server/ssh/KeysInjectorTest.java
index e2c818c9a8..6be95f3a9d 100644
--- a/plugins/plugin-machine/che-plugin-machine-ext-server/src/test/java/org/eclipse/che/ide/ext/machine/server/ssh/KeysInjectorTest.java
+++ b/plugins/plugin-machine/che-plugin-machine-ext-server/src/test/java/org/eclipse/che/ide/ext/machine/server/ssh/KeysInjectorTest.java
@@ -134,7 +134,7 @@ public class KeysInjectorTest {
@Test
public void shouldNotInjectSshKeysWhenThereAreNotAnyPairWithPublicKey() throws Exception {
when(sshManager.getPairs(anyString(), anyString()))
- .thenReturn(Collections.singletonList(new SshPairImpl("machine", "myPair", null, null)));
+ .thenReturn(Collections.singletonList(new SshPairImpl(OWNER_ID, "machine", "myPair", null, null)));
subscriber.onEvent(newDto(MachineStatusEvent.class).withEventType(MachineStatusEvent.EventType.RUNNING)
.withMachineId(MACHINE_ID)
@@ -148,8 +148,8 @@ public class KeysInjectorTest {
@Test
public void shouldInjectSshKeysWhenThereAreAnyPairWithNotNullPublicKey() throws Exception {
when(sshManager.getPairs(anyString(), anyString()))
- .thenReturn(Arrays.asList(new SshPairImpl("machine", "myPair", "publicKey1", null),
- new SshPairImpl("machine", "myPair", "publicKey2", null)));
+ .thenReturn(Arrays.asList(new SshPairImpl(OWNER_ID, "machine", "myPair", "publicKey1", null),
+ new SshPairImpl(OWNER_ID, "machine", "myPair", "publicKey2", null)));
subscriber.onEvent(newDto(MachineStatusEvent.class).withEventType(MachineStatusEvent.EventType.RUNNING)
.withMachineId(MACHINE_ID)
@@ -170,7 +170,7 @@ public class KeysInjectorTest {
@Test
public void shouldSendMessageInMachineLoggerWhenSomeErrorOcursOnKeysInjection() throws Exception {
when(sshManager.getPairs(anyString(), anyString()))
- .thenReturn(Collections.singletonList(new SshPairImpl("machine", "myPair", "publicKey1", null)));
+ .thenReturn(Collections.singletonList(new SshPairImpl(OWNER_ID, "machine", "myPair", "publicKey1", null)));
when(logMessage.getType()).thenReturn(LogMessage.Type.STDERR);
when(logMessage.getContent()).thenReturn("FAILED");
diff --git a/plugins/plugin-maven/che-plugin-maven-ide/src/main/java/org/eclipse/che/plugin/maven/client/project/MavenModelImporter.java b/plugins/plugin-maven/che-plugin-maven-ide/src/main/java/org/eclipse/che/plugin/maven/client/project/MavenModelImporter.java
index 632fbff162..ceab1a16ca 100644
--- a/plugins/plugin-maven/che-plugin-maven-ide/src/main/java/org/eclipse/che/plugin/maven/client/project/MavenModelImporter.java
+++ b/plugins/plugin-maven/che-plugin-maven-ide/src/main/java/org/eclipse/che/plugin/maven/client/project/MavenModelImporter.java
@@ -12,7 +12,7 @@ package org.eclipse.che.plugin.maven.client.project;
import com.google.web.bindery.event.shared.EventBus;
-import org.eclipse.che.api.factory.shared.dto.Factory;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.api.promises.client.Operation;
import org.eclipse.che.api.promises.client.OperationException;
import org.eclipse.che.api.promises.client.PromiseError;
@@ -54,7 +54,7 @@ public class MavenModelImporter implements FactoryAcceptedHandler {
@Override
public void onFactoryAccepted(FactoryAcceptedEvent event) {
- final Factory factory = event.getFactory();
+ final FactoryDto factory = event.getFactory();
final List projects = factory.getWorkspace().getProjects();
final List paths = new ArrayList<>();
for (ProjectConfigDto project : projects) {
diff --git a/pom.xml b/pom.xml
index 14f663bc99..4d2525be91 100644
--- a/pom.xml
+++ b/pom.xml
@@ -80,6 +80,17 @@
${che.version}war
+
+ org.eclipse.che.core
+ che-core-api-account
+ ${che.version}
+
+
+ org.eclipse.che.core
+ che-core-api-account
+ ${project.version}
+ tests
+ org.eclipse.che.coreche-core-api-agent
@@ -125,6 +136,12 @@
che-core-api-factory${che.version}
+
+ org.eclipse.che.core
+ che-core-api-factory
+ ${project.version}
+ tests
+ org.eclipse.che.coreche-core-api-factory-shared
@@ -151,11 +168,27 @@
che-core-api-infrastructure-local${che.version}
+
+ org.eclipse.che.core
+ che-core-api-jdbc
+ ${project.version}
+
+
+ org.eclipse.che.core
+ che-core-api-jdbc-vendor-h2
+ ${project.version}
+ org.eclipse.che.coreche-core-api-machine${che.version}
+
+ org.eclipse.che.core
+ che-core-api-machine
+ ${project.version}
+ tests
+ org.eclipse.che.coreche-core-api-machine-shared
@@ -191,6 +224,12 @@
che-core-api-ssh${che.version}
+
+ org.eclipse.che.core
+ che-core-api-ssh
+ ${che.version}
+ tests
+ org.eclipse.che.coreche-core-api-ssh-shared
@@ -212,6 +251,12 @@
che-core-api-user-shared${che.version}
+
+ org.eclipse.che.core
+ che-core-api-workspace
+ ${che.version}
+ tests
+ org.eclipse.che.coreche-core-api-workspace
diff --git a/wsmaster/che-core-api-account/pom.xml b/wsmaster/che-core-api-account/pom.xml
new file mode 100644
index 0000000000..e68a3179ba
--- /dev/null
+++ b/wsmaster/che-core-api-account/pom.xml
@@ -0,0 +1,136 @@
+
+
+
+ 4.0.0
+
+ che-master-parent
+ org.eclipse.che.core
+ 5.0.0-M2-SNAPSHOT
+
+ che-core-api-account
+ Che Core :: API :: Account
+
+
+ com.google.inject
+ guice
+
+
+ javax.inject
+ javax.inject
+
+
+ org.eclipse.che.core
+ che-core-api-core
+
+
+ org.eclipse.che.core
+ che-core-commons-lang
+
+
+ org.slf4j
+ slf4j-api
+
+
+ com.google.inject.extensions
+ guice-persist
+ provided
+
+
+ org.eclipse.che.core
+ che-core-api-jdbc
+ provided
+
+
+ org.eclipse.persistence
+ eclipselink
+ provided
+
+
+ org.eclipse.persistence
+ javax.persistence
+ provided
+
+
+ ch.qos.logback
+ logback-classic
+ test
+
+
+ com.google.code.gson
+ gson
+ test
+
+
+ com.h2database
+ h2
+ test
+
+
+ org.eclipse.che.core
+ che-core-api-jdbc-vendor-h2
+ test
+
+
+ org.eclipse.che.core
+ che-core-commons-json
+ test
+
+
+ org.eclipse.che.core
+ che-core-commons-test
+ test
+
+
+ org.mockito
+ mockito-all
+ test
+
+
+ org.mockito
+ mockito-core
+ test
+
+
+ org.mockitong
+ mockitong
+ test
+
+
+ org.testng
+ testng
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ test-jar
+
+
+
+ **/spi/tck/*.*
+
+
+
+
+
+
+
+
diff --git a/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/api/AccountManager.java b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/api/AccountManager.java
new file mode 100644
index 0000000000..31b9674436
--- /dev/null
+++ b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/api/AccountManager.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.account.api;
+
+import org.eclipse.che.account.shared.model.Account;
+import org.eclipse.che.account.spi.AccountDao;
+import org.eclipse.che.api.core.NotFoundException;
+import org.eclipse.che.api.core.ServerException;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Facade for Account related operations.
+ *
+ * @author Sergii Leschenko
+ */
+@Singleton
+public class AccountManager {
+
+ private final AccountDao accountDao;
+
+ @Inject
+ public AccountManager(AccountDao accountDao) {
+ this.accountDao = accountDao;
+ }
+
+ /**
+ * Gets account by identifier.
+ *
+ * @param id
+ * id of account to fetch
+ * @return account instance with given id
+ * @throws NullPointerException
+ * when {@code id} is null
+ * @throws NotFoundException
+ * when account with given {@code id} was not found
+ * @throws ServerException
+ * when any other error occurs during account fetching
+ */
+ public Account getById(String id) throws NotFoundException, ServerException {
+ requireNonNull(id, "Required non-null account id");
+ return accountDao.getById(id);
+ }
+
+ /**
+ * Gets account by name.
+ *
+ * @param name
+ * name of account to fetch
+ * @return account instance with given name
+ * @throws NullPointerException
+ * when {@code name} is null
+ * @throws NotFoundException
+ * when account with given {@code name} was not found
+ * @throws ServerException
+ * when any other error occurs during account fetching
+ */
+ public Account getByName(String name) throws NotFoundException, ServerException {
+ requireNonNull(name, "Required non-null account name");
+ return accountDao.getByName(name);
+ }
+}
diff --git a/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/api/AccountModule.java b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/api/AccountModule.java
new file mode 100644
index 0000000000..62a960cfd5
--- /dev/null
+++ b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/api/AccountModule.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.account.api;
+
+import org.eclipse.che.account.spi.AccountDao;
+import org.eclipse.che.account.spi.jpa.JpaAccountDao;
+
+import com.google.inject.AbstractModule;
+
+/**
+ * @author Sergii Leschenko
+ */
+public class AccountModule extends AbstractModule {
+ @Override
+ protected void configure() {
+ bind(AccountDao.class).to(JpaAccountDao.class);
+ }
+}
diff --git a/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/event/BeforeAccountRemovedEvent.java b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/event/BeforeAccountRemovedEvent.java
new file mode 100644
index 0000000000..da98b11053
--- /dev/null
+++ b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/event/BeforeAccountRemovedEvent.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.account.event;
+
+import org.eclipse.che.account.spi.AccountImpl;
+
+/**
+ * Published before {@link AccountImpl account} removed.
+ *
+ * @author Antona Korneta
+ */
+public class BeforeAccountRemovedEvent {
+
+ private final AccountImpl account;
+
+ public BeforeAccountRemovedEvent(AccountImpl account) {
+ this.account = account;
+ }
+
+ /** Returns account which is going to be removed. */
+ public AccountImpl getAccount() {
+ return account;
+ }
+}
diff --git a/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/acl/AclEntry.java b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/shared/model/Account.java
similarity index 62%
rename from core/che-core-api-core/src/main/java/org/eclipse/che/api/core/acl/AclEntry.java
rename to wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/shared/model/Account.java
index 754321323f..f10634b100 100644
--- a/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/acl/AclEntry.java
+++ b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/shared/model/Account.java
@@ -8,23 +8,24 @@
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
-package org.eclipse.che.api.core.acl;
-
-import java.util.List;
+package org.eclipse.che.account.shared.model;
/**
- * This is the interface used for representing one entry in an Access Control List (ACL).
- *
* @author Sergii Leschenko
*/
-public interface AclEntry {
+public interface Account {
/**
- * Returns user id or '*' for all users
+ * Returns account id
*/
- String getUser();
+ String getId();
/**
- * Returns list of actions which are allowed to perform for specified user
+ * Returns name of account
*/
- List getActions();
+ String getName();
+
+ /**
+ * Returns type of account
+ */
+ String getType();
}
diff --git a/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/AccountDao.java b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/AccountDao.java
new file mode 100644
index 0000000000..eafebfb301
--- /dev/null
+++ b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/AccountDao.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.account.spi;
+
+import org.eclipse.che.api.core.NotFoundException;
+import org.eclipse.che.api.core.ServerException;
+
+/**
+ * Defines data access object for {@link AccountImpl}
+ *
+ * @author Sergii Leschenko
+ */
+public interface AccountDao {
+ /**
+ * Gets account by identifier.
+ *
+ * @param id
+ * account identifier
+ * @return account instance with given id
+ * @throws NullPointerException
+ * when {@code id} is null
+ * @throws NotFoundException
+ * when account with given {@code id} was not found
+ * @throws ServerException
+ * when any other error occurs during account fetching
+ */
+ AccountImpl getById(String id) throws NotFoundException, ServerException;
+
+ /**
+ * Gets account by name.
+ *
+ * @param name
+ * account name
+ * @return account instance with given name
+ * @throws NullPointerException
+ * when {@code name} is null
+ * @throws NotFoundException
+ * when account with given {@code name} was not found
+ * @throws ServerException
+ * when any other error occurs during account fetching
+ */
+ AccountImpl getByName(String name) throws ServerException, NotFoundException;
+}
diff --git a/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/AccountImpl.java b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/AccountImpl.java
new file mode 100644
index 0000000000..30c6f17b90
--- /dev/null
+++ b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/AccountImpl.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.account.spi;
+
+import org.eclipse.che.account.shared.model.Account;
+import org.eclipse.che.account.spi.jpa.AccountEntityListener;
+
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.Id;
+import javax.persistence.Index;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import java.util.Objects;
+
+/**
+ * Data object for {@link Account}.
+ *
+ * @author Sergii Leschenko
+ */
+@Entity(name = "Account")
+@NamedQueries(
+ {
+ @NamedQuery(name = "Account.getByName",
+ query = "SELECT a " +
+ "FROM Account a " +
+ "WHERE a.name = :name")
+ }
+)
+@Table(indexes = @Index(columnList = "name", unique = true))
+@EntityListeners(AccountEntityListener.class)
+public class AccountImpl implements Account {
+
+ @Id
+ protected String id;
+
+ @Column(nullable = false)
+ protected String name;
+
+ @Basic
+ private String type;
+
+ public AccountImpl() {}
+
+ public AccountImpl(String id, String name, String type) {
+ this.id = id;
+ this.name = name;
+ this.type = type;
+ }
+
+ public AccountImpl(Account account) {
+ this(account.getId(), account.getName(), account.getType());
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof AccountImpl)) return false;
+ AccountImpl account = (AccountImpl)o;
+ return Objects.equals(id, account.id) &&
+ Objects.equals(name, account.name);
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + Objects.hash(id);
+ hash = 31 * hash + Objects.hash(name);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return "AccountImpl{" +
+ "id='" + id + '\'' +
+ ", name='" + name + '\'' +
+ '}';
+ }
+}
diff --git a/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/AccountValidator.java b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/AccountValidator.java
new file mode 100644
index 0000000000..7cc8cfdce0
--- /dev/null
+++ b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/AccountValidator.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.account.spi;
+
+import org.eclipse.che.account.api.AccountManager;
+import org.eclipse.che.api.core.NotFoundException;
+import org.eclipse.che.api.core.ServerException;
+import org.eclipse.che.commons.lang.NameGenerator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import java.util.regex.Pattern;
+
+/**
+ * Utils for account validation.
+ *
+ * @author Sergii Leschenko
+ */
+// TODO extract normalization code from the validator as it is not related to the validation at all
+@Singleton
+public class AccountValidator {
+ private static final Logger LOG = LoggerFactory.getLogger(AccountValidator.class);
+
+ private static final Pattern ILLEGAL_ACCOUNT_NAME_CHARACTERS = Pattern.compile("[^a-zA-Z0-9]");
+ private static final Pattern VALID_ACCOUNT_NAME = Pattern.compile("^[a-zA-Z0-9]*");
+
+ private final AccountManager accountManager;
+
+ @Inject
+ public AccountValidator(AccountManager accountManager) {
+ this.accountManager = accountManager;
+ }
+
+ /**
+ * Validate name, if it doesn't contain illegal characters
+ *
+ * @param name
+ * account name
+ * @return true if valid name, false otherwise
+ */
+ public boolean isValidName(String name) {
+ return name != null && VALID_ACCOUNT_NAME.matcher(name).matches();
+ }
+
+ /**
+ * Remove illegal characters from account name, to make it URL-friendly.
+ * If all characters are illegal, return automatically generated account name with specified prefix.
+ * Also ensures account name is unique, if not, adds digits to it's end.
+ *
+ * @param name
+ * account name
+ * @param prefix
+ * prefix to add to generated name
+ * @return account name without illegal characters
+ */
+ public String normalizeAccountName(String name, String prefix) throws ServerException {
+ String normalized = ILLEGAL_ACCOUNT_NAME_CHARACTERS.matcher(name).replaceAll("");
+ String candidate = normalized.isEmpty() ? NameGenerator.generate(prefix, 4) : normalized;
+
+ int i = 1;
+ try {
+ while (accountExists(candidate)) {
+ candidate = normalized.isEmpty() ? NameGenerator.generate(prefix, 4) : normalized + String.valueOf(i++);
+ }
+ } catch (ServerException e) {
+ LOG.warn("Error occurred during account name normalization", e);
+ throw e;
+ }
+ return candidate;
+ }
+
+ private boolean accountExists(String accountName) throws ServerException {
+ try {
+ accountManager.getByName(accountName);
+ } catch (NotFoundException e) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/jpa/AccountEntityListener.java b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/jpa/AccountEntityListener.java
new file mode 100644
index 0000000000..f74f5416cf
--- /dev/null
+++ b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/jpa/AccountEntityListener.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.account.spi.jpa;
+
+
+import org.eclipse.che.account.event.BeforeAccountRemovedEvent;
+import org.eclipse.che.account.spi.AccountImpl;
+import org.eclipse.che.api.core.notification.EventService;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.persistence.PreRemove;
+
+/**
+ * Callback for {@link AccountImpl account} jpa related events.
+ *
+ * @author Anton Korneta.
+ */
+@Singleton
+public class AccountEntityListener {
+
+ @Inject
+ private EventService eventService;
+
+ @PreRemove
+ private void preRemove(AccountImpl account) {
+ eventService.publish(new BeforeAccountRemovedEvent(account));
+ }
+}
diff --git a/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/jpa/JpaAccountDao.java b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/jpa/JpaAccountDao.java
new file mode 100644
index 0000000000..f73e55f53e
--- /dev/null
+++ b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/jpa/JpaAccountDao.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.account.spi.jpa;
+
+import com.google.inject.persist.Transactional;
+
+import org.eclipse.che.account.spi.AccountDao;
+import org.eclipse.che.account.spi.AccountImpl;
+import org.eclipse.che.api.core.NotFoundException;
+import org.eclipse.che.api.core.ServerException;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+
+import static java.lang.String.format;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * JPA based implementation of {@link AccountDao}.
+ *
+ * @author Sergii Leschenko
+ */
+@Singleton
+public class JpaAccountDao implements AccountDao {
+ private final Provider managerProvider;
+
+ @Inject
+ public JpaAccountDao(Provider managerProvider) {
+ this.managerProvider = managerProvider;
+ }
+
+ @Override
+ @Transactional
+ public AccountImpl getById(String id) throws NotFoundException, ServerException {
+ requireNonNull(id, "Required non-null account id");
+ final EntityManager manager = managerProvider.get();
+ try {
+ AccountImpl account = manager.find(AccountImpl.class, id);
+ if (account == null) {
+ throw new NotFoundException(format("Account with id '%s' was not found", id));
+ }
+ return account;
+ } catch (RuntimeException x) {
+ throw new ServerException(x.getLocalizedMessage(), x);
+ }
+ }
+
+ @Override
+ @Transactional
+ public AccountImpl getByName(String name) throws ServerException, NotFoundException {
+ requireNonNull(name, "Required non-null account name");
+ final EntityManager manager = managerProvider.get();
+ try {
+ return manager.createNamedQuery("Account.getByName",
+ AccountImpl.class)
+ .setParameter("name", name)
+ .getSingleResult();
+ } catch (NoResultException e) {
+ throw new NotFoundException(String.format("Account with name '%s' was not found", name));
+ } catch (RuntimeException e) {
+ throw new ServerException(e.getLocalizedMessage(), e);
+ }
+ }
+}
diff --git a/wsmaster/che-core-api-account/src/test/java/org/eclipse/che/account/spi/AccountValidatorTest.java b/wsmaster/che-core-api-account/src/test/java/org/eclipse/che/account/spi/AccountValidatorTest.java
new file mode 100644
index 0000000000..f136979cbc
--- /dev/null
+++ b/wsmaster/che-core-api-account/src/test/java/org/eclipse/che/account/spi/AccountValidatorTest.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.account.spi;
+
+import org.eclipse.che.account.api.AccountManager;
+import org.eclipse.che.api.core.NotFoundException;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.testng.MockitoTestNGListener;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doThrow;
+
+/**
+ * Tests of {@link AccountValidator}.
+ *
+ * @author Mihail Kuznyetsov
+ * @author Yevhenii Voevodin
+ * @author Sergii Leschenko
+ */
+@Listeners(MockitoTestNGListener.class)
+public class AccountValidatorTest {
+
+ @Mock
+ private AccountManager accountManager;
+
+ @InjectMocks
+ private AccountValidator accountValidator;
+
+ @Test(dataProvider = "normalizeNames")
+ public void testNormalizeAccountName(String input, String expected) throws Exception {
+ doThrow(NotFoundException.class).when(accountManager).getByName(anyString());
+
+ Assert.assertEquals(accountValidator.normalizeAccountName(input, "account"), expected);
+ }
+
+ @Test
+ public void testNormalizeAccountNameWhenInputDoesNotContainAnyValidCharacter() throws Exception {
+ doThrow(NotFoundException.class).when(accountManager).getByName(anyString());
+
+ Assert.assertTrue(accountValidator.normalizeAccountName("#", "name").startsWith("name"));
+ }
+
+ @Test(dataProvider = "validNames")
+ public void testValidUserName(String input, boolean expected) throws Exception {
+ doThrow(NotFoundException.class).when(accountManager).getByName(anyString());
+
+ Assert.assertEquals(accountValidator.isValidName(input), expected);
+ }
+
+ @DataProvider(name = "normalizeNames")
+ public Object[][] normalizeNames() {
+ return new Object[][] {{"test", "test"},
+ {"test123", "test123"},
+ {"test 123", "test123"},
+ {"test@gmail.com", "testgmailcom"},
+ {"TEST", "TEST"},
+ {"test-", "test"},
+ {"te-st", "test"},
+ {"-test", "test"},
+ {"te_st", "test"},
+ {"te#st", "test"}
+ };
+ }
+
+ @DataProvider(name = "validNames")
+ public Object[][] validNames() {
+ return new Object[][] {{"test", true},
+ {"test123", true},
+ {"test 123", false},
+ {"test@gmail.com", false},
+ {"TEST", true},
+ {"test-", false},
+ {"te-st", false},
+ {"-test", false},
+ {"te_st", false},
+ {"te#st", false}
+ };
+ }
+}
diff --git a/wsmaster/che-core-api-account/src/test/java/org/eclipse/che/account/spi/tck/AccountDaoTest.java b/wsmaster/che-core-api-account/src/test/java/org/eclipse/che/account/spi/tck/AccountDaoTest.java
new file mode 100644
index 0000000000..261feb370d
--- /dev/null
+++ b/wsmaster/che-core-api-account/src/test/java/org/eclipse/che/account/spi/tck/AccountDaoTest.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.account.spi.tck;
+
+import org.eclipse.che.account.spi.AccountDao;
+import org.eclipse.che.account.spi.AccountImpl;
+import org.eclipse.che.api.core.NotFoundException;
+import org.eclipse.che.commons.lang.NameGenerator;
+import org.eclipse.che.commons.test.tck.TckModuleFactory;
+import org.eclipse.che.commons.test.tck.repository.TckRepository;
+import org.eclipse.che.commons.test.tck.repository.TckRepositoryException;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import javax.inject.Inject;
+
+import static java.util.Arrays.asList;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Tests {@link AccountDao} contract.
+ *
+ * @author Sergii Leschenko
+ */
+@Guice(moduleFactory = TckModuleFactory.class)
+@Test(suiteName = AccountDaoTest.SUITE_NAME)
+public class AccountDaoTest {
+ public static final String SUITE_NAME = "AccountDaoTck";
+
+ private AccountImpl[] accounts;
+
+ @Inject
+ private AccountDao accountDao;
+
+ @Inject
+ private TckRepository accountRepo;
+
+ @BeforeMethod
+ private void setUp() throws TckRepositoryException {
+ accounts = new AccountImpl[2];
+
+ accounts[0] = new AccountImpl(NameGenerator.generate("account", 10), "test1", "test");
+ accounts[1] = new AccountImpl(NameGenerator.generate("account", 10), "test2", "test");
+
+ accountRepo.createAll(asList(accounts));
+ }
+
+ @AfterMethod
+ private void cleanup() throws TckRepositoryException {
+ accountRepo.removeAll();
+ }
+
+ @Test
+ public void shouldGetAccountById() throws Exception {
+ final AccountImpl account = accounts[0];
+
+ final AccountImpl found = accountDao.getById(account.getId());
+
+ assertEquals(account, found);
+ }
+
+ @Test(expectedExceptions = NotFoundException.class)
+ public void shouldThrowNotFoundExceptionOnGettingNonExistingAccountById() throws Exception {
+ accountDao.getById("non-existing-account");
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrowNpeOnGettingAccountByNullId() throws Exception {
+ accountDao.getById(null);
+ }
+
+ @Test
+ public void shouldGetAccountByName() throws Exception {
+ final AccountImpl account = accounts[0];
+
+ final AccountImpl found = accountDao.getByName(account.getName());
+
+ assertEquals(account, found);
+ }
+
+ @Test(expectedExceptions = NotFoundException.class)
+ public void shouldThrowNotFoundExceptionOnGettingNonExistingaccountByName() throws Exception {
+ accountDao.getByName("non-existing-account");
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrowNpeOnGettingAccountByNullName() throws Exception {
+ accountDao.getByName(null);
+ }
+}
diff --git a/wsmaster/che-core-api-account/src/test/java/org/eclipse/che/account/spi/tck/jpa/AccountJpaTckModule.java b/wsmaster/che-core-api-account/src/test/java/org/eclipse/che/account/spi/tck/jpa/AccountJpaTckModule.java
new file mode 100644
index 0000000000..8267a015a9
--- /dev/null
+++ b/wsmaster/che-core-api-account/src/test/java/org/eclipse/che/account/spi/tck/jpa/AccountJpaTckModule.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.account.spi.tck.jpa;
+
+import com.google.inject.TypeLiteral;
+import com.google.inject.persist.jpa.JpaPersistModule;
+
+import org.eclipse.che.account.spi.AccountDao;
+import org.eclipse.che.account.spi.AccountImpl;
+import org.eclipse.che.account.spi.jpa.JpaAccountDao;
+import org.eclipse.che.api.core.jdbc.jpa.eclipselink.EntityListenerInjectionManagerInitializer;
+import org.eclipse.che.api.core.jdbc.jpa.guice.JpaInitializer;
+import org.eclipse.che.commons.test.tck.TckModule;
+import org.eclipse.che.commons.test.tck.repository.JpaTckRepository;
+import org.eclipse.che.commons.test.tck.repository.TckRepository;
+
+/**
+ * @author Sergii Leschenko
+ */
+public class AccountJpaTckModule extends TckModule {
+ @Override
+ protected void configure() {
+ install(new JpaPersistModule("main"));
+ bind(JpaInitializer.class).asEagerSingleton();
+ bind(EntityListenerInjectionManagerInitializer.class).asEagerSingleton();
+ bind(new TypeLiteral>() {}).toInstance(new JpaTckRepository<>(AccountImpl.class));
+
+ bind(AccountDao.class).to(JpaAccountDao.class);
+ }
+}
diff --git a/wsmaster/che-core-api-account/src/test/resources/META-INF/persistence.xml b/wsmaster/che-core-api-account/src/test/resources/META-INF/persistence.xml
new file mode 100644
index 0000000000..0df1419c14
--- /dev/null
+++ b/wsmaster/che-core-api-account/src/test/resources/META-INF/persistence.xml
@@ -0,0 +1,34 @@
+
+
+
+ org.eclipse.persistence.jpa.PersistenceProvider
+ org.eclipse.che.account.spi.AccountImpl
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/wsmaster/che-core-api-account/src/test/resources/META-INF/services/org.eclipse.che.commons.test.tck.TckModule b/wsmaster/che-core-api-account/src/test/resources/META-INF/services/org.eclipse.che.commons.test.tck.TckModule
new file mode 100644
index 0000000000..36dc9836b3
--- /dev/null
+++ b/wsmaster/che-core-api-account/src/test/resources/META-INF/services/org.eclipse.che.commons.test.tck.TckModule
@@ -0,0 +1 @@
+org.eclipse.che.account.spi.tck.jpa.AccountJpaTckModule
diff --git a/wsmaster/che-core-api-account/src/test/resources/logback-test.xml b/wsmaster/che-core-api-account/src/test/resources/logback-test.xml
new file mode 100644
index 0000000000..0d5e22c3c6
--- /dev/null
+++ b/wsmaster/che-core-api-account/src/test/resources/logback-test.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+ %-41(%date[%.15thread]) %-45([%-5level] [%.30logger{30} %L]) - %msg%n
+
+
+
+
+
+
+
diff --git a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/Constants.java b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/Constants.java
new file mode 100644
index 0000000000..f7704b9d5c
--- /dev/null
+++ b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/Constants.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.factory.shared;
+
+/**
+ * Constants for Factory API.
+ *
+ * @author Anton Korneta
+ */
+public final class Constants {
+
+ // factory links rel attributes
+ public static final String IMAGE_REL_ATT = "image";
+ public static final String RETRIEVE_FACTORY_REL_ATT = "self";
+ public static final String SNIPPET_REL_ATT = "snippet";
+ public static final String FACTORY_ACCEPTANCE_REL_ATT = "accept";
+ public static final String NAMED_FACTORY_ACCEPTANCE_REL_ATT = "accept-named";
+ public static final String ACCEPTED_REL_ATT = "accepted";
+
+ // factory snippet types
+ public static final String MARKDOWN_SNIPPET_TYPE = "markdown";
+ public static final String IFRAME_SNIPPET_TYPE = "iframe";
+ public static final String HTML_SNIPPET_TYPE = "html";
+ public static final String URL_SNIPPET_TYPE = "url";
+
+ private Constants() {}
+}
diff --git a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/Author.java b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/AuthorDto.java
similarity index 84%
rename from wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/Author.java
rename to wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/AuthorDto.java
index 9c34b5babd..dec4ee6502 100644
--- a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/Author.java
+++ b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/AuthorDto.java
@@ -11,6 +11,7 @@
package org.eclipse.che.api.factory.shared.dto;
import org.eclipse.che.api.core.factory.FactoryParameter;
+import org.eclipse.che.api.core.model.factory.Author;
import org.eclipse.che.dto.shared.DTO;
import static org.eclipse.che.api.core.factory.FactoryParameter.Obligation.OPTIONAL;
@@ -21,7 +22,30 @@ import static org.eclipse.che.api.core.factory.FactoryParameter.Obligation.OPTIO
* @author Alexander Garagatyi
*/
@DTO
-public interface Author {
+public interface AuthorDto extends Author {
+
+ /**
+ * Id of user that create factory, set by the server
+ */
+ @Override
+ @FactoryParameter(obligation = OPTIONAL, setByServer = true)
+ String getUserId();
+
+ void setUserId(String userId);
+
+ AuthorDto withUserId(String userId);
+
+ /**
+ * @return Creation time of factory, set by the server (in milliseconds, from Unix epoch, no timezone)
+ */
+ @Override
+ @FactoryParameter(obligation = OPTIONAL, setByServer = true)
+ Long getCreated();
+
+ void setCreated(Long created);
+
+ AuthorDto withCreated(Long created);
+
/**
* Name of the author
*/
@@ -30,7 +54,7 @@ public interface Author {
void setName(String name);
- Author withName(String name);
+ AuthorDto withName(String name);
/**
* Email of the author
@@ -40,25 +64,5 @@ public interface Author {
void setEmail(String email);
- Author withEmail(String email);
-
- /**
- * Id of user that create factory, set by the server
- */
- @FactoryParameter(obligation = OPTIONAL, setByServer = true)
- String getUserId();
-
- void setUserId(String userId);
-
- Author withUserId(String userId);
-
- /**
- * @return Creation time of factory, set by the server (in milliseconds, from Unix epoch, no timezone)
- */
- @FactoryParameter(obligation = OPTIONAL, setByServer = true)
- Long getCreated();
-
- void setCreated(Long created);
-
- Author withCreated(Long created);
+ AuthorDto withEmail(String email);
}
diff --git a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/ButtonAttributes.java b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/ButtonAttributesDto.java
similarity index 76%
rename from wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/ButtonAttributes.java
rename to wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/ButtonAttributesDto.java
index ad9cf020c2..4ee34e6ad5 100644
--- a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/ButtonAttributes.java
+++ b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/ButtonAttributesDto.java
@@ -11,6 +11,7 @@
package org.eclipse.che.api.factory.shared.dto;
import org.eclipse.che.api.core.factory.FactoryParameter;
+import org.eclipse.che.api.core.model.factory.ButtonAttributes;
import org.eclipse.che.dto.shared.DTO;
import static org.eclipse.che.api.core.factory.FactoryParameter.Obligation.OPTIONAL;
@@ -19,32 +20,37 @@ import static org.eclipse.che.api.core.factory.FactoryParameter.Obligation.OPTIO
* @author Alexander Garagatyi
*/
@DTO
-public interface ButtonAttributes {
+public interface ButtonAttributesDto extends ButtonAttributes {
+
+ @Override
@FactoryParameter(obligation = OPTIONAL)
String getColor();
void setColor(String color);
- ButtonAttributes withColor(String color);
+ ButtonAttributesDto withColor(String color);
+ @Override
@FactoryParameter(obligation = OPTIONAL)
Boolean getCounter();
void setCounter(Boolean counter);
- ButtonAttributes withCounter(Boolean counter);
+ ButtonAttributesDto withCounter(Boolean counter);
+ @Override
@FactoryParameter(obligation = OPTIONAL)
String getLogo();
void setLogo(String logo);
- ButtonAttributes withLogo(String logo);
+ ButtonAttributesDto withLogo(String logo);
+ @Override
@FactoryParameter(obligation = OPTIONAL)
String getStyle();
void setStyle(String style);
- ButtonAttributes withStyle(String style);
+ ButtonAttributesDto withStyle(String style);
}
diff --git a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/Button.java b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/ButtonDto.java
similarity index 72%
rename from wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/Button.java
rename to wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/ButtonDto.java
index 5302dff05d..58cde95c41 100644
--- a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/Button.java
+++ b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/ButtonDto.java
@@ -11,34 +11,32 @@
package org.eclipse.che.api.factory.shared.dto;
import org.eclipse.che.api.core.factory.FactoryParameter;
+import org.eclipse.che.api.core.model.factory.Button;
import org.eclipse.che.dto.shared.DTO;
import static org.eclipse.che.api.core.factory.FactoryParameter.Obligation.OPTIONAL;
/**
- * Describes factory button
- *
* @author Alexander Garagatyi
*/
@DTO
-public interface Button {
- public enum ButtonType {
- logo, nologo
- }
+public interface ButtonDto extends Button {
/** Type of the button */
+ @Override
@FactoryParameter(obligation = OPTIONAL)
- ButtonType getType();
+ Type getType();
- void setType(ButtonType type);
+ void setType(Type type);
- Button withType(ButtonType type);
+ ButtonDto withType(Type type);
/** Button attributes */
+ @Override
@FactoryParameter(obligation = OPTIONAL)
- ButtonAttributes getAttributes();
+ ButtonAttributesDto getAttributes();
- void setAttributes(ButtonAttributes attributes);
+ void setAttributes(ButtonAttributesDto attributes);
- Button withAttributes(ButtonAttributes attributes);
+ ButtonDto withAttributes(ButtonAttributesDto attributes);
}
diff --git a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/Factory.java b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/Factory.java
deleted file mode 100644
index 481eab4a3b..0000000000
--- a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/Factory.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012-2016 Codenvy, S.A.
- * 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
- *
- * Contributors:
- * Codenvy, S.A. - initial API and implementation
- *******************************************************************************/
-package org.eclipse.che.api.factory.shared.dto;
-
-import org.eclipse.che.api.core.rest.shared.dto.Hyperlinks;
-import org.eclipse.che.api.core.rest.shared.dto.Link;
-import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto;
-import org.eclipse.che.dto.shared.DTO;
-
-import java.util.List;
-
-/**
- * Latest version of factory implementation.
- *
- * @author Alexander Garagatyi
- */
-@DTO
-public interface Factory extends FactoryV4_0, Hyperlinks {
- Factory withV(String v);
-
- Factory withId(String id);
-
- Factory withName(String name);
-
- Factory withWorkspace(WorkspaceConfigDto workspace);
-
- Factory withPolicies(Policies policies);
-
- Factory withCreator(Author creator);
-
- Factory withButton(Button button);
-
- Factory withIde(Ide ide);
-
- @Override
- Factory withLinks(List links);
-}
diff --git a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/FactoryV4_0.java b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/FactoryDto.java
similarity index 58%
rename from wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/FactoryV4_0.java
rename to wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/FactoryDto.java
index 551f9aaf6c..3dc3668c0c 100644
--- a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/FactoryV4_0.java
+++ b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/FactoryDto.java
@@ -11,7 +11,13 @@
package org.eclipse.che.api.factory.shared.dto;
import org.eclipse.che.api.core.factory.FactoryParameter;
+import org.eclipse.che.api.core.rest.shared.dto.Hyperlinks;
+import org.eclipse.che.api.core.rest.shared.dto.Link;
+import org.eclipse.che.api.core.model.factory.Factory;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto;
+import org.eclipse.che.dto.shared.DTO;
+
+import java.util.List;
import static org.eclipse.che.api.core.factory.FactoryParameter.Obligation.MANDATORY;
import static org.eclipse.che.api.core.factory.FactoryParameter.Obligation.OPTIONAL;
@@ -20,94 +26,74 @@ import static org.eclipse.che.api.core.factory.FactoryParameter.Obligation.OPTIO
* Factory of version 4.0
*
* @author Max Shaposhnik
- *
*/
-public interface FactoryV4_0 {
+@DTO
+public interface FactoryDto extends Factory, Hyperlinks {
- /**
- * @return Version for Codenvy Factory API.
- */
+ @Override
@FactoryParameter(obligation = MANDATORY)
String getV();
void setV(String v);
- FactoryV4_0 withV(String v);
+ FactoryDto withV(String v);
-
- /**
- * Describes parameters of the workspace that should be used for factory
- */
+ @Override
@FactoryParameter(obligation = MANDATORY)
WorkspaceConfigDto getWorkspace();
void setWorkspace(WorkspaceConfigDto workspace);
- FactoryV4_0 withWorkspace(WorkspaceConfigDto workspace);
+ FactoryDto withWorkspace(WorkspaceConfigDto workspace);
-
- /**
- * Describe restrictions of the factory
- */
+ @Override
@FactoryParameter(obligation = OPTIONAL, trackedOnly = true)
- Policies getPolicies();
+ PoliciesDto getPolicies();
- void setPolicies(Policies policies);
+ void setPolicies(PoliciesDto policies);
- FactoryV4_0 withPolicies(Policies policies);
+ FactoryDto withPolicies(PoliciesDto policies);
-
- /**
- * Identifying information of author
- */
+ @Override
@FactoryParameter(obligation = OPTIONAL)
- Author getCreator();
+ AuthorDto getCreator();
- void setCreator(Author creator);
+ void setCreator(AuthorDto creator);
- FactoryV4_0 withCreator(Author creator);
+ FactoryDto withCreator(AuthorDto creator);
-
- /**
- * Describes factory button
- */
+ @Override
@FactoryParameter(obligation = OPTIONAL)
- Button getButton();
+ ButtonDto getButton();
- void setButton(Button button);
+ void setButton(ButtonDto button);
- FactoryV4_0 withButton(Button button);
+ FactoryDto withButton(ButtonDto button);
-
- /**
- * Describes ide look and feel.
- */
+ @Override
@FactoryParameter(obligation = OPTIONAL)
- Ide getIde();
+ IdeDto getIde();
- void setIde(Ide ide);
+ void setIde(IdeDto ide);
- FactoryV4_0 withIde(Ide ide);
+ FactoryDto withIde(IdeDto ide);
-
- /**
- * @return - id of stored factory object
- */
+ @Override
@FactoryParameter(obligation = OPTIONAL, setByServer = true)
String getId();
void setId(String id);
- FactoryV4_0 withId(String id);
-
- /**
- * @return - name of stored factory object
- */
+ FactoryDto withId(String id);
+
+ @Override
@FactoryParameter(obligation = OPTIONAL)
String getName();
void setName(String name);
- FactoryV4_0 withName(String name);
+ FactoryDto withName(String name);
+ @Override
+ FactoryDto withLinks(List links);
}
diff --git a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/Action.java b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/IdeActionDto.java
similarity index 84%
rename from wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/Action.java
rename to wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/IdeActionDto.java
index 13453d5d12..b9c1321afa 100644
--- a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/Action.java
+++ b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/IdeActionDto.java
@@ -13,6 +13,7 @@ package org.eclipse.che.api.factory.shared.dto;
import static org.eclipse.che.api.core.factory.FactoryParameter.Obligation.OPTIONAL;
import org.eclipse.che.api.core.factory.FactoryParameter;
+import org.eclipse.che.api.core.model.factory.Action;
import org.eclipse.che.dto.shared.DTO;
import java.util.Map;
@@ -23,27 +24,30 @@ import java.util.Map;
* @author Sergii Kabashniuk
*/
@DTO
-public interface Action {
+public interface IdeActionDto extends Action {
+
/**
* Action Id
*
* @return id of action.
*/
+ @Override
@FactoryParameter(obligation = OPTIONAL)
String getId();
void setId(String id);
- Action withId(String id);
+ IdeActionDto withId(String id);
/***
*
* @return Action properties
*/
+ @Override
@FactoryParameter(obligation = OPTIONAL)
Map getProperties();
void setProperties(Map properties);
- Action withProperties(Map properties);
+ IdeActionDto withProperties(Map properties);
}
diff --git a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/Ide.java b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/IdeDto.java
similarity index 66%
rename from wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/Ide.java
rename to wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/IdeDto.java
index 9436af46db..3cc7ab59dd 100644
--- a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/Ide.java
+++ b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/IdeDto.java
@@ -13,6 +13,7 @@ package org.eclipse.che.api.factory.shared.dto;
import static org.eclipse.che.api.core.factory.FactoryParameter.Obligation.OPTIONAL;
import org.eclipse.che.api.core.factory.FactoryParameter;
+import org.eclipse.che.api.core.model.factory.Ide;
import org.eclipse.che.dto.shared.DTO;
/**
@@ -21,36 +22,39 @@ import org.eclipse.che.dto.shared.DTO;
* @author Sergii Kabashniuk
*/
@DTO
-public interface Ide {
+public interface IdeDto extends Ide {
/**
* @return configuration of IDE on application loaded event.
*/
+ @Override
@FactoryParameter(obligation = OPTIONAL)
- OnAppLoaded getOnAppLoaded();
+ OnAppLoadedDto getOnAppLoaded();
- void setOnAppLoaded(OnAppLoaded onAppLoaded);
+ void setOnAppLoaded(OnAppLoadedDto onAppLoaded);
- Ide withOnAppLoaded(OnAppLoaded onAppLoaded);
+ IdeDto withOnAppLoaded(OnAppLoadedDto onAppLoaded);
/**
* @return configuration of IDE on application closed event.
*/
+ @Override
@FactoryParameter(obligation = OPTIONAL)
- OnAppClosed getOnAppClosed();
+ OnAppClosedDto getOnAppClosed();
- void setOnAppClosed(OnAppClosed onAppClosed);
+ void setOnAppClosed(OnAppClosedDto onAppClosed);
- Ide withOnAppClosed(OnAppClosed onAppClosed);
+ IdeDto withOnAppClosed(OnAppClosedDto onAppClosed);
/**
* @return configuration of IDE on projects loaded event.
*/
+ @Override
@FactoryParameter(obligation = OPTIONAL)
- OnProjectsLoaded getOnProjectsLoaded();
+ OnProjectsLoadedDto getOnProjectsLoaded();
- void setOnProjectsLoaded(OnProjectsLoaded onProjectsLoaded);
+ void setOnProjectsLoaded(OnProjectsLoadedDto onProjectsLoaded);
- Ide withOnProjectsLoaded(OnProjectsLoaded onProjectsLoaded);
+ IdeDto withOnProjectsLoaded(OnProjectsLoadedDto onProjectsLoaded);
}
diff --git a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/OnAppClosed.java b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/OnAppClosedDto.java
similarity index 78%
rename from wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/OnAppClosed.java
rename to wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/OnAppClosedDto.java
index dad926775a..81f4cddc8f 100644
--- a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/OnAppClosed.java
+++ b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/OnAppClosedDto.java
@@ -11,6 +11,7 @@
package org.eclipse.che.api.factory.shared.dto;
import org.eclipse.che.api.core.factory.FactoryParameter;
+import org.eclipse.che.api.core.model.factory.OnAppClosed;
import org.eclipse.che.dto.shared.DTO;
import java.util.List;
@@ -23,15 +24,16 @@ import static org.eclipse.che.api.core.factory.FactoryParameter.Obligation.OPTIO
* @author Sergii Kabashniuk
*/
@DTO
-public interface OnAppClosed {
+public interface OnAppClosedDto extends OnAppClosed {
/**
* @return actions for current event.
*/
+ @Override
@FactoryParameter(obligation = OPTIONAL)
- List getActions();
+ List getActions();
- void setActions(List actions);
+ void setActions(List actions);
- OnAppClosed withActions(List actions);
+ OnAppClosedDto withActions(List actions);
}
diff --git a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/OnAppLoaded.java b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/OnAppLoadedDto.java
similarity index 78%
rename from wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/OnAppLoaded.java
rename to wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/OnAppLoadedDto.java
index b2e2de2039..75f8ad371d 100644
--- a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/OnAppLoaded.java
+++ b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/OnAppLoadedDto.java
@@ -11,6 +11,7 @@
package org.eclipse.che.api.factory.shared.dto;
import org.eclipse.che.api.core.factory.FactoryParameter;
+import org.eclipse.che.api.core.model.factory.OnAppLoaded;
import org.eclipse.che.dto.shared.DTO;
import java.util.List;
@@ -23,14 +24,16 @@ import static org.eclipse.che.api.core.factory.FactoryParameter.Obligation.OPTIO
* @author Sergii Kabashniuk
*/
@DTO
-public interface OnAppLoaded {
+public interface OnAppLoadedDto extends OnAppLoaded {
+
/**
* @return actions for current event.
*/
+ @Override
@FactoryParameter(obligation = OPTIONAL)
- List getActions();
+ List getActions();
- void setActions(List actions);
+ void setActions(List actions);
- OnAppLoaded withActions(List actions);
+ OnAppLoadedDto withActions(List actions);
}
diff --git a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/OnProjectsLoaded.java b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/OnProjectsLoadedDto.java
similarity index 77%
rename from wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/OnProjectsLoaded.java
rename to wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/OnProjectsLoadedDto.java
index 305988de99..e073173ca7 100644
--- a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/OnProjectsLoaded.java
+++ b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/OnProjectsLoadedDto.java
@@ -11,6 +11,7 @@
package org.eclipse.che.api.factory.shared.dto;
import org.eclipse.che.api.core.factory.FactoryParameter;
+import org.eclipse.che.api.core.model.factory.OnProjectsLoaded;
import org.eclipse.che.dto.shared.DTO;
import java.util.List;
@@ -23,14 +24,16 @@ import static org.eclipse.che.api.core.factory.FactoryParameter.Obligation.OPTIO
* @author Sergii Kabashniuk
*/
@DTO
-public interface OnProjectsLoaded {
+public interface OnProjectsLoadedDto extends OnProjectsLoaded {
+
/**
* @return actions for current event.
*/
+ @Override
@FactoryParameter(obligation = OPTIONAL)
- List getActions();
+ List getActions();
- void setActions(List actions);
+ void setActions(List actions);
- OnProjectsLoaded withActions(List actions);
+ OnProjectsLoadedDto withActions(List actions);
}
diff --git a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/Policies.java b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/PoliciesDto.java
similarity index 82%
rename from wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/Policies.java
rename to wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/PoliciesDto.java
index d5bc3cbb7d..c6cfb10993 100644
--- a/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/Policies.java
+++ b/wsmaster/che-core-api-factory-shared/src/main/java/org/eclipse/che/api/factory/shared/dto/PoliciesDto.java
@@ -11,9 +11,11 @@
package org.eclipse.che.api.factory.shared.dto;
import org.eclipse.che.api.core.factory.FactoryParameter;
+import org.eclipse.che.api.core.model.factory.Policies;
import org.eclipse.che.dto.shared.DTO;
import static org.eclipse.che.api.core.factory.FactoryParameter.Obligation.OPTIONAL;
+
/**
* Describe restrictions of the factory
*
@@ -21,55 +23,60 @@ import static org.eclipse.che.api.core.factory.FactoryParameter.Obligation.OPTIO
* @author Alexander Garagatyi
*/
@DTO
-public interface Policies {
+public interface PoliciesDto extends Policies {
/**
* Restrict access if referer header doesn't match this field
*/
// Do not change referer to referrer
+ @Override
@FactoryParameter(obligation = OPTIONAL)
String getReferer();
void setReferer(String referer);
- Policies withReferer(String referer);
+ PoliciesDto withReferer(String referer);
/**
* Restrict access for factories used earlier then author supposes
*/
+ @Override
@FactoryParameter(obligation = OPTIONAL)
Long getSince();
void setSince(Long since);
- Policies withSince(Long since);
+ PoliciesDto withSince(Long since);
/**
* Restrict access for factories used later then author supposes
*/
+ @Override
@FactoryParameter(obligation = OPTIONAL)
Long getUntil();
void setUntil(Long until);
- Policies withUntil(Long until);
+ PoliciesDto withUntil(Long until);
/**
* Re-open project on factory 2-nd click
*/
+ @Override
@FactoryParameter(obligation = OPTIONAL)
String getMatch();
void setMatch(String match);
- Policies withMatch(String match);
+ PoliciesDto withMatch(String match);
/**
* Workspace creation strategy
*/
+ @Override
@FactoryParameter(obligation = OPTIONAL)
String getCreate();
void setCreate(String create);
- Policies withCreate(String create);
+ PoliciesDto withCreate(String create);
}
diff --git a/wsmaster/che-core-api-factory/pom.xml b/wsmaster/che-core-api-factory/pom.xml
index 611cbaa3c0..85c2e826ae 100644
--- a/wsmaster/che-core-api-factory/pom.xml
+++ b/wsmaster/che-core-api-factory/pom.xml
@@ -45,6 +45,10 @@
io.swaggerswagger-annotations
+
+ javax.annotation
+ javax.annotation-api
+ javax.injectjavax.inject
@@ -65,6 +69,10 @@
org.eclipse.che.coreche-core-api-factory-shared
+
+ org.eclipse.che.core
+ che-core-api-machine
+ org.eclipse.che.coreche-core-api-machine-shared
@@ -89,10 +97,19 @@
org.eclipse.che.coreche-core-commons-lang
+
+ org.eclipse.che.core
+ che-core-commons-test
+ org.slf4jslf4j-api
+
+ com.google.inject.extensions
+ guice-persist
+ provided
+ javax.servletjavax.servlet-api
@@ -103,21 +120,46 @@
javax.ws.rs-apiprovided
+
+ org.eclipse.che.core
+ che-core-api-jdbc
+ provided
+
+
+ org.eclipse.persistence
+ javax.persistence
+ provided
+ ch.qos.logbacklogback-classictest
+
+ com.h2database
+ h2
+ test
+ com.jayway.restassuredrest-assuredtest
+
+ org.eclipse.che.core
+ che-core-api-jdbc-vendor-h2
+ test
+ org.eclipse.che.coreche-core-commons-jsontest
+
+ org.eclipse.persistence
+ eclipselink
+ test
+ org.everresteverrest-assured
@@ -162,4 +204,25 @@
test
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ test-jar
+
+
+
+ **/spi/tck/*.*
+
+
+
+
+
+
+
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/DtoConverter.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/DtoConverter.java
new file mode 100644
index 0000000000..36e07c7250
--- /dev/null
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/DtoConverter.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.factory.server;
+
+import org.eclipse.che.api.core.model.user.User;
+import org.eclipse.che.api.factory.shared.dto.AuthorDto;
+import org.eclipse.che.api.factory.shared.dto.ButtonAttributesDto;
+import org.eclipse.che.api.factory.shared.dto.ButtonDto;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
+import org.eclipse.che.api.factory.shared.dto.IdeActionDto;
+import org.eclipse.che.api.factory.shared.dto.IdeDto;
+import org.eclipse.che.api.factory.shared.dto.OnAppClosedDto;
+import org.eclipse.che.api.factory.shared.dto.OnAppLoadedDto;
+import org.eclipse.che.api.factory.shared.dto.OnProjectsLoadedDto;
+import org.eclipse.che.api.factory.shared.dto.PoliciesDto;
+import org.eclipse.che.api.core.model.factory.Action;
+import org.eclipse.che.api.core.model.factory.Author;
+import org.eclipse.che.api.core.model.factory.Button;
+import org.eclipse.che.api.core.model.factory.ButtonAttributes;
+import org.eclipse.che.api.core.model.factory.Factory;
+import org.eclipse.che.api.core.model.factory.Ide;
+import org.eclipse.che.api.core.model.factory.OnAppClosed;
+import org.eclipse.che.api.core.model.factory.OnAppLoaded;
+import org.eclipse.che.api.core.model.factory.OnProjectsLoaded;
+import org.eclipse.che.api.core.model.factory.Policies;
+
+import java.util.List;
+
+import static java.util.stream.Collectors.toList;
+import static org.eclipse.che.dto.server.DtoFactory.newDto;
+
+/**
+ * Helps to convert to DTOs related to factory.
+ *
+ * @author Anton Korneta
+ */
+public final class DtoConverter {
+
+ public static FactoryDto asDto(Factory factory, User user) {
+ final FactoryDto factoryDto = newDto(FactoryDto.class).withId(factory.getId())
+ .withName(factory.getName())
+ .withV(factory.getV());
+
+ if (factory.getWorkspace() != null) {
+ factoryDto.withWorkspace(org.eclipse.che.api.workspace.server.DtoConverter.asDto(factory.getWorkspace()));
+ }
+ if (factory.getCreator() != null) {
+ factoryDto.withCreator(asDto(factory.getCreator(), user));
+ }
+ if (factory.getIde() != null) {
+ factoryDto.withIde(asDto(factory.getIde()));
+ }
+ if (factory.getPolicies() != null) {
+ factoryDto.withPolicies(asDto(factory.getPolicies()));
+ }
+ if (factory.getButton() != null) {
+ factoryDto.withButton(asDto(factory.getButton()));
+ }
+ return factoryDto;
+ }
+
+ public static IdeDto asDto(Ide ide) {
+ final IdeDto ideDto = newDto(IdeDto.class);
+ final OnAppClosed onAppClosed = ide.getOnAppClosed();
+ final OnAppLoaded onAppLoaded = ide.getOnAppLoaded();
+ final OnProjectsLoaded onProjectsLoaded = ide.getOnProjectsLoaded();
+ if (onAppClosed != null) {
+ ideDto.withOnAppClosed(newDto(OnAppClosedDto.class).withActions(asDto(onAppClosed.getActions())));
+ }
+ if (onAppLoaded != null) {
+ ideDto.withOnAppLoaded(newDto(OnAppLoadedDto.class).withActions(asDto(onAppLoaded.getActions())));
+ }
+ if (onProjectsLoaded != null) {
+ ideDto.withOnProjectsLoaded(newDto(OnProjectsLoadedDto.class).withActions(asDto(onProjectsLoaded.getActions())));
+ }
+ return ideDto;
+ }
+
+ public static AuthorDto asDto(Author author, User user) {
+ return newDto(AuthorDto.class).withUserId(author.getUserId())
+ .withName(user.getName())
+ .withEmail(user.getEmail())
+ .withCreated(author.getCreated());
+ }
+
+ public static IdeActionDto asDto(Action action) {
+ return newDto(IdeActionDto.class).withId(action.getId())
+ .withProperties(action.getProperties());
+ }
+
+ public static List asDto(List extends Action> actions) {
+ return actions.stream().map(DtoConverter::asDto).collect(toList());
+ }
+
+ public static PoliciesDto asDto(Policies policies) {
+ return newDto(PoliciesDto.class).withCreate(policies.getCreate())
+ .withMatch(policies.getMatch())
+ .withReferer(policies.getReferer())
+ .withSince(policies.getSince())
+ .withUntil(policies.getUntil());
+ }
+
+ public static ButtonDto asDto(Button button) {
+ final ButtonDto buttonDto = newDto(ButtonDto.class);
+ if (button.getAttributes() != null) {
+ buttonDto.withAttributes(asDto(button.getAttributes()));
+ }
+
+ if (button.getType() != null) {
+ buttonDto.withType(button.getType());
+ }
+ return buttonDto;
+ }
+
+ public static ButtonAttributesDto asDto(ButtonAttributes attributes) {
+ return newDto(ButtonAttributesDto.class).withColor(attributes.getColor())
+ .withCounter(attributes.getCounter())
+ .withLogo(attributes.getLogo())
+ .withStyle(attributes.getStyle());
+ }
+
+ private DtoConverter() {}
+}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryAcceptValidator.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryAcceptValidator.java
index e062550b3c..6e8f07f91b 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryAcceptValidator.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryAcceptValidator.java
@@ -12,7 +12,7 @@ package org.eclipse.che.api.factory.server;
import org.eclipse.che.api.core.BadRequestException;
-import org.eclipse.che.api.factory.shared.dto.Factory;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
/**
* Interface for validations of factory urls on accept stage.
@@ -28,5 +28,5 @@ public interface FactoryAcceptValidator {
* @throws BadRequestException
* in case if factory is not valid
*/
- void validateOnAccept(Factory factory) throws BadRequestException;
+ void validateOnAccept(FactoryDto factory) throws BadRequestException;
}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryCreateValidator.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryCreateValidator.java
index 4987ae83e7..a7f4265c95 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryCreateValidator.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryCreateValidator.java
@@ -13,7 +13,7 @@ package org.eclipse.che.api.factory.server;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.ServerException;
-import org.eclipse.che.api.factory.shared.dto.Factory;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
/**
* Interface for validations of factory creation stage.
@@ -35,5 +35,5 @@ public interface FactoryCreateValidator {
* @throws ForbiddenException
* when user have no access rights for factory creation
*/
- void validateOnCreate(Factory factory) throws BadRequestException, ServerException, ForbiddenException;
+ void validateOnCreate(FactoryDto factory) throws BadRequestException, ServerException, ForbiddenException;
}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryEditValidator.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryEditValidator.java
index 072cfe4e11..366004b0bd 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryEditValidator.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryEditValidator.java
@@ -12,7 +12,7 @@ package org.eclipse.che.api.factory.server;
import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.ServerException;
-import org.eclipse.che.api.factory.shared.dto.Factory;
+import org.eclipse.che.api.core.model.factory.Factory;
/**
* This validator ensures that a factory can be edited by a user that has the associated rights (author or account owner)
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryImage.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryImage.java
index 4142da29b6..86350b43c6 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryImage.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryImage.java
@@ -10,23 +10,27 @@
*******************************************************************************/
package org.eclipse.che.api.factory.server;
-import org.eclipse.che.api.core.ConflictException;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
+import javax.persistence.Basic;
+import javax.persistence.Embeddable;
import java.util.Arrays;
+import java.util.Objects;
/** Class to hold image information such as data, name, media type */
+@Embeddable
public class FactoryImage {
+
+ @Basic
private byte[] imageData;
+
+ @Basic
private String mediaType;
+
+ @Basic
private String name;
- public FactoryImage() {
- }
+ public FactoryImage() {}
- public FactoryImage(byte[] data, String mediaType, String name) throws IOException {
+ public FactoryImage(byte[] data, String mediaType, String name) {
setMediaType(mediaType);
this.name = name;
setImageData(data);
@@ -36,7 +40,7 @@ public class FactoryImage {
return imageData;
}
- public void setImageData(byte[] imageData) throws IOException {
+ public void setImageData(byte[] imageData) {
this.imageData = imageData;
}
@@ -44,7 +48,7 @@ public class FactoryImage {
return mediaType;
}
- public void setMediaType(String mediaType) throws IOException {
+ public void setMediaType(String mediaType) {
if (mediaType != null) {
switch (mediaType) {
case "image/jpeg":
@@ -53,10 +57,10 @@ public class FactoryImage {
this.mediaType = mediaType;
return;
default:
- throw new IOException("Image media type '" + mediaType + "' is unsupported.");
+ throw new IllegalArgumentException("Image media type '" + mediaType + "' is unsupported.");
}
}
- throw new IOException("Image media type 'null' is unsupported.");
+ throw new IllegalArgumentException("Image media type 'null' is unsupported.");
}
public String getName() {
@@ -72,60 +76,21 @@ public class FactoryImage {
}
@Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof FactoryImage)) return false;
-
- FactoryImage that = (FactoryImage)o;
-
- if (!Arrays.equals(imageData, that.imageData)) return false;
- if (mediaType != null ? !mediaType.equals(that.mediaType) : that.mediaType != null) return false;
- if (name != null ? !name.equals(that.name) : that.name != null) return false;
-
- return true;
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (!(obj instanceof FactoryImage)) return false;
+ final FactoryImage other = (FactoryImage)obj;
+ return Arrays.equals(imageData, other.imageData)
+ && Objects.equals(mediaType, other.mediaType)
+ && Objects.equals(name, other.name);
}
@Override
public int hashCode() {
- int result = imageData != null ? Arrays.hashCode(imageData) : 0;
- result = 31 * result + (mediaType != null ? mediaType.hashCode() : 0);
- result = 31 * result + (name != null ? name.hashCode() : 0);
- return result;
- }
-
- /**
- * Creates {@code FactoryImage}.
- * InputStream should be closed manually.
- *
- * @param is
- * - input stream with image data
- * @param mediaType
- * - media type of image
- * @param name
- * - image name
- * @return - {@code FactoryImage} if {@code FactoryImage} was created, null if input stream has no content
- * @throws org.eclipse.che.api.core.ConflictException
- */
- public static FactoryImage createImage(InputStream is, String mediaType, String name) throws ConflictException {
- try {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- byte[] buffer = new byte[1024];
- int read;
- while ((read = is.read(buffer, 0, buffer.length)) != -1) {
- baos.write(buffer, 0, read);
- if (baos.size() > 1024 * 1024) {
- throw new ConflictException("Maximum upload size exceeded.");
- }
- }
-
- if (baos.size() == 0) {
- return new FactoryImage();
- }
- baos.flush();
-
- return new FactoryImage(baos.toByteArray(), mediaType, name);
- } catch (IOException e) {
- throw new ConflictException(e.getLocalizedMessage());
- }
+ int hash = 7;
+ hash = 31 * hash + Arrays.hashCode(imageData);
+ hash = 31 * hash + Objects.hashCode(mediaType);
+ hash = 31 * hash + Objects.hashCode(name);
+ return hash;
}
}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryLinksHelper.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryLinksHelper.java
new file mode 100644
index 0000000000..085ee40b8d
--- /dev/null
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryLinksHelper.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.factory.server;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+
+import org.eclipse.che.api.core.rest.ServiceContext;
+import org.eclipse.che.api.core.rest.shared.dto.Link;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
+
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.UriBuilder;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import static java.util.stream.Collectors.toList;
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static javax.ws.rs.core.MediaType.TEXT_HTML;
+import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
+import static org.eclipse.che.api.core.util.LinksHelper.createLink;
+import static org.eclipse.che.api.factory.shared.Constants.ACCEPTED_REL_ATT;
+import static org.eclipse.che.api.factory.shared.Constants.FACTORY_ACCEPTANCE_REL_ATT;
+import static org.eclipse.che.api.factory.shared.Constants.IMAGE_REL_ATT;
+import static org.eclipse.che.api.factory.shared.Constants.NAMED_FACTORY_ACCEPTANCE_REL_ATT;
+import static org.eclipse.che.api.factory.shared.Constants.RETRIEVE_FACTORY_REL_ATT;
+import static org.eclipse.che.api.factory.shared.Constants.SNIPPET_REL_ATT;
+
+/**
+ * Helper class for creation links.
+ *
+ * @author Anton Korneta
+ */
+public class FactoryLinksHelper {
+
+ private static final List SNIPPET_TYPES = ImmutableList.of("markdown", "url", "html", "iframe");
+
+ private FactoryLinksHelper() {}
+
+ /**
+ * Creates factory links and links for retrieving factory images.
+ *
+ * @param images
+ * a set of factory images
+ * @param serviceContext
+ * the context to retrieve factory service base URI
+ * @return list of factory and factory images links
+ */
+ public static List createLinks(FactoryDto factory,
+ Set images,
+ ServiceContext serviceContext,
+ String userName) {
+ final List links = new LinkedList<>(createLinks(factory, serviceContext, userName));
+ final UriBuilder uriBuilder = serviceContext.getServiceUriBuilder();
+ final String factoryId = factory.getId();
+
+ // creation of links to retrieve images
+ links.addAll(images.stream()
+ .map(image -> createLink(HttpMethod.GET,
+ uriBuilder.clone()
+ .path(FactoryService.class, "getImage")
+ .queryParam("imgId", image.getName())
+ .build(factoryId)
+ .toString(),
+ null,
+ image.getMediaType(),
+ IMAGE_REL_ATT))
+ .collect(toList()));
+ return links;
+ }
+
+ /**
+ * Creates factory links.
+ *
+ * @param serviceContext
+ * the context to retrieve factory service base URI
+ * @return list of factory links
+ */
+ public static List createLinks(FactoryDto factory,
+ ServiceContext serviceContext,
+ String userName) {
+ final List links = new LinkedList<>();
+ final UriBuilder uriBuilder = serviceContext.getServiceUriBuilder();
+ final String factoryId = factory.getId();
+ if (factoryId != null) {
+ // creation of link to retrieve factory
+ links.add(createLink(HttpMethod.GET,
+ uriBuilder.clone()
+ .path(FactoryService.class, "getFactory")
+ .build(factoryId)
+ .toString(),
+ null,
+ APPLICATION_JSON,
+ RETRIEVE_FACTORY_REL_ATT));
+
+ // creation of snippet links
+ links.addAll(SNIPPET_TYPES.stream()
+ .map(snippet -> createLink(HttpMethod.GET,
+ uriBuilder.clone()
+ .path(FactoryService.class,
+ "getFactorySnippet")
+ .queryParam("type", snippet)
+ .build(factoryId)
+ .toString(),
+ null,
+ TEXT_PLAIN,
+ SNIPPET_REL_ATT + '/' + snippet))
+ .collect(toList()));
+
+ // creation of accept factory link
+ final Link createWorkspace = createLink(HttpMethod.GET,
+ uriBuilder.clone()
+ .replacePath("f")
+ .queryParam("id", factoryId)
+ .build()
+ .toString(),
+ null,
+ TEXT_HTML,
+ FACTORY_ACCEPTANCE_REL_ATT);
+ links.add(createWorkspace);
+ // creation of links for analytics
+ links.add(createLink(HttpMethod.GET,
+ uriBuilder.clone()
+ .path("analytics")
+ .path("public-metric/factory_used")
+ .queryParam("factory", createWorkspace.getHref())
+ .toString(),
+ null,
+ TEXT_PLAIN,
+ ACCEPTED_REL_ATT));
+ }
+
+ if (!Strings.isNullOrEmpty(factory.getName()) && !Strings.isNullOrEmpty(userName)) {
+ // creation of accept factory link by name and creator
+ final Link createWorkspaceFromNamedFactory = createLink(HttpMethod.GET,
+ uriBuilder.clone()
+ .replacePath("f")
+ .queryParam("name", factory.getName())
+ .queryParam("user", userName)
+ .build()
+ .toString(),
+ null,
+ TEXT_HTML,
+ NAMED_FACTORY_ACCEPTANCE_REL_ATT);
+ links.add(createWorkspaceFromNamedFactory);
+ }
+ return links;
+ }
+}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryManager.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryManager.java
new file mode 100644
index 0000000000..1c29a66ba4
--- /dev/null
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryManager.java
@@ -0,0 +1,285 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.factory.server;
+
+import org.eclipse.che.api.core.ConflictException;
+import org.eclipse.che.api.core.NotFoundException;
+import org.eclipse.che.api.core.ServerException;
+import org.eclipse.che.api.core.model.factory.Factory;
+import org.eclipse.che.api.factory.server.model.impl.AuthorImpl;
+import org.eclipse.che.api.factory.server.model.impl.FactoryImpl;
+import org.eclipse.che.api.factory.server.snippet.SnippetGenerator;
+import org.eclipse.che.api.factory.server.spi.FactoryDao;
+import org.eclipse.che.commons.lang.NameGenerator;
+import org.eclipse.che.commons.lang.Pair;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.ws.rs.core.UriBuilder;
+import java.net.URI;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static com.google.common.base.MoreObjects.firstNonNull;
+import static java.util.Objects.requireNonNull;
+import static org.eclipse.che.api.factory.shared.Constants.HTML_SNIPPET_TYPE;
+import static org.eclipse.che.api.factory.shared.Constants.IFRAME_SNIPPET_TYPE;
+import static org.eclipse.che.api.factory.shared.Constants.MARKDOWN_SNIPPET_TYPE;
+import static org.eclipse.che.api.factory.shared.Constants.URL_SNIPPET_TYPE;
+
+/**
+ * @author Anton Korneta
+ */
+@Singleton
+public class FactoryManager {
+
+ @Inject
+ private FactoryDao factoryDao;
+
+ /**
+ * Stores {@link Factory} instance.
+ *
+ * @param factory
+ * instance of factory which would be stored
+ * @return factory which has been stored
+ * @throws NullPointerException
+ * when {@code factory} is null
+ * @throws ConflictException
+ * when any conflict occurs (e.g Factory with given name already exists for {@code creator})
+ * @throws ServerException
+ * when any server errors occurs
+ */
+ public Factory saveFactory(Factory factory) throws ConflictException, ServerException {
+ return saveFactory(factory, null);
+ }
+
+ /**
+ * Stores {@link Factory} instance and related set of {@link FactoryImage}.
+ *
+ * @param factory
+ * instance of factory which would be stored
+ * @param images
+ * factory images which would be stored
+ * @return factory which has been stored
+ * @throws NullPointerException
+ * when {@code factory} is null
+ * @throws ConflictException
+ * when any conflict occurs (e.g Factory with given name already exists for {@code creator})
+ * @throws ServerException
+ * when any server errors occurs
+ */
+ public Factory saveFactory(Factory factory, Set images) throws ConflictException,
+ ServerException {
+ requireNonNull(factory);
+ final FactoryImpl newFactory = new FactoryImpl(factory, images);
+ newFactory.setId(NameGenerator.generate("factory", 16));
+ return factoryDao.create(newFactory);
+ }
+
+ /**
+ * Updates factory accordance to the new configuration.
+ *
+ *
Note: Updating uses replacement strategy,
+ * therefore existing factory would be replaced with given update {@code update}
+ *
+ * @param update
+ * factory update
+ * @return updated factory
+ * @throws NullPointerException
+ * when {@code update} is null
+ * @throws ConflictException
+ * when any conflict occurs (e.g Factory with given name already exists for {@code creator})
+ * @throws NotFoundException
+ * when factory with given id not found
+ * @throws ServerException
+ * when any server error occurs
+ */
+ public Factory updateFactory(Factory update) throws ConflictException,
+ NotFoundException,
+ ServerException {
+ requireNonNull(update);
+ return updateFactory(update, null);
+ }
+
+ /**
+ * Updates factory and its images accordance to the new configuration.
+ *
+ *
Note: Updating uses replacement strategy,
+ * therefore existing factory would be replaced with given update {@code update}
+ *
+ * @param update
+ * factory update
+ * @return updated factory
+ * @throws NullPointerException
+ * when {@code update} is null
+ * @throws ConflictException
+ * when any conflict occurs (e.g Factory with given name already exists for {@code creator})
+ * @throws NotFoundException
+ * when factory with given id not found
+ * @throws ServerException
+ * when any server error occurs
+ */
+ public Factory updateFactory(Factory update, Set images) throws ConflictException,
+ NotFoundException,
+ ServerException {
+ requireNonNull(update);
+ final AuthorImpl creator = factoryDao.getById(update.getId()).getCreator();
+ return factoryDao.update(FactoryImpl.builder()
+ .from(new FactoryImpl(update, images))
+ .setCreator(new AuthorImpl(creator.getUserId(), creator.getCreated()))
+ .build());
+ }
+
+ /**
+ * Removes stored {@link Factory} by given id.
+ *
+ * @param id
+ * factory identifier
+ * @throws NullPointerException
+ * when {@code id} is null
+ * @throws ServerException
+ * when any server errors occurs
+ */
+ public void removeFactory(String id) throws ServerException {
+ requireNonNull(id);
+ factoryDao.remove(id);
+ }
+
+ /**
+ * Gets factory by given id.
+ *
+ * @param id
+ * factory identifier
+ * @return factory instance
+ * @throws NullPointerException
+ * when {@code id} is null
+ * @throws NotFoundException
+ * when factory with given id not found
+ * @throws ServerException
+ * when any server errors occurs
+ */
+ public Factory getById(String id) throws NotFoundException,
+ ServerException {
+ requireNonNull(id);
+ return factoryDao.getById(id);
+ }
+
+ /**
+ * Gets factory images by given factory and image ids.
+ *
+ * @param factoryId
+ * factory identifier
+ * @param imageId
+ * image identifier
+ * @return factory images or empty set if no image found by given {@code imageId}
+ * @throws NotFoundException
+ * when specified factory not found
+ * @throws ServerException
+ * when any server errors occurs
+ */
+ public Set getFactoryImages(String factoryId, String imageId) throws NotFoundException,
+ ServerException {
+ requireNonNull(factoryId);
+ requireNonNull(imageId);
+ return getFactoryImages(factoryId).stream()
+ .filter(image -> imageId.equals(image.getName()))
+ .collect(Collectors.toSet());
+ }
+
+ /**
+ * Gets all the factory images.
+ *
+ * @param factoryId
+ * factory identifier
+ * @return factory images or empty set if no image found for factory
+ * @throws NotFoundException
+ * when specified factory not found
+ * @throws ServerException
+ * when any server errors occurs
+ */
+ public Set getFactoryImages(String factoryId) throws NotFoundException,
+ ServerException {
+ requireNonNull(factoryId);
+ return factoryDao.getById(factoryId).getImages();
+ }
+
+ /**
+ * Get list of factories which conform specified attributes.
+ *
+ * @param maxItems
+ * max number of items in response
+ * @param skipCount
+ * skip items. Must be equals or greater then {@code 0}
+ * @param attributes
+ * skip items. Must be equals or greater then {@code 0}
+ * @return stored data, if specified attributes is correct
+ * @throws ServerException
+ * when any server errors occurs
+ */
+ @SuppressWarnings("unchecked")
+ public > T getByAttribute(int maxItems,
+ int skipCount,
+ List> attributes) throws ServerException {
+ return (T)factoryDao.getByAttribute(maxItems, skipCount, attributes);
+ }
+
+ /**
+ * Gets factory snippet by factory id and snippet type.
+ * If snippet type is not set, "url" type will be used as default.
+ *
+ * @param factoryId
+ * id of factory
+ * @param snippetType
+ * type of snippet
+ * @param baseUri
+ * URI from which will be created snippet
+ * @return snippet content or null when snippet type not found.
+ * @throws NotFoundException
+ * when factory with specified id doesn't not found
+ * @throws ServerException
+ * when any server error occurs during snippet creation
+ */
+ public String getFactorySnippet(String factoryId,
+ String snippetType,
+ URI baseUri) throws NotFoundException,
+ ServerException {
+ requireNonNull(factoryId);
+ final String baseUrl = UriBuilder.fromUri(baseUri)
+ .replacePath("")
+ .build()
+ .toString();
+ switch (firstNonNull(snippetType, URL_SNIPPET_TYPE)) {
+ case URL_SNIPPET_TYPE:
+ return UriBuilder.fromUri(baseUri)
+ .replacePath("factory")
+ .queryParam("id", factoryId)
+ .build()
+ .toString();
+ case HTML_SNIPPET_TYPE:
+ return SnippetGenerator.generateHtmlSnippet(baseUrl, factoryId);
+ case IFRAME_SNIPPET_TYPE:
+ return SnippetGenerator.generateiFrameSnippet(baseUrl, factoryId);
+ case MARKDOWN_SNIPPET_TYPE:
+ final Set images = getFactoryImages(factoryId);
+ final String imageId = (images.size() > 0) ? images.iterator().next().getName()
+ : null;
+ try {
+ return SnippetGenerator.generateMarkdownSnippet(baseUrl, getById(factoryId), imageId);
+ } catch (IllegalArgumentException e) {
+ throw new ServerException(e.getLocalizedMessage());
+ }
+ default:
+ // when the specified type is not supported
+ return null;
+ }
+ }
+}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryMessageBodyAdapter.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryMessageBodyAdapter.java
index 1732157fbf..43aa3751d0 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryMessageBodyAdapter.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryMessageBodyAdapter.java
@@ -13,8 +13,8 @@ package org.eclipse.che.api.factory.server;
import com.google.common.collect.ImmutableSet;
import com.google.gson.JsonObject;
-import org.eclipse.che.api.factory.shared.dto.Factory;
-import org.eclipse.che.api.factory.shared.dto.FactoryV4_0;
+import org.eclipse.che.api.core.model.factory.Factory;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.api.workspace.server.WorkspaceConfigMessageBodyAdapter;
import javax.inject.Singleton;
@@ -30,7 +30,7 @@ public class FactoryMessageBodyAdapter extends WorkspaceConfigMessageBodyAdapter
@Override
public Set> getTriggers() {
- return ImmutableSet.of(Factory.class, FactoryV4_0.class);
+ return ImmutableSet.of(Factory.class, FactoryDto.class);
}
@Override
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryParametersResolver.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryParametersResolver.java
index 87984b9e9a..384cd1d70f 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryParametersResolver.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryParametersResolver.java
@@ -11,7 +11,7 @@
package org.eclipse.che.api.factory.server;
import org.eclipse.che.api.core.BadRequestException;
-import org.eclipse.che.api.factory.shared.dto.Factory;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import javax.validation.constraints.NotNull;
import java.util.Map;
@@ -40,7 +40,5 @@ public interface FactoryParametersResolver {
* @throws BadRequestException
* when data are invalid
*/
- Factory createFactory(@NotNull Map factoryParameters) throws BadRequestException;
-
-
+ FactoryDto createFactory(@NotNull Map factoryParameters) throws BadRequestException;
}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryService.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryService.java
index ae20c544a1..b6887856c7 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryService.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryService.java
@@ -16,22 +16,25 @@ import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
+import com.google.common.collect.ImmutableSet;
import com.google.gson.JsonSyntaxException;
import org.apache.commons.fileupload.FileItem;
+import org.eclipse.che.api.core.ApiException;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.core.ConflictException;
import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
+import org.eclipse.che.api.core.model.factory.Factory;
import org.eclipse.che.api.core.model.project.ProjectConfig;
+import org.eclipse.che.api.core.model.user.User;
import org.eclipse.che.api.core.rest.Service;
-import org.eclipse.che.api.core.rest.shared.dto.Link;
import org.eclipse.che.api.factory.server.builder.FactoryBuilder;
-import org.eclipse.che.api.factory.server.snippet.SnippetGenerator;
-import org.eclipse.che.api.factory.shared.dto.Author;
-import org.eclipse.che.api.factory.shared.dto.Factory;
-import org.eclipse.che.api.user.server.spi.UserDao;
+import org.eclipse.che.api.factory.shared.dto.AuthorDto;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
+import org.eclipse.che.api.user.server.PreferenceManager;
+import org.eclipse.che.api.user.server.UserManager;
import org.eclipse.che.api.workspace.server.WorkspaceManager;
import org.eclipse.che.api.workspace.server.model.impl.ProjectConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl;
@@ -39,7 +42,7 @@ import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.lang.NameGenerator;
import org.eclipse.che.commons.lang.Pair;
import org.eclipse.che.commons.lang.URLEncodedUtils;
-import org.eclipse.che.commons.subject.Subject;
+import org.eclipse.che.dto.server.DtoFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -56,29 +59,27 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.util.Arrays;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import static com.google.common.base.Strings.isNullOrEmpty;
+import static java.lang.Boolean.parseBoolean;
import static java.util.stream.Collectors.toList;
import static javax.ws.rs.core.HttpHeaders.CONTENT_DISPOSITION;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static javax.ws.rs.core.MediaType.MULTIPART_FORM_DATA;
import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
-import static org.eclipse.che.api.workspace.server.DtoConverter.asDto;
-import static org.eclipse.che.dto.server.DtoFactory.newDto;
+import static org.eclipse.che.api.factory.server.FactoryLinksHelper.createLinks;
/**
* Defines Factory REST API.
@@ -97,11 +98,6 @@ public class FactoryService extends Service {
*/
public static final String ERROR_NO_RESOLVER_AVAILABLE = "Cannot build factory with any of the provided parameters.";
- /**
- * If there is no parameter.
- */
- public static final String ERROR_NO_PARAMETERS = "Missing parameters";
-
/**
* Validate query parameter. If true, factory will be validated
*/
@@ -112,87 +108,71 @@ public class FactoryService extends Service {
*/
private final Set factoryParametersResolvers;
- private final FactoryStore factoryStore;
- private final FactoryEditValidator factoryEditValidator;
+ private final FactoryManager factoryManager;
+ private final UserManager userManager;
+ private final PreferenceManager preferenceManager;
+ private final FactoryEditValidator editValidator;
private final FactoryCreateValidator createValidator;
private final FactoryAcceptValidator acceptValidator;
- private final LinksHelper linksHelper;
private final FactoryBuilder factoryBuilder;
private final WorkspaceManager workspaceManager;
- private final UserDao userDao;
@Inject
- public FactoryService(FactoryStore factoryStore,
+ public FactoryService(FactoryManager factoryManager,
+ UserManager userManager,
+ PreferenceManager preferenceManager,
FactoryCreateValidator createValidator,
FactoryAcceptValidator acceptValidator,
- FactoryEditValidator factoryEditValidator,
- LinksHelper linksHelper,
+ FactoryEditValidator editValidator,
FactoryBuilder factoryBuilder,
WorkspaceManager workspaceManager,
- FactoryParametersResolverHolder factoryParametersResolverHolder,
- UserDao userDao) {
- this.factoryStore = factoryStore;
+ FactoryParametersResolverHolder factoryParametersResolverHolder) {
+ this.factoryManager = factoryManager;
+ this.userManager = userManager;
this.createValidator = createValidator;
+ this.preferenceManager = preferenceManager;
this.acceptValidator = acceptValidator;
- this.factoryEditValidator = factoryEditValidator;
- this.linksHelper = linksHelper;
+ this.editValidator = editValidator;
this.factoryBuilder = factoryBuilder;
this.workspaceManager = workspaceManager;
this.factoryParametersResolvers = factoryParametersResolverHolder.getFactoryParametersResolvers();
- this.userDao = userDao;
}
- /**
- * Save factory to storage and return stored data. Field 'factory' should contains factory information.
- * Fields with images should be named 'image'. Acceptable image size 100x100 pixels.
- *
- * @param formData
- * http request form data
- * @param uriInfo
- * url context
- * @return stored data
- * @throws ForbiddenException
- * when the user have no access rights for saving the factory
- * @throws ConflictException
- * when an error occurred during saving the factory
- * @throws BadRequestException
- * when image content cannot be read or is invalid
- * @throws ServerException
- * when any server errors occurs
- */
@POST
@Consumes(MULTIPART_FORM_DATA)
@Produces(APPLICATION_JSON)
- @ApiOperation(value = "Create a Factory and return data",
- notes = "Save factory to storage and return stored data. Field 'factory' should contains factory information.")
- @ApiResponses({@ApiResponse(code = 200, message = "OK"),
- @ApiResponse(code = 400, message = "Parameters are not valid: missing required parameter(s)"),
- @ApiResponse(code = 403, message = "You do not have the permissions to perform a Factory save operation"),
- @ApiResponse(code = 409, message = "Parameters are not valid: missing parameters causing conflict"),
- @ApiResponse(code = 500, message = "Unable to identify user from context")})
- public Factory saveFactory(Iterator formData, @Context UriInfo uriInfo)
- throws ForbiddenException, ConflictException, BadRequestException, ServerException, NotFoundException {
+ @ApiOperation(value = "Create a new factory based on configuration and factory images",
+ notes = "The field 'factory' is required")
+ @ApiResponses({@ApiResponse(code = 200, message = "Factory successfully created"),
+ @ApiResponse(code = 400, message = "Missed required parameters, parameters are not valid"),
+ @ApiResponse(code = 403, message = "The user does not have rights to create factory"),
+ @ApiResponse(code = 409, message = "When factory with given name and creator already exists"),
+ @ApiResponse(code = 500, message = "Internal server error occurred")})
+ public FactoryDto saveFactory(Iterator formData) throws ForbiddenException,
+ ConflictException,
+ BadRequestException,
+ ServerException {
try {
final Set images = new HashSet<>();
- Factory factory = null;
+ FactoryDto factory = null;
while (formData.hasNext()) {
final FileItem item = formData.next();
switch (item.getFieldName()) {
case ("factory"): {
try (InputStream factoryData = item.getInputStream()) {
factory = factoryBuilder.build(factoryData);
- } catch (JsonSyntaxException e) {
- throw new BadRequestException("You have provided an invalid JSON.");
+ } catch (JsonSyntaxException ex) {
+ throw new BadRequestException("Invalid JSON value of the field 'factory' provided");
}
break;
}
case ("image"): {
try (InputStream imageData = item.getInputStream()) {
- final FactoryImage factoryImage = FactoryImage.createImage(imageData,
- item.getContentType(),
- NameGenerator.generate(null, 16));
- if (factoryImage.hasContent()) {
- images.add(factoryImage);
+ final FactoryImage image = createImage(imageData,
+ item.getContentType(),
+ NameGenerator.generate(null, 16));
+ if (image.hasContent()) {
+ images.add(image);
}
}
break;
@@ -201,530 +181,351 @@ public class FactoryService extends Service {
//DO NOTHING
}
}
- if (factory == null) {
- LOG.warn("No factory information found in 'factory' section of multipart form-data.");
- throw new BadRequestException("No factory information found in 'factory' section of multipart/form-data.");
- }
+ requiredNotNull(factory, "factory configuration");
processDefaults(factory);
createValidator.validateOnCreate(factory);
- final Factory storedFactory = factoryStore.getFactory(factoryStore.saveFactory(factory, images));
- return storedFactory.withLinks(createLinks(storedFactory, images, uriInfo));
- } catch (IOException e) {
- LOG.error(e.getLocalizedMessage(), e);
- throw new ServerException(e.getLocalizedMessage(), e);
+ return injectLinks(asDto(factoryManager.saveFactory(factory, images)), images);
+ } catch (IOException ioEx) {
+ throw new ServerException(ioEx.getLocalizedMessage(), ioEx);
}
}
- /**
- * Save factory to storage and return stored data.
- *
- * @param factory
- * instance of factory which would be stored
- * @return decorated the factory instance of which has been stored
- * @throws BadRequestException
- * when stored the factory is invalid
- * @throws ServerException
- * when any server errors occurs
- * @throws ForbiddenException
- * when the user have no access rights for saving the factory
- * @throws ConflictException
- * when stored the factory is already exist
- */
@POST
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
- @ApiOperation(value = "Stores the factory from the configuration",
- notes = "Stores the factory without pictures and returns instance of the stored factory with links")
- @ApiResponses({@ApiResponse(code = 200, message = "OK"),
- @ApiResponse(code = 400, message = "Parameters are not valid: missing required parameter(s)"),
- @ApiResponse(code = 403, message = "You do not have the permissions to perform a Factory save operation"),
- @ApiResponse(code = 409, message = "Parameters are not valid: missing parameters causing conflict"),
- @ApiResponse(code = 500, message = "Internal Server Error")})
- public Factory saveFactory(Factory factory)
- throws BadRequestException, ServerException, ForbiddenException, ConflictException, NotFoundException {
- if (factory == null) {
- throw new BadRequestException("Not null factory required");
- }
+ @ApiOperation(value = "Create a new factory based on configuration",
+ notes = "Factory will be created without images")
+ @ApiResponses({@ApiResponse(code = 200, message = "Factory successfully created"),
+ @ApiResponse(code = 400, message = "Missed required parameters, parameters are not valid"),
+ @ApiResponse(code = 403, message = "User does not have rights to create factory"),
+ @ApiResponse(code = 409, message = "When factory with given name and creator already exists"),
+ @ApiResponse(code = 500, message = "Internal server error occurred")})
+ public FactoryDto saveFactory(FactoryDto factory) throws BadRequestException,
+ ServerException,
+ ForbiddenException,
+ ConflictException {
+ requiredNotNull(factory, "Factory configuration");
factoryBuilder.checkValid(factory);
processDefaults(factory);
createValidator.validateOnCreate(factory);
- final Factory storedFactory = factoryStore.getFactory(factoryStore.saveFactory(factory, null));
- return storedFactory.withLinks(createLinks(storedFactory, null, uriInfo));
+ return injectLinks(asDto(factoryManager.saveFactory(factory)), null);
}
- /**
- * Get factory information from storage by specified id.
- *
- * @param id
- * id of factory
- * @param uriInfo
- * url context
- * @return the factory instance if it's found by id
- * @throws NotFoundException
- * when the factory with specified id doesn't not found
- * @throws ServerException
- * when any server errors occurs
- * @throws BadRequestException
- * when the factory is invalid e.g. is expired
- */
@GET
@Path("/{id}")
@Produces(APPLICATION_JSON)
- @ApiOperation(value = "Get factory information by its id",
- notes = "Get JSON with factory information. Factory id is passed in a path parameter")
- @ApiResponses({@ApiResponse(code = 200, message = "OK"),
- @ApiResponse(code = 404, message = "Factory not found"),
- @ApiResponse(code = 400, message = "Failed to validate factory e.g. if it expired"),
- @ApiResponse(code = 500, message = "Internal server error")})
- public Factory getFactory(@ApiParam(value = "Factory ID")
- @PathParam("id")
- String id,
- @ApiParam(value = "Whether or not to validate values like it is done when accepting a Factory",
- allowableValues = "true,false",
- defaultValue = "false")
- @DefaultValue("false")
- @QueryParam("validate")
- Boolean validate,
- @Context
- UriInfo uriInfo) throws NotFoundException, ServerException, BadRequestException {
- final Factory factory = factoryStore.getFactory(id);
- factory.setLinks(createLinks(factory, factoryStore.getFactoryImages(id, null), uriInfo));
+ @ApiOperation(value = "Get factory by its identifier",
+ notes = "If validate parameter is not specified, retrieved factory wont be validated")
+ @ApiResponses({@ApiResponse(code = 200, message = "Response contains requested factory entry"),
+ @ApiResponse(code = 400, message = "Missed required parameters, failed to validate factory"),
+ @ApiResponse(code = 404, message = "Factory with specified identifier does not exist"),
+ @ApiResponse(code = 500, message = "Internal server error occurred")})
+ public FactoryDto getFactory(@ApiParam(value = "Factory identifier")
+ @PathParam("id")
+ String factoryId,
+ @ApiParam(value = "Whether or not to validate values like it is done when accepting the factory",
+ allowableValues = "true, false",
+ defaultValue = "false")
+ @DefaultValue("false")
+ @QueryParam("validate")
+ Boolean validate) throws BadRequestException,
+ NotFoundException,
+ ServerException {
+ final FactoryDto factoryDto = asDto(factoryManager.getById(factoryId));
if (validate) {
- acceptValidator.validateOnAccept(factory);
+ acceptValidator.validateOnAccept(factoryDto);
}
- return factory;
+ return injectLinks(factoryDto, factoryManager.getFactoryImages(factoryId));
+ }
+
+ @GET
+ @Path("/find")
+ @Produces(APPLICATION_JSON)
+ @ApiOperation(value = "Get factory by attribute, " +
+ "the attribute must match one of the Factory model fields with type 'String', " +
+ "e.g. (factory.name, factory.creator.name)",
+ notes = "If specify more than one value for a single query parameter then will be taken the first one")
+ @ApiResponses({@ApiResponse(code = 200, message = "Response contains list requested factories"),
+ @ApiResponse(code = 400, message = "When query does not contain at least one attribute to search for"),
+ @ApiResponse(code = 500, message = "Internal server error")})
+ public List getFactoryByAttribute(@DefaultValue("0")
+ @QueryParam("skipCount")
+ Integer skipCount,
+ @DefaultValue("30")
+ @QueryParam("maxItems")
+ Integer maxItems,
+ @Context
+ UriInfo uriInfo) throws BadRequestException,
+ ServerException {
+ final Set skip = ImmutableSet.of("token", "skipCount", "maxItems");
+ final List> query = URLEncodedUtils.parse(uriInfo.getRequestUri())
+ .entrySet()
+ .stream()
+ .filter(param -> !skip.contains(param.getKey())
+ && !param.getValue().isEmpty())
+ .map(entry -> Pair.of(entry.getKey(), entry.getValue()
+ .iterator()
+ .next()))
+ .collect(toList());
+ checkArgument(!query.isEmpty(), "Query must contain at least one attribute");
+ final List factories = new ArrayList<>();
+ for (Factory factory : factoryManager.getByAttribute(maxItems, skipCount, query)) {
+ factories.add(injectLinks(asDto(factory), null));
+ }
+ return factories;
}
- /**
- * Updates specified factory with a new factory content.
- *
- * @param id
- * id of factory
- * @param newFactory
- * the new data for the factory
- * @return updated factory with links
- * @throws BadRequestException
- * when the factory config is invalid
- * @throws NotFoundException
- * when the factory with specified id doesn't not found
- * @throws ServerException
- * when any server error occurs
- * @throws ForbiddenException
- * when the current user is not granted to edit the factory
- * @throws ConflictException
- * when not rewritable factory information is present in the new factory
- */
@PUT
@Path("/{id}")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
- @ApiOperation(value = "Updates factory information by its id",
- notes = "Updates factory based on the factory id which is passed in a path parameter. " +
+ @ApiOperation(value = "Update factory information by configuration and specified identifier",
+ notes = "Update factory based on the factory id which is passed in a path parameter. " +
"For perform this operation user needs respective rights")
- @ApiResponses({@ApiResponse(code = 200, message = "OK"),
- @ApiResponse(code = 400, message = "Parameters are not valid: missing required parameter(s)"),
- @ApiResponse(code = 403, message = "You do not have the permissions to perform a Factory save operation"),
- @ApiResponse(code = 409, message = "The factory information is not updateable"),
+ @ApiResponses({@ApiResponse(code = 200, message = "Factory successfully updated"),
+ @ApiResponse(code = 400, message = "Missed required parameters, parameters are not valid"),
+ @ApiResponse(code = 403, message = "User does not have rights to update factory"),
@ApiResponse(code = 404, message = "Factory to update not found"),
+ @ApiResponse(code = 409, message = "Conflict error occurred during factory update" +
+ "(e.g. Factory with such name and creator already exists)"),
@ApiResponse(code = 500, message = "Internal server error")})
- public Factory updateFactory(@ApiParam(value = "Factory id")
- @PathParam("id")
- String id,
- Factory newFactory)
- throws BadRequestException, NotFoundException, ServerException, ForbiddenException, ConflictException {
- // forbid null update
- if (newFactory == null) {
- throw new BadRequestException("The factory information is not updateable");
- }
- final Factory existingFactory = factoryStore.getFactory(id);
-
+ public FactoryDto updateFactory(@ApiParam(value = "Factory identifier")
+ @PathParam("id")
+ String factoryId,
+ FactoryDto update) throws BadRequestException,
+ NotFoundException,
+ ServerException,
+ ForbiddenException,
+ ConflictException {
+ requiredNotNull(update, "Factory configuration");
+ update.setId(factoryId);
+ final Factory existing = factoryManager.getById(factoryId);
// check if the current user has enough access to edit the factory
- factoryEditValidator.validate(existingFactory);
-
- processDefaults(newFactory);
- newFactory.getCreator().withCreated(existingFactory.getCreator().getCreated());
- newFactory.setId(existingFactory.getId());
-
+ editValidator.validate(existing);
+ factoryBuilder.checkValid(update, true);
// validate the new content
- factoryBuilder.checkValid(newFactory, true);
- createValidator.validateOnCreate(newFactory);
-
- // access granted, user can update the factory
- factoryStore.updateFactory(id, newFactory);
- newFactory.setLinks(createLinks(newFactory, factoryStore.getFactoryImages(id, null), uriInfo));
- return newFactory;
+ createValidator.validateOnCreate(update);
+ return injectLinks(asDto(factoryManager.updateFactory(update)),
+ factoryManager.getFactoryImages(factoryId));
}
- /**
- * Removes factory information from storage by its id.
- *
- * @param id
- * id of factory
- * @param uriInfo
- * url context
- * @throws NotFoundException
- * when the factory with specified id doesn't not found
- * @throws ServerException
- * when any server errors occurs
- * @throws ForbiddenException
- * when user does not have permission for removal the factory
- */
@DELETE
@Path("/{id}")
- @ApiOperation(value = "Removes factory by its id",
+ @ApiOperation(value = "Removes factory by its identifier",
notes = "Removes factory based on the factory id which is passed in a path parameter. " +
"For perform this operation user needs respective rights")
- @ApiResponses({@ApiResponse(code = 200, message = "OK"),
- @ApiResponse(code = 403, message = "You do not have the permissions to perform a Factory remove operation"),
+ @ApiResponses({@ApiResponse(code = 200, message = "Factory successfully removed"),
+ @ApiResponse(code = 403, message = "User not authorized to call this operation"),
@ApiResponse(code = 404, message = "Factory not found"),
@ApiResponse(code = 500, message = "Internal server error")})
- public void removeFactory(@ApiParam(value = "Factory id")
+ public void removeFactory(@ApiParam(value = "Factory identifier")
@PathParam("id")
- String id,
- @Context
- UriInfo uriInfo) throws NotFoundException, ServerException, ForbiddenException {
- final Factory factory = factoryStore.getFactory(id);
-
- // check if the current user has enough access to edit the factory
- factoryEditValidator.validate(factory);
-
- // if validator didn't fail it means that the access is granted
- factoryStore.removeFactory(id);
+ String id) throws ForbiddenException,
+ ServerException {
+ factoryManager.removeFactory(id);
}
- /**
- * Get list of factories which conform specified attributes.
- *
- * @param maxItems
- * max number of items in response
- * @param skipCount
- * skip items. Must be equals or greater then {@code 0}
- * @param uriInfo
- * url context
- * @return stored data, if specified attributes is correct
- * @throws BadRequestException
- * when no search attributes passed
- */
- @GET
- @Path("/find")
- @Produces(APPLICATION_JSON)
- @ApiOperation(value = "Get Factory by attribute",
- notes = "If specify more than one value for a single query parameter then will be taken first one")
- @ApiResponses({@ApiResponse(code = 200, message = "OK"),
- @ApiResponse(code = 400, message = "No search parameters provided"),
- @ApiResponse(code = 500, message = "Internal server error")})
- public List getFactoryByAttribute(@DefaultValue("0")
- @QueryParam("skipCount")
- Integer skipCount,
- @DefaultValue("30")
- @QueryParam("maxItems")
- Integer maxItems,
- @Context
- UriInfo uriInfo) throws BadRequestException {
- final List skipParams = Arrays.asList("token", "skipCount", "maxItems");
- final List> queryParams = URLEncodedUtils.parse(uriInfo.getRequestUri()).entrySet().stream()
- .filter(entry -> !skipParams.contains(entry.getKey()) &&
- !entry.getValue().isEmpty())
- .map(entry -> Pair.of(entry.getKey(),
- entry.getValue().iterator().next()))
- .collect(toList());
- if (queryParams.isEmpty()) {
- throw new BadRequestException("Query must contain at least one attribute.");
- }
-
- return factoryStore.findByAttribute(maxItems, skipCount, queryParams);
- }
-
- /**
- * Get image information by its id from specified factory.
- *
- * @param id
- * id of factory
- * @param imageId
- * image id
- * @return image information if ids are correct. If imageId is not set, random image of the factory will be returned,
- * if factory has no images, exception will be thrown
- * @throws NotFoundException
- * when the factory with specified id doesn't not found
- * @throws NotFoundException
- * when image id is not specified and there is no default image for the specified factory
- * @throws NotFoundException
- * when image with specified id doesn't exist
- */
@GET
@Path("/{id}/image")
@Produces("image/*")
- @ApiOperation(value = "Get factory image information",
- notes = "If the factory does not have image with specified id then first found image will be returned")
- @ApiResponses({@ApiResponse(code = 200, message = "OK"),
- @ApiResponse(code = 404, message = "Factory or image id not found")})
- public Response getImage(@ApiParam(value = "Factory id")
+ @ApiOperation(value = "Get factory image",
+ notes = "If image identifier is not specified then first found image will be returned")
+ @ApiResponses({@ApiResponse(code = 200, message = "Response contains requested factory image"),
+ @ApiResponse(code = 400, message = "Missed required parameters, parameters are not valid"),
+ @ApiResponse(code = 404, message = "Factory or factory image not found"),
+ @ApiResponse(code = 500, message = "Internal server error")})
+ public Response getImage(@ApiParam(value = "Factory identifier")
@PathParam("id")
- String id,
- @ApiParam(value = "Image id", required = true)
+ String factoryId,
+ @ApiParam(value = "Image identifier")
@QueryParam("imgId")
- String imageId) throws NotFoundException {
- final Set factoryImages = factoryStore.getFactoryImages(id, null);
+ String imageId) throws NotFoundException,
+ BadRequestException,
+ ServerException {
+ final Set images;
if (isNullOrEmpty(imageId)) {
- if (factoryImages.isEmpty()) {
- LOG.warn("Default image for factory {} is not found.", id);
- throw new NotFoundException("Default image for factory " + id + " is not found.");
+ if ((images = factoryManager.getFactoryImages(factoryId)).isEmpty()) {
+ LOG.warn("Default image for factory {} is not found.", factoryId);
+ throw new NotFoundException("Default image for factory " + factoryId + " is not found.");
}
- final FactoryImage image = factoryImages.iterator().next();
- return Response.ok(image.getImageData(), image.getMediaType()).build();
- }
- for (FactoryImage image : factoryImages) {
- if (imageId.equals(image.getName())) {
- return Response.ok(image.getImageData(), image.getMediaType()).build();
+ } else {
+ if ((images = factoryManager.getFactoryImages(factoryId, imageId)).isEmpty()) {
+ LOG.warn("Image with id {} is not found.", imageId);
+ throw new NotFoundException("Image with id " + imageId + " is not found.");
}
}
- LOG.warn("Image with id {} is not found.", imageId);
- throw new NotFoundException("Image with id " + imageId + " is not found.");
+ final FactoryImage image = images.iterator().next();
+ return Response.ok(image.getImageData(), image.getMediaType()).build();
}
- /**
- * Get factory snippet by factory id and snippet type. If snippet type is not set, "url" type will be used as default.
- *
- * @param id
- * id of factory
- * @param type
- * type of snippet
- * @param uriInfo
- * url context
- * @return snippet content.
- * @throws NotFoundException
- * when factory with specified id doesn't not found - with response code 400
- * @throws ServerException
- * when any server error occurs during snippet creation
- * @throws BadRequestException
- * when the snippet type is not supported,
- * or if the specified factory does not contain enough information for snippet creation
- */
@GET
@Path("/{id}/snippet")
@Produces(TEXT_PLAIN)
- @ApiOperation(value = "Get factory snippet by id",
- notes = "If snippet type not set then default 'url' will be used")
- @ApiResponses({@ApiResponse(code = 200, message = "OK"),
- @ApiResponse(code = 400, message = "Parameters are not valid: missing required parameter(s)"),
- @ApiResponse(code = 404, message = "Factory or factory images not found"),
+ @ApiOperation(value = "Get factory snippet",
+ notes = "If snippet type is not specified then default 'url' will be used")
+ @ApiResponses({@ApiResponse(code = 200, message = "Response contains requested factory snippet"),
+ @ApiResponse(code = 400, message = "Missed required parameters, parameters are not valid"),
+ @ApiResponse(code = 404, message = "Factory or factory snippet not found"),
@ApiResponse(code = 500, message = "Internal server error")})
- public String getFactorySnippet(@ApiParam(value = "Factory ID")
+ public String getFactorySnippet(@ApiParam(value = "Factory identifier")
@PathParam("id")
- String id,
+ String factoryId,
@ApiParam(value = "Snippet type",
required = true,
- allowableValues = "url,html,iframe,markdown",
+ allowableValues = "url, html, iframe, markdown",
defaultValue = "url")
@DefaultValue("url")
@QueryParam("type")
- String type,
- @Context
- UriInfo uriInfo) throws NotFoundException, ServerException, BadRequestException {
- final Factory factory = factoryStore.getFactory(id);
- final String baseUrl = UriBuilder.fromUri(uriInfo.getBaseUri()).replacePath("").build().toString();
- switch (type) {
- case "url":
- return UriBuilder.fromUri(uriInfo.getBaseUri()).replacePath("factory").queryParam("id", id).build().toString();
- case "html":
- return SnippetGenerator.generateHtmlSnippet(baseUrl, id);
- case "iframe":
- return SnippetGenerator.generateiFrameSnippet(baseUrl, id);
- case "markdown":
- final Set factoryImages = factoryStore.getFactoryImages(id, null);
- final String imageId = (factoryImages.size() > 0) ? factoryImages.iterator().next().getName() : null;
- try {
- return SnippetGenerator.generateMarkdownSnippet(baseUrl, factory, imageId);
- } catch (IllegalArgumentException e) {
- throw new BadRequestException(e.getLocalizedMessage());
- }
- default:
- LOG.warn("Snippet type {} is unsupported", type);
- throw new BadRequestException("Snippet type \"" + type + "\" is unsupported.");
- }
+ String type) throws NotFoundException,
+ BadRequestException,
+ ServerException {
+ final String factorySnippet = factoryManager.getFactorySnippet(factoryId, type, uriInfo.getBaseUri());
+ checkArgument(factorySnippet != null, "Snippet type \"" + type + "\" is unsupported.");
+ return factorySnippet;
}
- /**
- * Generate factory containing workspace configuration.
- * Only projects that have {@code SourceStorage} configured can be included.
- *
- * @param workspace
- * workspace id to generate factory from
- * @param path
- * optional project path, if set, only this project will be included into result projects set
- * @throws ServerException
- * when any server error occurs during factory getting
- * @throws BadRequestException
- * when it is impossible get factory from specified workspace e.g. no projects in workspace
- * @throws NotFoundException
- * when user's workspace with specified id not found
- * @throws ForbiddenException
- * when user have no access rights e.g. user is not owner of specified workspace
- */
@GET
@Path("/workspace/{ws-id}")
@Produces(APPLICATION_JSON)
@ApiOperation(value = "Construct factory from workspace",
- notes = "This call returns a Factory.json that is used to create a factory.")
- @ApiResponses({@ApiResponse(code = 200, message = "OK"),
- @ApiResponse(code = 400, message = "Parameters are not valid: missing required parameter(s)"),
- @ApiResponse(code = 403, message = "Access to workspace denied"),
+ notes = "This call returns a Factory.json that is used to create a factory")
+ @ApiResponses({@ApiResponse(code = 200, message = "Response contains requested factory JSON"),
+ @ApiResponse(code = 400, message = "Missed required parameters, parameters are not valid"),
@ApiResponse(code = 404, message = "Workspace not found"),
@ApiResponse(code = 500, message = "Internal server error")})
- public Response getFactoryJson(@ApiParam(value = "Workspace ID")
+ public Response getFactoryJson(@ApiParam(value = "Workspace identifier")
@PathParam("ws-id")
- String workspace,
+ String wsId,
@ApiParam(value = "Project path")
@QueryParam("path")
- String path)
- throws ServerException, BadRequestException, NotFoundException, ForbiddenException {
- final WorkspaceImpl usersWorkspace = workspaceManager.getWorkspace(workspace);
- excludeProjectsWithoutLocation(usersWorkspace, path);
- final Factory factory = newDto(Factory.class).withWorkspace(asDto(usersWorkspace.getConfig())).withV("4.0");
- return Response.ok(factory, APPLICATION_JSON)
+ String path) throws BadRequestException,
+ NotFoundException,
+ ServerException {
+ final WorkspaceImpl workspace = workspaceManager.getWorkspace(wsId);
+ excludeProjectsWithoutLocation(workspace, path);
+ final FactoryDto factoryDto = DtoFactory.newDto(FactoryDto.class)
+ .withV("4.0")
+ .withWorkspace(org.eclipse.che.api.workspace.server.DtoConverter
+ .asDto(workspace.getConfig()));
+ return Response.ok(factoryDto, APPLICATION_JSON)
.header(CONTENT_DISPOSITION, "attachment; filename=factory.json")
.build();
}
-
- /**
- * Resolve parameters and build a factory for the given parameters
- *
- * @param parameters
- * map of key/values used to build factory.
- * @param uriInfo
- * url context
- * @return a factory instance if found a matching resolver
- * @throws NotFoundException
- * when no resolver can be used
- * @throws ServerException
- * when any server errors occurs
- * @throws BadRequestException
- * when the factory is invalid e.g. is expired
- */
@POST
@Path("/resolver")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
@ApiOperation(value = "Create factory by providing map of parameters",
- notes = "Get JSON with factory information.")
- @ApiResponses({@ApiResponse(code = 200, message = "OK"),
- @ApiResponse(code = 400, message = "Failed to validate factory"),
+ notes = "Get JSON with factory information")
+ @ApiResponses({@ApiResponse(code = 200, message = "Factory successfully built from parameters"),
+ @ApiResponse(code = 400, message = "Missed required parameters, failed to validate factory"),
@ApiResponse(code = 500, message = "Internal server error")})
- public Factory resolveFactory(
- @ApiParam(value = "Parameters provided to create factories")
- final Map parameters,
- @ApiParam(value = "Whether or not to validate values like it is done when accepting a Factory",
- allowableValues = "true,false",
- defaultValue = "false")
- @DefaultValue("false")
- @QueryParam(VALIDATE_QUERY_PARAMETER)
- final Boolean validate,
- @Context
- final UriInfo uriInfo) throws NotFoundException, ServerException, BadRequestException {
+ public FactoryDto resolveFactory(@ApiParam(value = "Parameters provided to create factories")
+ Map parameters,
+ @ApiParam(value = "Whether or not to validate values like it is done when accepting a Factory",
+ allowableValues = "true,false",
+ defaultValue = "false")
+ @DefaultValue("false")
+ @QueryParam(VALIDATE_QUERY_PARAMETER)
+ Boolean validate) throws ServerException,
+ BadRequestException {
- // Check parameter
- if (parameters == null) {
- throw new BadRequestException(ERROR_NO_PARAMETERS);
- }
+ // check parameter
+ requiredNotNull(parameters, "Factory build parameters");
- // search matching resolver
- Optional factoryParametersResolverOptional = this.factoryParametersResolvers.stream().filter((resolver -> resolver.accept(parameters))).findFirst();
-
- // no match
- if (!factoryParametersResolverOptional.isPresent()) {
- throw new NotFoundException(ERROR_NO_RESOLVER_AVAILABLE);
- }
-
- // create factory from matching resolver
- final Factory factory = factoryParametersResolverOptional.get().createFactory(parameters);
-
- // Apply links
- try {
- factory.setLinks(linksHelper.createLinks(factory, uriInfo, null));
- } catch (UnsupportedEncodingException e) {
- throw new ServerException(e.getLocalizedMessage(), e);
- }
-
- // time to validate the factory
- if (validate) {
- acceptValidator.validateOnAccept(factory);
- }
-
- return factory;
- }
-
- /**
- * Creates factory links.
- *
- * If factory is named it will be generated accept named link,
- * if images set is not null and not empty it will be generate links for them
- */
- private List createLinks(Factory factory, Set images, UriInfo uriInfo) throws NotFoundException, ServerException {
- try {
- String username = null;
- if (!isNullOrEmpty(factory.getName())) {
- username = userDao.getById(factory.getCreator().getUserId()).getName();
+ // search matching resolver and create factory from matching resolver
+ for (FactoryParametersResolver resolver : factoryParametersResolvers) {
+ if (resolver.accept(parameters)) {
+ final FactoryDto factory = resolver.createFactory(parameters);
+ if (validate) {
+ acceptValidator.validateOnAccept(factory);
+ }
+ return injectLinks(factory, null);
}
- return images != null && !images.isEmpty()
- ? linksHelper.createLinks(factory, images, uriInfo, username)
- : linksHelper.createLinks(factory, uriInfo, username);
-
- } catch (UnsupportedEncodingException e) {
- throw new ServerException(e.getLocalizedMessage(), e);
}
+ // no match
+ throw new BadRequestException(ERROR_NO_RESOLVER_AVAILABLE);
}
/**
- * Filters workspace projects, removes projects which don't have location set.
- * If all workspace projects don't have location throws {@link BadRequestException}.
+ * Injects factory links. If factory is named then accept named link will be injected,
+ * if {@code images} is not null and not empty then image links will be injected
*/
- private void excludeProjectsWithoutLocation(WorkspaceImpl usersWorkspace, String projectPath) throws BadRequestException {
+ private FactoryDto injectLinks(FactoryDto factory, Set images) {
+ String username = null;
+ if (factory.getCreator() != null && factory.getCreator().getUserId() != null) {
+ try {
+ username = userManager.getById(factory.getCreator().getUserId()).getName();
+ } catch (ApiException ignored) {
+ // when impossible to get username then named factory link won't be injected
+ }
+ }
+ return factory.withLinks(images != null && !images.isEmpty()
+ ? createLinks(factory, images, getServiceContext(), username)
+ : createLinks(factory, getServiceContext(), username));
+ }
+
+ /**
+ * Filters workspace projects and removes projects without source location.
+ * If there is no at least one project with source location then {@link BadRequestException} will be thrown
+ */
+ private static void excludeProjectsWithoutLocation(WorkspaceImpl usersWorkspace, String projectPath) throws BadRequestException {
final boolean notEmptyPath = projectPath != null;
//Condition for sifting valid project in user's workspace
Predicate predicate = projectConfig -> {
- // if project is a subproject (it's path contains another project) , then location can be null
+ // if project is a sub project (it's path contains another project) , then location can be null
final boolean isSubProject = projectConfig.getPath().indexOf('/', 1) != -1;
final boolean hasNotEmptySource = projectConfig.getSource() != null
- && projectConfig.getSource().getType() != null
- && projectConfig.getSource().getLocation() != null;
+ && projectConfig.getSource().getType() != null
+ && projectConfig.getSource().getLocation() != null;
return !(notEmptyPath && !projectPath.equals(projectConfig.getPath()))
- && (isSubProject ? true : hasNotEmptySource);
+ && (isSubProject || hasNotEmptySource);
};
- //Filtered out projects by path and source storage presence.
+ // Filtered out projects by path and source storage presence
final List filtered = usersWorkspace.getConfig()
.getProjects()
.stream()
.filter(predicate)
.collect(toList());
- if (filtered.isEmpty()) {
- throw new BadRequestException("Unable to create factory from this workspace, " +
- "because it does not contains projects with source storage set and/or specified path");
- }
+ checkArgument(!filtered.isEmpty(), "Unable to create factory from this workspace, " +
+ "because it does not contains projects with source storage");
usersWorkspace.getConfig().setProjects(filtered);
}
/**
- * Adds to the factory information about creator and time of creation
+ * Checks the current user if it is not temporary then
+ * adds to the factory creator information and time of creation
*/
- private void processDefaults(Factory factory) {
- final Subject currentSubject = EnvironmentContext.getCurrent().getSubject();
- final Author creator = factory.getCreator();
- if (creator == null) {
- factory.setCreator(newDto(Author.class).withUserId(currentSubject.getUserId())
- .withCreated(System.currentTimeMillis()));
- return;
- }
- if (isNullOrEmpty(creator.getUserId())) {
- creator.setUserId(currentSubject.getUserId());
- }
- if (creator.getCreated() == null) {
- creator.setCreated(System.currentTimeMillis());
+ private void processDefaults(FactoryDto factory) throws ForbiddenException {
+ try {
+ final String userId = EnvironmentContext.getCurrent().getSubject().getUserId();
+ final User user = userManager.getById(userId);
+ if (user == null || parseBoolean(preferenceManager.find(userId).get("temporary"))) {
+ throw new ForbiddenException("Current user is not allowed to use this method.");
+ }
+ factory.setCreator(DtoFactory.newDto(AuthorDto.class)
+ .withUserId(userId)
+ .withName(user.getName())
+ .withEmail(user.getEmail())
+ .withCreated(System.currentTimeMillis()));
+ } catch (NotFoundException | ServerException ex) {
+ throw new ForbiddenException("Current user is not allowed to use this method");
}
}
+ /**
+ * Converts {@link Factory} to dto object
+ */
+ private FactoryDto asDto(Factory factory) throws ServerException {
+ try {
+ return DtoConverter.asDto(factory, userManager.getById(factory.getCreator().getUserId()));
+ } catch (ServerException | NotFoundException ex) {
+ throw new ServerException("Failed to retrieve factory creator");
+ }
+ }
/**
* Usage of a dedicated class to manage the optional resolvers
@@ -739,6 +540,7 @@ public class FactoryService extends Service {
/**
* Provides the set of resolvers if there are some else return an empty set.
+ *
* @return a non null set
*/
public Set getFactoryParametersResolvers() {
@@ -748,6 +550,72 @@ public class FactoryService extends Service {
return Collections.emptySet();
}
}
+ }
+ /**
+ * Creates factory image from input stream.
+ * InputStream should be closed manually.
+ *
+ * @param is
+ * input stream with image data
+ * @param mediaType
+ * media type of image
+ * @param name
+ * image name
+ * @return factory image, if {@param is} has no content then empty factory image will be returned
+ * @throws BadRequestException
+ * when factory image exceeded maximum size
+ * @throws ServerException
+ * when any server errors occurs
+ */
+ public static FactoryImage createImage(InputStream is, String mediaType, String name) throws BadRequestException,
+ ServerException {
+ try {
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ final byte[] buffer = new byte[1024];
+ int read;
+ while ((read = is.read(buffer, 0, buffer.length)) != -1) {
+ out.write(buffer, 0, read);
+ if (out.size() > 1024 * 1024) {
+ throw new BadRequestException("Maximum upload size exceeded.");
+ }
+ }
+
+ if (out.size() == 0) {
+ return new FactoryImage();
+ }
+ out.flush();
+
+ return new FactoryImage(out.toByteArray(), mediaType, name);
+ } catch (IOException ioEx) {
+ throw new ServerException(ioEx.getLocalizedMessage());
+ }
+ }
+
+ /**
+ * Checks object reference is not {@code null}
+ *
+ * @param object
+ * object reference to check
+ * @param subject
+ * used as subject of exception message "{subject} required"
+ * @throws BadRequestException
+ * when object reference is {@code null}
+ */
+ private static void requiredNotNull(Object object, String subject) throws BadRequestException {
+ if (object == null) {
+ throw new BadRequestException(subject + " required");
+ }
+ }
+
+ /**
+ * Checks that expression is true, throws {@link BadRequestException} otherwise.
+ *
+ *
Exception uses error message built from error message template and error message parameters.
+ */
+ private static void checkArgument(boolean expression, String errorMessage) throws BadRequestException {
+ if (!expression) {
+ throw new BadRequestException(errorMessage);
+ }
}
}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryStore.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryStore.java
deleted file mode 100644
index ee0b503e8f..0000000000
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryStore.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012-2016 Codenvy, S.A.
- * 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
- *
- * Contributors:
- * Codenvy, S.A. - initial API and implementation
- *******************************************************************************/
-package org.eclipse.che.api.factory.server;
-
-import org.eclipse.che.api.core.ConflictException;
-import org.eclipse.che.api.core.NotFoundException;
-import org.eclipse.che.api.core.ServerException;
-import org.eclipse.che.api.factory.shared.dto.Factory;
-import org.eclipse.che.commons.lang.Pair;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * Interface for CRUD operations with factory data.
- *
- * @author Max Shaposhnik
- */
-
-public interface FactoryStore {
- /**
- * Save factory at storage.
- *
- * @param factory
- * factory information
- * @param images
- * factory images
- * @return id of stored factory
- * @throws java.lang.RuntimeException
- * if {@code factory} is null
- * @throws org.eclipse.che.api.core.ConflictException
- * if {@code factory} with given name and creator already exists
- * @throws org.eclipse.che.api.core.ServerException
- * if other error occurs
- */
- public String saveFactory(Factory factory, Set images) throws ConflictException, ServerException;
-
- /**
- * Remove factory by id
- *
- * @param factoryId
- * - id of factory to remove
- * @throws org.eclipse.che.api.core.NotFoundException
- * if factory with given {@code factoryId} is not found
- * @throws java.lang.RuntimeException
- * if {@code factoryId} is null
- * @throws org.eclipse.che.api.core.ServerException
- * if other error occurs
- */
- public void removeFactory(String factoryId) throws NotFoundException, ServerException;
-
- /**
- * Retrieve factory data by its id
- *
- * @param factoryId
- * - factory id
- * @return - {@code AdvancedFactoryUrl} if factory exist and found
- * @throws org.eclipse.che.api.core.NotFoundException
- * if factory with given {@code factoryId} is not found
- * @throws java.lang.RuntimeException
- * if {@code factoryId} is null
- * @throws org.eclipse.che.api.core.ServerException
- * if other error occurs
- *
- */
- public Factory getFactory(String factoryId) throws NotFoundException, ServerException;
-
- /**
- * Retrieve factory by given list of pairs of attribute names and values.
- *
- * @param maxItems
- * max number of items in response.
- * @param skipCount
- * skip items. Must be equals or greater then {@code 0}. IllegalArgumentException thrown otherwise.
- * @param attributes
- * attribute pairs to search for
- *
- * @return - List {@code AdvancedFactoryUrl} if factory(s) exist and found, empty list otherwise
- * @throws org.eclipse.che.api.core.IllegalArgumentException
- * if {@code skipCount} is negative
- *
- */
- public List findByAttribute(int maxItems, int skipCount, List> attributes) throws IllegalArgumentException;
-
- /**
- * Retrieve factory images by factory id
- *
- * @param factoryId
- * factory id. Must not be null.
- * @param imageId
- * id of the requested image. When null, all images for given factory will be returned.
- * @return {@code Set} of images if factory found, empty set otherwise
- * @throws java.lang.RuntimeException
- * if {@code factoryId} is null
- * @throws org.eclipse.che.api.core.NotFoundException
- * if factory with given {@code factoryId} is not found
- */
- public Set getFactoryImages(String factoryId, String imageId) throws NotFoundException;
-
- /**
- * Update factory at storage.
- *
- * @param factoryId
- * factory id to update. Must not be null.
- * @param factory
- * factory information. Must not be null.
- * @return id of stored factory
- * @throws org.eclipse.che.api.core.NotFoundException
- * if factory with given {@code factoryId} is not found
- * @throws org.eclipse.che.api.core.ConflictException
- * if {@code factory} with given name and creator already exists
- * @throws java.lang.RuntimeException
- * if {@code factory} is null
- */
- public String updateFactory(String factoryId, Factory factory) throws NotFoundException, ConflictException;
-
-}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/LegacyConverter.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/LegacyConverter.java
index e4733c75b4..4b3ecc4460 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/LegacyConverter.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/LegacyConverter.java
@@ -11,7 +11,7 @@
package org.eclipse.che.api.factory.server;
import org.eclipse.che.api.core.ApiException;
-import org.eclipse.che.api.factory.shared.dto.Factory;
+import org.eclipse.che.api.core.model.factory.Factory;
/**
* Convert legacy factory parameter to new the latest format
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/LinksHelper.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/LinksHelper.java
deleted file mode 100644
index 66a2b50cfd..0000000000
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/LinksHelper.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012-2016 Codenvy, S.A.
- * 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
- *
- * Contributors:
- * Codenvy, S.A. - initial API and implementation
- *******************************************************************************/
-package org.eclipse.che.api.factory.server;
-
-import com.google.common.base.Strings;
-import org.eclipse.che.api.core.rest.shared.dto.Link;
-import org.eclipse.che.api.core.rest.shared.dto.LinkParameter;
-import org.eclipse.che.api.factory.shared.dto.Factory;
-import org.eclipse.che.dto.server.DtoFactory;
-
-import javax.inject.Singleton;
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
-import static java.util.stream.Collectors.toCollection;
-import static java.util.stream.Collectors.toList;
-
-/** Helper class for creation links. */
-@Singleton
-public class LinksHelper {
-
- private static final String IMAGE_REL_ATT = "image";
- private static final String RETRIEVE_FACTORY_REL_ATT = "self";
- private static final String SNIPPET_REL_ATT = "snippet/";
- private static final String FACTORY_ACCEPTANCE_REL_ATT = "accept";
- private static final String NAMED_FACTORY_ACCEPTANCE_REL_ATT = "accept-named";
- private static final String ACCEPTED_REL_ATT = "accepted";
-
- private static List snippetTypes = Collections.unmodifiableList(Arrays.asList("markdown", "url", "html", "iframe"));
-
- /**
- * Creates factory links and links on factory images.
- *
- * @param images
- * a set of factory images
- * @param uriInfo
- * URI information about relative URIs are relative to the base URI
- * @return list of factory links
- * @throws UnsupportedEncodingException
- * occurs when impossible to encode URL
- */
- public List createLinks(Factory factory, Set images, UriInfo uriInfo, String userName) throws UnsupportedEncodingException {
- final List links = new LinkedList<>(createLinks(factory, uriInfo, userName));
- final UriBuilder baseUriBuilder = uriInfo != null ? UriBuilder.fromUri(uriInfo.getBaseUri()) : UriBuilder.fromUri("/");
-
- // add path to factory service
- final UriBuilder factoryUriBuilder = baseUriBuilder.clone().path(FactoryService.class);
- final String factoryId = factory.getId();
-
- // uri's to retrieve images
- links.addAll(images.stream()
- .map(image -> createLink(HttpMethod.GET,
- IMAGE_REL_ATT,
- null,
- image.getMediaType(),
- factoryUriBuilder.clone()
- .path(FactoryService.class, "getImage")
- .queryParam("imgId", image.getName())
- .build(factoryId)
- .toString()))
- .collect(toList()));
- return links;
- }
-
- /**
- * Creates factory links.
- *
- * @param uriInfo
- * URI information about relative URIs are relative to the base URI
- * @return list of factory links
- * @throws UnsupportedEncodingException
- * occurs when impossible to encode URL
- */
- public List createLinks(Factory factory, UriInfo uriInfo, String userName) throws UnsupportedEncodingException {
- final List links = new LinkedList<>();
- final UriBuilder baseUriBuilder = uriInfo != null ? UriBuilder.fromUri(uriInfo.getBaseUri()) : UriBuilder.fromUri("/");
-
- // add path to factory service
- final UriBuilder factoryUriBuilder = baseUriBuilder.clone().path(FactoryService.class);
- final String factoryId = factory.getId();
- if (factoryId != null) {
- // uri to retrieve factory
- links.add(createLink(HttpMethod.GET,
- RETRIEVE_FACTORY_REL_ATT,
- null,
- MediaType.APPLICATION_JSON,
- factoryUriBuilder.clone()
- .path(FactoryService.class, "getFactory")
- .build(factoryId)
- .toString()));
-
- // uri's of snippets
- links.addAll(snippetTypes.stream()
- .map(snippet -> createLink(HttpMethod.GET,
- SNIPPET_REL_ATT + snippet,
- null,
- MediaType.TEXT_PLAIN,
- factoryUriBuilder.clone()
- .path(FactoryService.class, "getFactorySnippet")
- .queryParam("type", snippet)
- .build(factoryId)
- .toString()))
- .collect(toList()));
-
- // uri to accept factory
- final Link createWorkspace = createLink(HttpMethod.GET,
- FACTORY_ACCEPTANCE_REL_ATT,
- null,
- MediaType.TEXT_HTML,
- baseUriBuilder.clone()
- .replacePath("f")
- .queryParam("id", factoryId)
- .build()
- .toString());
- links.add(createWorkspace);
-
-
- // links of analytics
- links.add(createLink(HttpMethod.GET,
- ACCEPTED_REL_ATT,
- null,
- MediaType.TEXT_PLAIN,
- baseUriBuilder.clone()
- .path("analytics")
- .path("public-metric/factory_used")
- .queryParam("factory", URLEncoder.encode(createWorkspace.getHref(), "UTF-8"))
- .build()
- .toString()));
- }
-
- if (!Strings.isNullOrEmpty(factory.getName()) && !Strings.isNullOrEmpty(userName)) {
- // uri to accept factory by name and creator
- final Link createWorkspaceFromNamedFactory = createLink(HttpMethod.GET,
- NAMED_FACTORY_ACCEPTANCE_REL_ATT,
- null,
- MediaType.TEXT_HTML,
- baseUriBuilder.clone()
- .replacePath("f")
- .queryParam("name", factory.getName())
- .queryParam("user", userName)
- .build()
- .toString());
- links.add(createWorkspaceFromNamedFactory);
- }
-
- return links;
- }
-
- /**
- * Find links with given relation.
- *
- * @param links
- * links for searching
- * @param relation
- * searching relation
- * @return set of links with relation equal to desired, empty set if there is no such links
- */
- public List getLinkByRelation(List links, String relation) {
- if (relation == null || links == null) {
- throw new IllegalArgumentException("Value of parameters can't be null.");
- }
- return links.stream()
- .filter(link -> relation.equals(link.getRel()))
- .collect(toCollection(LinkedList::new));
- }
-
- /** Creates factory Link */
- private Link createLink(String method, String rel, String consumes, String produces, String href) {
- return createLink(method, rel, consumes, produces, href, null);
- }
-
- /** Creates factory Link */
- private Link createLink(String method, String rel, String consumes, String produces, String href, List params) {
- return DtoFactory.getInstance()
- .createDto(Link.class)
- .withMethod(method)
- .withRel(rel)
- .withProduces(produces)
- .withConsumes(consumes)
- .withHref(href)
- .withParameters(params);
- }
-}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/builder/FactoryBuilder.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/builder/FactoryBuilder.java
index 127d656c24..89df05876b 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/builder/FactoryBuilder.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/builder/FactoryBuilder.java
@@ -21,8 +21,7 @@ import org.eclipse.che.api.factory.server.FactoryConstants;
import org.eclipse.che.api.factory.server.LegacyConverter;
import org.eclipse.che.api.factory.server.ValueHelper;
import org.eclipse.che.api.factory.server.impl.SourceStorageParametersValidator;
-import org.eclipse.che.api.factory.shared.dto.Factory;
-import org.eclipse.che.api.factory.shared.dto.FactoryV4_0;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.api.workspace.shared.dto.SourceStorageDto;
import org.eclipse.che.dto.server.DtoFactory;
import org.eclipse.che.dto.shared.DTO;
@@ -80,9 +79,9 @@ public class FactoryBuilder {
* - json Reader from encoded factory.
* @return - Factory object represented by given factory json.
*/
- public Factory build(Reader json) throws IOException, ApiException {
- Factory factory = DtoFactory.getInstance()
- .createDtoFromJson(json, Factory.class);
+ public FactoryDto build(Reader json) throws IOException, ApiException {
+ FactoryDto factory = DtoFactory.getInstance()
+ .createDtoFromJson(json, FactoryDto.class);
checkValid(factory);
return factory;
}
@@ -94,9 +93,9 @@ public class FactoryBuilder {
* - json string from encoded factory.
* @return - Factory object represented by given factory json.
*/
- public Factory build(String json) throws ApiException {
- Factory factory = DtoFactory.getInstance()
- .createDtoFromJson(json, Factory.class);
+ public FactoryDto build(String json) throws ApiException {
+ FactoryDto factory = DtoFactory.getInstance()
+ .createDtoFromJson(json, FactoryDto.class);
checkValid(factory);
return factory;
}
@@ -108,9 +107,9 @@ public class FactoryBuilder {
* - json InputStream from encoded factory.
* @return - Factory object represented by given factory json.
*/
- public Factory build(InputStream json) throws IOException, ConflictException {
- Factory factory = DtoFactory.getInstance()
- .createDtoFromJson(json, Factory.class);
+ public FactoryDto build(InputStream json) throws IOException, ConflictException {
+ FactoryDto factory = DtoFactory.getInstance()
+ .createDtoFromJson(json, FactoryDto.class);
checkValid(factory);
return factory;
}
@@ -122,7 +121,7 @@ public class FactoryBuilder {
* - factory object to validate
* @throws ConflictException
*/
- public void checkValid(Factory factory) throws ConflictException {
+ public void checkValid(FactoryDto factory) throws ConflictException {
checkValid(factory, false);
}
@@ -136,7 +135,7 @@ public class FactoryBuilder {
* Set-by-server variables are allowed during update.
* @throws ConflictException
*/
- public void checkValid(Factory factory, boolean isUpdate) throws ConflictException {
+ public void checkValid(FactoryDto factory, boolean isUpdate) throws ConflictException {
if (null == factory) {
throw new ConflictException(FactoryConstants.UNPARSABLE_FACTORY_MESSAGE);
}
@@ -154,12 +153,12 @@ public class FactoryBuilder {
Class usedFactoryVersionMethodProvider;
switch (v) {
case V4_0:
- usedFactoryVersionMethodProvider = FactoryV4_0.class;
+ usedFactoryVersionMethodProvider = FactoryDto.class;
break;
default:
throw new ConflictException(FactoryConstants.INVALID_VERSION_MESSAGE);
}
- validateCompatibility(factory, null, Factory.class, usedFactoryVersionMethodProvider, v, "", isUpdate);
+ validateCompatibility(factory, null, FactoryDto.class, usedFactoryVersionMethodProvider, v, "", isUpdate);
}
/**
@@ -170,8 +169,8 @@ public class FactoryBuilder {
* @return - factory in latest format.
* @throws org.eclipse.che.api.core.ApiException
*/
- public Factory convertToLatest(Factory factory) throws ApiException {
- Factory resultFactory = DtoFactory.getInstance().clone(factory).withV("4.0");
+ public FactoryDto convertToLatest(FactoryDto factory) throws ApiException {
+ FactoryDto resultFactory = DtoFactory.getInstance().clone(factory).withV("4.0");
for (LegacyConverter converter : LEGACY_CONVERTERS) {
converter.convert(resultFactory);
}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryAcceptValidatorImpl.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryAcceptValidatorImpl.java
index dacb658c6b..274bb67dd2 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryAcceptValidatorImpl.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryAcceptValidatorImpl.java
@@ -12,7 +12,7 @@ package org.eclipse.che.api.factory.server.impl;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.factory.server.FactoryAcceptValidator;
-import org.eclipse.che.api.factory.shared.dto.Factory;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.api.user.server.spi.PreferenceDao;
import javax.inject.Inject;
@@ -23,13 +23,9 @@ import javax.inject.Singleton;
*/
@Singleton
public class FactoryAcceptValidatorImpl extends FactoryBaseValidator implements FactoryAcceptValidator {
- @Inject
- public FactoryAcceptValidatorImpl(PreferenceDao preferenceDao) {
- super(preferenceDao);
- }
@Override
- public void validateOnAccept(Factory factory) throws BadRequestException {
+ public void validateOnAccept(FactoryDto factory) throws BadRequestException {
validateCurrentTimeBetweenSinceUntil(factory);
validateProjectActions(factory);
}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryBaseValidator.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryBaseValidator.java
index 73feb7a8ff..29c4fa28f8 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryBaseValidator.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryBaseValidator.java
@@ -11,16 +11,13 @@
package org.eclipse.che.api.factory.server.impl;
import org.eclipse.che.api.core.BadRequestException;
-import org.eclipse.che.api.core.ForbiddenException;
-import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.factory.server.FactoryConstants;
-import org.eclipse.che.api.factory.shared.dto.Action;
-import org.eclipse.che.api.factory.shared.dto.Factory;
-import org.eclipse.che.api.factory.shared.dto.Ide;
-import org.eclipse.che.api.factory.shared.dto.OnAppLoaded;
-import org.eclipse.che.api.factory.shared.dto.OnProjectsLoaded;
-import org.eclipse.che.api.factory.shared.dto.Policies;
-import org.eclipse.che.api.user.server.spi.PreferenceDao;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
+import org.eclipse.che.api.factory.shared.dto.IdeActionDto;
+import org.eclipse.che.api.factory.shared.dto.IdeDto;
+import org.eclipse.che.api.factory.shared.dto.OnAppLoadedDto;
+import org.eclipse.che.api.factory.shared.dto.OnProjectsLoadedDto;
+import org.eclipse.che.api.factory.shared.dto.PoliciesDto;
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
import java.io.UnsupportedEncodingException;
@@ -31,7 +28,6 @@ import java.util.Map;
import java.util.regex.Pattern;
import static com.google.common.base.Strings.isNullOrEmpty;
-import static java.lang.Boolean.parseBoolean;
import static java.lang.String.format;
import static java.lang.System.currentTimeMillis;
@@ -44,12 +40,6 @@ import static java.lang.System.currentTimeMillis;
public abstract class FactoryBaseValidator {
private static final Pattern PROJECT_NAME_VALIDATOR = Pattern.compile("^[\\\\\\w\\\\\\d]+[\\\\\\w\\\\\\d_.-]*$");
- private final PreferenceDao preferenceDao;
-
- public FactoryBaseValidator(PreferenceDao preferenceDao) {
- this.preferenceDao = preferenceDao;
- }
-
/**
* Validates source parameter of factory.
*
@@ -58,7 +48,7 @@ public abstract class FactoryBaseValidator {
* @throws BadRequestException
* when source projects in the factory is invalid
*/
- protected void validateProjects(Factory factory) throws BadRequestException {
+ protected void validateProjects(FactoryDto factory) throws BadRequestException {
for (ProjectConfigDto project : factory.getWorkspace().getProjects()) {
final String projectName = project.getName();
if (null != projectName && !PROJECT_NAME_VALIDATOR.matcher(projectName)
@@ -89,31 +79,6 @@ public abstract class FactoryBaseValidator {
}
}
- /**
- * Validates that creator of factory is really owner of account specified in it.
- *
- * @param factory
- * factory to validate
- * @throws ServerException
- * when any server errors occurs
- * @throws ForbiddenException
- * when user does not have required rights
- */
- protected void validateAccountId(Factory factory) throws ServerException, ForbiddenException {
- // TODO do we need check if user is temporary?
- final String userId = factory.getCreator() != null ? factory.getCreator().getUserId() : null;
-
- if (userId == null) {
- return;
- }
-
- final Map preferences = preferenceDao.getPreferences(userId);
- if (parseBoolean(preferences.get("temporary"))) {
- throw new ForbiddenException("Current user is not allowed to use this method.");
- }
-
- }
-
/**
* Validates that factory can be used at present time (used on accept)
*
@@ -124,8 +89,8 @@ public abstract class FactoryBaseValidator {
* @throws BadRequestException
* if until date less than current date
*/
- protected void validateCurrentTimeBetweenSinceUntil(Factory factory) throws BadRequestException {
- final Policies policies = factory.getPolicies();
+ protected void validateCurrentTimeBetweenSinceUntil(FactoryDto factory) throws BadRequestException {
+ final PoliciesDto policies = factory.getPolicies();
if (policies == null) {
return;
}
@@ -148,14 +113,14 @@ public abstract class FactoryBaseValidator {
* @param factory
* factory to validate
* @throws BadRequestException
- * if since date greater or equal than until date
+ * if since date greater or equal than until date
* @throws BadRequestException
- * if since date less than current date
+ * if since date less than current date
* @throws BadRequestException
- * if until date less than current date
+ * if until date less than current date
*/
- protected void validateCurrentTimeAfterSinceUntil(Factory factory) throws BadRequestException {
- final Policies policies = factory.getPolicies();
+ protected void validateCurrentTimeAfterSinceUntil(FactoryDto factory) throws BadRequestException {
+ final PoliciesDto policies = factory.getPolicies();
if (policies == null) {
return;
}
@@ -185,13 +150,13 @@ public abstract class FactoryBaseValidator {
* @throws BadRequestException
* when factory actions is invalid
*/
- protected void validateProjectActions(Factory factory) throws BadRequestException {
- final Ide ide = factory.getIde();
+ protected void validateProjectActions(FactoryDto factory) throws BadRequestException {
+ final IdeDto ide = factory.getIde();
if (ide == null) {
return;
}
- final List applicationActions = new ArrayList<>();
+ final List applicationActions = new ArrayList<>();
if (ide.getOnAppClosed() != null) {
applicationActions.addAll(ide.getOnAppClosed().getActions());
}
@@ -199,16 +164,16 @@ public abstract class FactoryBaseValidator {
applicationActions.addAll(ide.getOnAppLoaded().getActions());
}
- for (Action applicationAction : applicationActions) {
+ for (IdeActionDto applicationAction : applicationActions) {
String id = applicationAction.getId();
if ("openFile".equals(id) || "findReplace".equals(id) || "runCommand".equals(id) || "newTerminal".equals(id)) {
throw new BadRequestException(format(FactoryConstants.INVALID_ACTION_SECTION, id));
}
}
- final OnAppLoaded onAppLoaded = ide.getOnAppLoaded();
+ final OnAppLoadedDto onAppLoaded = ide.getOnAppLoaded();
if (onAppLoaded != null) {
- for (Action action : onAppLoaded.getActions()) {
+ for (IdeActionDto action : onAppLoaded.getActions()) {
final Map properties = action.getProperties();
if ("openWelcomePage".equals(action.getId()) && isNullOrEmpty(properties.get("greetingContentUrl"))) {
throw new BadRequestException(FactoryConstants.INVALID_WELCOME_PAGE_ACTION);
@@ -216,10 +181,10 @@ public abstract class FactoryBaseValidator {
}
}
- final OnProjectsLoaded onLoaded = ide.getOnProjectsLoaded();
+ final OnProjectsLoadedDto onLoaded = ide.getOnProjectsLoaded();
if (onLoaded != null) {
- final List onProjectOpenedActions = onLoaded.getActions();
- for (Action applicationAction : onProjectOpenedActions) {
+ final List onProjectOpenedActions = onLoaded.getActions();
+ for (IdeActionDto applicationAction : onProjectOpenedActions) {
final String id = applicationAction.getId();
final Map properties = applicationAction.getProperties();
@@ -229,7 +194,7 @@ public abstract class FactoryBaseValidator {
throw new BadRequestException(FactoryConstants.INVALID_OPENFILE_ACTION);
}
break;
-
+
case "runCommand":
if (isNullOrEmpty(properties.get("name"))) {
throw new BadRequestException(FactoryConstants.INVALID_RUNCOMMAND_ACTION);
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryCreateValidatorImpl.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryCreateValidatorImpl.java
index 168e768fb6..2c3b2273f1 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryCreateValidatorImpl.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryCreateValidatorImpl.java
@@ -14,7 +14,7 @@ import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.factory.server.FactoryCreateValidator;
-import org.eclipse.che.api.factory.shared.dto.Factory;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.api.user.server.spi.PreferenceDao;
import org.eclipse.che.api.workspace.server.WorkspaceValidator;
@@ -29,16 +29,15 @@ public class FactoryCreateValidatorImpl extends FactoryBaseValidator implements
private WorkspaceValidator workspaceConfigValidator;
@Inject
- public FactoryCreateValidatorImpl(PreferenceDao preferenceDao,
- WorkspaceValidator workspaceConfigValidator) {
- super(preferenceDao);
+ public FactoryCreateValidatorImpl(WorkspaceValidator workspaceConfigValidator) {
this.workspaceConfigValidator = workspaceConfigValidator;
}
@Override
- public void validateOnCreate(Factory factory) throws BadRequestException, ServerException, ForbiddenException {
+ public void validateOnCreate(FactoryDto factory) throws BadRequestException,
+ ServerException,
+ ForbiddenException {
validateProjects(factory);
- validateAccountId(factory);
validateCurrentTimeAfterSinceUntil(factory);
validateProjectActions(factory);
workspaceConfigValidator.validateConfig(factory.getWorkspace());
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryEditValidatorImpl.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryEditValidatorImpl.java
index 68afee56f7..702630ec70 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryEditValidatorImpl.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryEditValidatorImpl.java
@@ -13,8 +13,8 @@ package org.eclipse.che.api.factory.server.impl;
import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.factory.server.FactoryEditValidator;
-import org.eclipse.che.api.factory.shared.dto.Author;
-import org.eclipse.che.api.factory.shared.dto.Factory;
+import org.eclipse.che.api.core.model.factory.Author;
+import org.eclipse.che.api.core.model.factory.Factory;
import org.eclipse.che.commons.env.EnvironmentContext;
import javax.inject.Singleton;
@@ -42,7 +42,7 @@ public class FactoryEditValidatorImpl implements FactoryEditValidator {
@Override
public void validate(Factory factory) throws ForbiddenException, ServerException {
// Checks if there is an author from the factory (It may be missing for some old factories)
- Author author = factory.getCreator();
+ final Author author = factory.getCreator();
if (author == null || author.getUserId() == null) {
throw new ServerException(format("Invalid factory without author stored. Please contact the support about the factory ID '%s'",
factory.getId()));
@@ -51,7 +51,7 @@ public class FactoryEditValidatorImpl implements FactoryEditValidator {
final String userId = EnvironmentContext.getCurrent().getSubject().getUserId();
if (!author.getUserId().equals(userId)) {
throw new ForbiddenException(format("You are not authorized for the factory '%s'",
- factory.getId()));
+ factory.getId()));
}
}
}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/jpa/FactoryJpaModule.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/jpa/FactoryJpaModule.java
new file mode 100644
index 0000000000..9b8d18889f
--- /dev/null
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/jpa/FactoryJpaModule.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.factory.server.jpa;
+
+import com.google.inject.AbstractModule;
+
+import org.eclipse.che.api.factory.server.jpa.JpaFactoryDao.RemoveFactoriesBeforeUserRemovedEventSubscriber;
+import org.eclipse.che.api.factory.server.spi.FactoryDao;
+
+/**
+ * @author Yevhenii Voevodin
+ */
+public class FactoryJpaModule extends AbstractModule {
+ @Override
+ protected void configure() {
+ bind(FactoryDao.class).to(JpaFactoryDao.class);
+ bind(RemoveFactoriesBeforeUserRemovedEventSubscriber.class).asEagerSingleton();
+ }
+}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/jpa/JpaFactoryDao.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/jpa/JpaFactoryDao.java
new file mode 100644
index 0000000000..d3629ecb11
--- /dev/null
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/jpa/JpaFactoryDao.java
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.factory.server.jpa;
+
+import com.google.inject.persist.Transactional;
+
+import org.eclipse.che.api.core.ConflictException;
+import org.eclipse.che.api.core.NotFoundException;
+import org.eclipse.che.api.core.ServerException;
+import org.eclipse.che.api.core.jdbc.jpa.DuplicateKeyException;
+import org.eclipse.che.api.core.jdbc.jpa.IntegrityConstraintViolationException;
+import org.eclipse.che.api.core.notification.EventService;
+import org.eclipse.che.api.core.notification.EventSubscriber;
+import org.eclipse.che.api.factory.server.model.impl.FactoryImpl;
+import org.eclipse.che.api.factory.server.spi.FactoryDao;
+import org.eclipse.che.api.user.server.event.BeforeUserRemovedEvent;
+import org.eclipse.che.commons.lang.NameGenerator;
+import org.eclipse.che.commons.lang.Pair;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+import javax.persistence.EntityManager;
+import java.util.Collections;
+import javax.persistence.TypedQuery;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringJoiner;
+
+import static java.lang.String.format;
+import static java.util.Collections.singletonList;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * @author Anton Korneta
+ */
+@Singleton
+public class JpaFactoryDao implements FactoryDao {
+ private static final Logger LOG = LoggerFactory.getLogger(JpaFactoryDao.class);
+
+ @Inject
+ private Provider managerProvider;
+
+ @Override
+ public FactoryImpl create(FactoryImpl factory) throws ConflictException, ServerException {
+ requireNonNull(factory);
+ try {
+ doCreate(factory);
+ } catch (DuplicateKeyException ex) {
+ throw new ConflictException(ex.getLocalizedMessage());
+ } catch (IntegrityConstraintViolationException ex) {
+ throw new ConflictException("Could not create factory with creator that refers on non-existent user");
+ } catch (RuntimeException ex) {
+ throw new ServerException(ex.getLocalizedMessage(), ex);
+ }
+ return factory;
+ }
+
+ @Override
+ public FactoryImpl update(FactoryImpl update) throws NotFoundException, ConflictException, ServerException {
+ requireNonNull(update);
+ try {
+ return doUpdate(update);
+ } catch (DuplicateKeyException ex) {
+ throw new ConflictException(ex.getLocalizedMessage());
+ } catch (RuntimeException ex) {
+ throw new ServerException(ex.getLocalizedMessage(), ex);
+ }
+ }
+
+ @Override
+ public void remove(String id) throws ServerException {
+ requireNonNull(id);
+ try {
+ doRemove(id);
+ } catch (RuntimeException ex) {
+ throw new ServerException(ex.getLocalizedMessage(), ex);
+ }
+ }
+
+ @Override
+ @Transactional
+ public FactoryImpl getById(String id) throws NotFoundException, ServerException {
+ requireNonNull(id);
+ try {
+ final FactoryImpl factory = managerProvider.get().find(FactoryImpl.class, id);
+ if (factory == null) {
+ throw new NotFoundException(format("Factory with id '%s' doesn't exist", id));
+ }
+ return factory;
+ } catch (RuntimeException ex) {
+ throw new ServerException(ex.getLocalizedMessage(), ex);
+ }
+ }
+
+ @Override
+ @Transactional
+ public List getByAttribute(int maxItems,
+ int skipCount,
+ List> attributes) throws ServerException {
+ try {
+ LOG.info("FactoryDao#getByAttributes #maxItems: {} #skipCount: {}, #attributes: {}", maxItems, skipCount, attributes);
+ final Map params = new HashMap<>();
+ String query = "SELECT factory FROM Factory factory";
+ if (!attributes.isEmpty()) {
+ final StringJoiner matcher = new StringJoiner(" AND ", " WHERE ", " ");
+ int i = 0;
+ for (Pair attribute : attributes) {
+ final String parameterName = "parameterName" + i++;
+ params.put(parameterName, attribute.second);
+ matcher.add("factory." + attribute.first + " = :" + parameterName);
+ }
+ query = query + matcher;
+ }
+ final TypedQuery typedQuery = managerProvider.get()
+ .createQuery(query, FactoryImpl.class)
+ .setFirstResult(skipCount)
+ .setMaxResults(maxItems);
+ for (Map.Entry entry : params.entrySet()) {
+ typedQuery.setParameter(entry.getKey(), entry.getValue());
+ }
+ return typedQuery.getResultList();
+ } catch (RuntimeException ex) {
+ throw new ServerException(ex.getLocalizedMessage(), ex);
+ }
+ }
+
+ @Transactional
+ protected void doCreate(FactoryImpl factory) {
+ final EntityManager manager = managerProvider.get();
+ manager.persist(factory);
+ }
+
+ @Transactional
+ protected FactoryImpl doUpdate(FactoryImpl update) throws NotFoundException {
+ final EntityManager manager = managerProvider.get();
+ if (manager.find(FactoryImpl.class, update.getId()) == null) {
+ throw new NotFoundException(format("Could not update factory with id %s because it doesn't exist", update.getId()));
+ }
+ return manager.merge(update);
+ }
+
+ @Transactional
+ protected void doRemove(String id) {
+ final EntityManager manager = managerProvider.get();
+ final FactoryImpl factory = manager.find(FactoryImpl.class, id);
+ if (factory != null) {
+ manager.remove(factory);
+ }
+ }
+
+ @Singleton
+ public static class RemoveFactoriesBeforeUserRemovedEventSubscriber implements EventSubscriber {
+ @Inject
+ private FactoryDao factoryDao;
+ @Inject
+ private EventService eventService;
+
+ @PostConstruct
+ public void subscribe() {
+ eventService.subscribe(this);
+ }
+
+ @PreDestroy
+ public void unsubscribe() {
+ eventService.unsubscribe(this);
+ }
+
+ @Override
+ public void onEvent(BeforeUserRemovedEvent event) {
+ try {
+ final Pair factoryCreator = Pair.of("creator.userId", event.getUser().getId());
+ for (FactoryImpl factory : factoryDao.getByAttribute(0, 0, singletonList(factoryCreator))) {
+ factoryDao.remove(factory.getId());
+ }
+ } catch (Exception x) {
+ LOG.error(format("Couldn't remove factories before user '%s' removed", event.getUser().getId()), x);
+ }
+ }
+ }
+}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/ActionImpl.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/ActionImpl.java
new file mode 100644
index 0000000000..7dbdf64ef5
--- /dev/null
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/ActionImpl.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.factory.server.model.impl;
+
+import org.eclipse.che.api.core.model.factory.Action;
+
+import javax.persistence.Basic;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Data object for {@link Action}.
+ *
+ * @author Anton Korneta
+ */
+@Entity(name = "Action")
+public class ActionImpl implements Action {
+
+ @Id
+ @GeneratedValue
+ private Long entityId;
+
+ @Basic
+ private String id;
+
+ @ElementCollection
+ private Map properties;
+
+ public ActionImpl() {}
+
+ public ActionImpl(String id, Map properties) {
+ this.id = id;
+ this.properties = properties;
+ }
+
+ public ActionImpl(Action action) {
+ this(action.getId(), action.getProperties());
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ @Override
+ public Map getProperties() {
+ if (properties == null) {
+ return new HashMap<>();
+ }
+ return properties;
+ }
+
+ public void setProperties(Map properties) {
+ this.properties = properties;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (!(obj instanceof ActionImpl)) return false;
+ final ActionImpl other = (ActionImpl)obj;
+ return Objects.equals(id, other.getId())
+ && getProperties().equals(other.getProperties());
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 7;
+ result = 31 * result + Objects.hashCode(id);
+ result = 31 * result + getProperties().hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "ActionImpl{" +
+ "id='" + id + '\'' +
+ ", properties=" + properties +
+ '}';
+ }
+}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/AuthorImpl.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/AuthorImpl.java
new file mode 100644
index 0000000000..0ee622dbbd
--- /dev/null
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/AuthorImpl.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.factory.server.model.impl;
+
+import org.eclipse.che.api.core.model.factory.Author;
+
+import javax.persistence.Basic;
+import javax.persistence.Embeddable;
+import java.util.Objects;
+
+/**
+ * Data object for {@link Author}.
+ *
+ * @author Anton Korneta
+ */
+@Embeddable
+public class AuthorImpl implements Author {
+
+ @Basic
+ private Long created;
+
+ @Basic
+ private String userId;
+
+ public AuthorImpl() {}
+
+ public AuthorImpl(String userId, Long created) {
+ this.created = created;
+ this.userId = userId;
+ }
+
+ public AuthorImpl(Author creator) {
+ this(creator.getUserId(), creator.getCreated());
+ }
+
+ @Override
+ public Long getCreated() {
+ return created;
+ }
+
+ public void setCreated(Long created) {
+ this.created = created;
+ }
+
+ @Override
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (!(obj instanceof AuthorImpl)) return false;
+ final AuthorImpl other = (AuthorImpl)obj;
+ return Objects.equals(userId, other.userId)
+ && Objects.equals(created, other.created);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 7;
+ result = 31 * result + Objects.hashCode(userId);
+ result = 31 * result + Long.hashCode(created);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "AuthorImpl{" +
+ "created=" + created +
+ ", userId='" + userId + '\'' +
+ '}';
+ }
+}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/ButtonAttributesImpl.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/ButtonAttributesImpl.java
new file mode 100644
index 0000000000..5def3b61c4
--- /dev/null
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/ButtonAttributesImpl.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.factory.server.model.impl;
+
+import org.eclipse.che.api.core.model.factory.ButtonAttributes;
+
+import javax.persistence.Basic;
+import javax.persistence.Embeddable;
+import java.util.Objects;
+
+/**
+ * Data object for {@link ButtonAttributes}.
+ *
+ * @author Anton Korneta
+ */
+@Embeddable
+public class ButtonAttributesImpl implements ButtonAttributes {
+
+ @Basic
+ private String color;
+
+ @Basic
+ private String logo;
+
+ @Basic
+ private String style;
+
+ @Basic
+ private Boolean counter;
+
+ public ButtonAttributesImpl() {}
+
+ public ButtonAttributesImpl(String color,
+ String logo,
+ String style,
+ Boolean counter) {
+ this.color = color;
+ this.logo = logo;
+ this.style = style;
+ this.counter = counter;
+ }
+
+ public ButtonAttributesImpl(ButtonAttributes attributes) {
+ this(attributes.getColor(),
+ attributes.getLogo(),
+ attributes.getStyle(),
+ attributes.getCounter());
+ }
+
+ @Override
+ public String getColor() {
+ return color;
+ }
+
+ public void setColor(String color) {
+ this.color = color;
+ }
+
+ @Override
+ public String getLogo() {
+ return logo;
+ }
+
+ public void setLogo(String logo) {
+ this.logo = logo;
+ }
+
+ @Override
+ public String getStyle() {
+ return style;
+ }
+
+ public void setStyle(String style) {
+ this.style = style;
+ }
+
+ @Override
+ public Boolean getCounter() {
+ return counter;
+ }
+
+ public void setCounter(Boolean counter) {
+ this.counter = counter;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (!(obj instanceof ButtonAttributesImpl)) return false;
+ final ButtonAttributesImpl other = (ButtonAttributesImpl)obj;
+ return Objects.equals(color, other.color)
+ && Objects.equals(logo, other.logo)
+ && Objects.equals(style, other.style)
+ && counter == other.counter;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 7;
+ result = 31 * result + Objects.hashCode(color);
+ result = 31 * result + Objects.hashCode(logo);
+ result = 31 * result + Objects.hashCode(style);
+ result = 31 * result + Boolean.hashCode(counter);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "ButtonAttributesImpl{" +
+ "color='" + color + '\'' +
+ ", logo='" + logo + '\'' +
+ ", style='" + style + '\'' +
+ ", counter=" + counter +
+ '}';
+ }
+}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/ButtonImpl.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/ButtonImpl.java
new file mode 100644
index 0000000000..a84dd92419
--- /dev/null
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/ButtonImpl.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.factory.server.model.impl;
+
+import org.eclipse.che.api.core.model.factory.Button;
+import org.eclipse.che.api.core.model.factory.ButtonAttributes;
+
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import java.util.Objects;
+
+/**
+ * Data object for {@link Button}.
+ *
+ * @author Anton Korneta
+ */
+@Entity(name = "Button")
+public class ButtonImpl implements Button {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ @Embedded
+ private ButtonAttributesImpl attributes;
+
+ @Enumerated(EnumType.STRING)
+ private Type type;
+
+ public ButtonImpl(ButtonAttributes attributes,
+ Type type) {
+ this.attributes = new ButtonAttributesImpl(attributes);
+ this.type = type;
+ }
+
+ public ButtonImpl() {}
+
+ public ButtonImpl(Button button) {
+ this(button.getAttributes(), button.getType());
+ }
+
+ @Override
+ public ButtonAttributesImpl getAttributes() {
+ return attributes;
+ }
+
+ public void setAttributes(ButtonAttributesImpl attributes) {
+ this.attributes = attributes;
+ }
+
+ @Override
+ public Type getType() {
+ return type;
+ }
+
+ public void setType(Type type) {
+ this.type = type;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (!(obj instanceof ButtonImpl)) return false;
+ final ButtonImpl other = (ButtonImpl)obj;
+ return Objects.equals(attributes, other.attributes)
+ && Objects.equals(type, other.type);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 7;
+ result = 31 * result + Objects.hashCode(attributes);
+ result = 31 * result + Objects.hashCode(type);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "ButtonImpl{" +
+ "attributes=" + attributes +
+ ", type=" + type +
+ '}';
+ }
+}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/FactoryImpl.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/FactoryImpl.java
new file mode 100644
index 0000000000..c760bfe00a
--- /dev/null
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/FactoryImpl.java
@@ -0,0 +1,342 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.factory.server.model.impl;
+
+import org.eclipse.che.api.core.model.factory.Author;
+import org.eclipse.che.api.core.model.factory.Button;
+import org.eclipse.che.api.core.model.factory.Factory;
+import org.eclipse.che.api.core.model.factory.Ide;
+import org.eclipse.che.api.core.model.factory.Policies;
+import org.eclipse.che.api.core.model.workspace.WorkspaceConfig;
+import org.eclipse.che.api.factory.server.FactoryImage;
+import org.eclipse.che.api.user.server.model.impl.UserImpl;
+import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
+import org.eclipse.che.commons.lang.NameGenerator;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Data object for {@link Factory}.
+ *
+ * @author Anton Korneta
+ */
+@Entity(name = "Factory")
+@Table
+// TODO fix after issue: https://github.com/eclipse/che/issues/2110
+//(uniqueConstraints = {@UniqueConstraint(columnNames = {"name", "userId"})})
+public class FactoryImpl implements Factory {
+
+ public static FactoryImplBuilder builder() {
+ return new FactoryImplBuilder();
+ }
+
+ @Id
+ private String id;
+
+ @Column(nullable = true)
+ private String name;
+
+ @Column(nullable = false)
+ private String version;
+
+ @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, optional = false)
+ private WorkspaceConfigImpl workspace;
+
+ @Embedded
+ private AuthorImpl creator;
+
+ @OneToOne
+ @JoinColumn(insertable = false, updatable = false, name = "userId")
+ private UserImpl userEntity;
+
+ @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
+ private ButtonImpl button;
+
+ @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
+ private IdeImpl ide;
+
+ @Embedded
+ private PoliciesImpl policies;
+
+ @ElementCollection
+ private Set images;
+
+ public FactoryImpl() {}
+
+ public FactoryImpl(String id,
+ String name,
+ String version,
+ WorkspaceConfig workspace,
+ Author creator,
+ Policies policies,
+ Ide ide,
+ Button button,
+ Set images) {
+ this.id = id;
+ this.name = name;
+ this.version = version;
+ if (workspace != null) {
+ this.workspace = new WorkspaceConfigImpl(workspace);
+ }
+ if (creator != null) {
+ this.creator = new AuthorImpl(creator);
+ }
+ if (policies != null) {
+ this.policies = new PoliciesImpl(policies);
+ }
+ if (ide != null) {
+ this.ide = new IdeImpl(ide);
+ }
+ if (button != null) {
+ this.button = new ButtonImpl(button);
+ }
+ if (images != null) {
+ this.images = new HashSet<>(images);
+ }
+ }
+
+ public FactoryImpl(Factory factory, Set images) {
+ this(factory.getId(),
+ factory.getName(),
+ factory.getV(),
+ factory.getWorkspace(),
+ factory.getCreator(),
+ factory.getPolicies(),
+ factory.getIde(),
+ factory.getButton(),
+ images);
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getV() {
+ return version;
+ }
+
+ public void setV(String version) {
+ this.version = version;
+ }
+
+ @Override
+ public WorkspaceConfigImpl getWorkspace() {
+ return workspace;
+ }
+
+ public void setWorkspace(WorkspaceConfigImpl workspace) {
+ this.workspace = workspace;
+ }
+
+ @Override
+ public AuthorImpl getCreator() {
+ return creator;
+ }
+
+ public void setCreator(AuthorImpl creator) {
+ this.creator = creator;
+ }
+
+ @Override
+ public PoliciesImpl getPolicies() {
+ return policies;
+ }
+
+ public void setPolicies(PoliciesImpl policies) {
+ this.policies = policies;
+ }
+
+ @Override
+ public ButtonImpl getButton() {
+ return button;
+ }
+
+ public void setButton(ButtonImpl button) {
+ this.button = button;
+ }
+
+ @Override
+ public IdeImpl getIde() {
+ return ide;
+ }
+
+ public void setIde(IdeImpl ide) {
+ this.ide = ide;
+ }
+
+ public Set getImages() {
+ if (images == null) {
+ images = new HashSet<>();
+ }
+ return images;
+ }
+
+ public void setImages(Set images) {
+ this.images = images;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (!(obj instanceof FactoryImpl)) return false;
+ final FactoryImpl other = (FactoryImpl)obj;
+ return Objects.equals(id, other.id)
+ && Objects.equals(name, other.name)
+ && Objects.equals(version, other.version)
+ && Objects.equals(workspace, other.workspace)
+ && Objects.equals(creator, other.creator)
+ && Objects.equals(policies, other.policies)
+ && Objects.equals(ide, other.ide)
+ && Objects.equals(button, other.button)
+ && getImages().equals(other.getImages());
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + Objects.hashCode(id);
+ hash = 31 * hash + Objects.hashCode(name);
+ hash = 31 * hash + Objects.hashCode(version);
+ hash = 31 * hash + Objects.hashCode(workspace);
+ hash = 31 * hash + Objects.hashCode(creator);
+ hash = 31 * hash + Objects.hashCode(policies);
+ hash = 31 * hash + Objects.hashCode(ide);
+ hash = 31 * hash + Objects.hashCode(button);
+ hash = 31 * hash + getImages().hashCode();
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return "FactoryImpl{" +
+ "id='" + id + '\'' +
+ ", name='" + name + '\'' +
+ ", version='" + version + '\'' +
+ ", workspace=" + workspace +
+ ", creator=" + creator +
+ ", policies=" + policies +
+ ", ide=" + ide +
+ ", button=" + button +
+ ", images=" + images +
+ '}';
+ }
+
+ /**
+ * Helps to create the instance of {@link FactoryImpl}.
+ */
+ public static class FactoryImplBuilder {
+
+ private String id;
+ private String name;
+ private String version;
+ private WorkspaceConfig workspace;
+ private Author creator;
+ private Policies policies;
+ private Ide ide;
+ private Button button;
+ private Set images;
+
+ private FactoryImplBuilder() {}
+
+ public FactoryImpl build() {
+ return new FactoryImpl(id, name, version, workspace, creator, policies, ide, button, images);
+ }
+
+ public FactoryImplBuilder from(FactoryImpl factory) {
+ this.id = factory.getId();
+ this.name = factory.getName();
+ this.version = factory.getV();
+ this.workspace = factory.getWorkspace();
+ this.creator = factory.getCreator();
+ this.policies = factory.getPolicies();
+ this.ide = factory.getIde();
+ this.button = factory.getButton();
+ this.images = factory.getImages();
+ return this;
+ }
+
+ public FactoryImplBuilder generateId() {
+ id = NameGenerator.generate("", 16);
+ return this;
+ }
+
+ public FactoryImplBuilder setId(String id) {
+ this.id = id;
+ return this;
+ }
+
+ public FactoryImplBuilder setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public FactoryImplBuilder setVersion(String version) {
+ this.version = version;
+ return this;
+ }
+
+ public FactoryImplBuilder setWorkspace(WorkspaceConfig workspace) {
+ this.workspace = workspace;
+ return this;
+ }
+
+ public FactoryImplBuilder setCreator(Author creator) {
+ this.creator = creator;
+ return this;
+ }
+
+ public FactoryImplBuilder setPolicies(Policies policies) {
+ this.policies = policies;
+ return this;
+ }
+
+ public FactoryImplBuilder setIde(Ide ide) {
+ this.ide = ide;
+ return this;
+ }
+
+ public FactoryImplBuilder setButton(Button button) {
+ this.button = button;
+ return this;
+ }
+
+ public FactoryImplBuilder setImages(Set images) {
+ this.images = images;
+ return this;
+ }
+ }
+}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/IdeImpl.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/IdeImpl.java
new file mode 100644
index 0000000000..e818b797a7
--- /dev/null
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/IdeImpl.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.factory.server.model.impl;
+
+import org.eclipse.che.api.core.model.factory.Ide;
+import org.eclipse.che.api.core.model.factory.OnAppClosed;
+import org.eclipse.che.api.core.model.factory.OnAppLoaded;
+import org.eclipse.che.api.core.model.factory.OnProjectsLoaded;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToOne;
+import java.util.Objects;
+
+/**
+ * Data object for {@link Ide}.
+ *
+ * @author Anton Korneta
+ */
+@Entity(name = "Ide")
+public class IdeImpl implements Ide {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
+ private OnAppLoadedImpl onAppLoaded;
+
+ @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
+ private OnProjectsLoadedImpl onProjectsLoaded;
+
+ @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
+ private OnAppClosedImpl onAppClosed;
+
+ public IdeImpl() {}
+
+ public IdeImpl(OnAppLoaded onAppLoaded,
+ OnProjectsLoaded onProjectsLoaded,
+ OnAppClosed onAppClosed) {
+ if (onAppLoaded != null) {
+ this.onAppLoaded = new OnAppLoadedImpl(onAppLoaded);
+ }
+ if (onProjectsLoaded != null) {
+ this.onProjectsLoaded = new OnProjectsLoadedImpl(onProjectsLoaded);
+ }
+ if (onAppClosed != null) {
+ this.onAppClosed = new OnAppClosedImpl(onAppClosed);
+ }
+ }
+
+ public IdeImpl(Ide ide) {
+ this(ide.getOnAppLoaded(),
+ ide.getOnProjectsLoaded(),
+ ide.getOnAppClosed());
+ }
+
+ @Override
+ public OnAppLoadedImpl getOnAppLoaded() {
+ return onAppLoaded;
+ }
+
+ public void setOnAppLoaded(OnAppLoadedImpl onAppLoaded) {
+ this.onAppLoaded = onAppLoaded;
+ }
+
+ @Override
+ public OnProjectsLoadedImpl getOnProjectsLoaded() {
+ return onProjectsLoaded;
+ }
+
+ public void setOnProjectsLoaded(OnProjectsLoadedImpl onProjectsLoaded) {
+ this.onProjectsLoaded = onProjectsLoaded;
+ }
+
+ @Override
+ public OnAppClosedImpl getOnAppClosed() {
+ return onAppClosed;
+ }
+
+ public void setOnAppClosed(OnAppClosedImpl onAppClosed) {
+ this.onAppClosed = onAppClosed;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (!(obj instanceof IdeImpl)) return false;
+ final IdeImpl other = (IdeImpl)obj;
+ return Objects.equals(onAppLoaded, other.onAppLoaded)
+ && Objects.equals(onProjectsLoaded, other.onProjectsLoaded)
+ && Objects.equals(onAppClosed, other.onAppClosed);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 7;
+ result = 31 * result + Objects.hashCode(onAppLoaded);
+ result = 31 * result + Objects.hashCode(onProjectsLoaded);
+ result = 31 * result + Objects.hashCode(onAppClosed);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "IdeImpl{" +
+ "onAppLoaded=" + onAppLoaded +
+ ", onProjectsLoaded=" + onProjectsLoaded +
+ ", onAppClosed=" + onAppClosed +
+ '}';
+ }
+}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/OnAppClosedImpl.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/OnAppClosedImpl.java
new file mode 100644
index 0000000000..aa2d7b66a7
--- /dev/null
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/OnAppClosedImpl.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.factory.server.model.impl;
+
+import org.eclipse.che.api.core.model.factory.Action;
+import org.eclipse.che.api.core.model.factory.OnAppClosed;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.util.stream.Collectors.toList;
+import static javax.persistence.CascadeType.ALL;
+
+/**
+ * Data object for {@link OnAppClosed}.
+ *
+ * @author Anton Korneta
+ */
+@Entity(name = "OnAppClosed")
+public class OnAppClosedImpl implements OnAppClosed {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ @OneToMany(cascade = ALL, orphanRemoval = true)
+ private List actions;
+
+ public OnAppClosedImpl() {}
+
+ public OnAppClosedImpl(List extends Action> actions) {
+ if (actions != null) {
+ this.actions = actions.stream()
+ .map(ActionImpl::new)
+ .collect(toList());
+ }
+ }
+
+ public OnAppClosedImpl(OnAppClosed onAppClosed) {
+ this(onAppClosed.getActions());
+ }
+
+ @Override
+ public List getActions() {
+ if (actions == null) {
+ return new ArrayList<>();
+ }
+ return actions;
+ }
+
+ public void setActions(List actions) {
+ this.actions = actions;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (!(obj instanceof OnAppClosedImpl)) return false;
+ final OnAppClosedImpl other = (OnAppClosedImpl)obj;
+ return getActions().equals(other.getActions());
+ }
+
+ @Override
+ public int hashCode() {
+ return getActions().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "OnAppClosedImpl{" +
+ "actions=" + actions +
+ '}';
+ }
+}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/OnAppLoadedImpl.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/OnAppLoadedImpl.java
new file mode 100644
index 0000000000..169d0e7db6
--- /dev/null
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/OnAppLoadedImpl.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.factory.server.model.impl;
+
+import org.eclipse.che.api.core.model.factory.Action;
+import org.eclipse.che.api.core.model.factory.OnAppLoaded;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Data object for {@link OnAppLoaded}.
+ *
+ * @author Anton Korneta
+ */
+import static java.util.stream.Collectors.toList;
+import static javax.persistence.CascadeType.ALL;
+
+@Entity(name = "OnAppLoaded")
+public class OnAppLoadedImpl implements OnAppLoaded {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ @OneToMany(cascade = ALL, orphanRemoval = true)
+ private List actions;
+
+ public OnAppLoadedImpl() {}
+
+ public OnAppLoadedImpl(List extends Action> actions) {
+ if (actions != null) {
+ this.actions = actions.stream()
+ .map(ActionImpl::new)
+ .collect(toList());
+ }
+ }
+
+ public OnAppLoadedImpl(OnAppLoaded onAppLoaded) {
+ this(onAppLoaded.getActions());
+ }
+
+ @Override
+ public List getActions() {
+ if (actions == null) {
+ return new ArrayList<>();
+ }
+ return actions;
+ }
+
+ public void setActions(List actions) {
+ this.actions = actions;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (!(obj instanceof OnAppLoadedImpl)) return false;
+ final OnAppLoadedImpl other = (OnAppLoadedImpl)obj;
+ return getActions().equals(other.getActions());
+ }
+
+ @Override
+ public int hashCode() {
+ return getActions().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "OnAppLoadedImpl{" +
+ "actions=" + actions +
+ '}';
+ }
+}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/OnProjectsLoadedImpl.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/OnProjectsLoadedImpl.java
new file mode 100644
index 0000000000..fcf9862f62
--- /dev/null
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/OnProjectsLoadedImpl.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.factory.server.model.impl;
+
+import org.eclipse.che.api.core.model.factory.Action;
+import org.eclipse.che.api.core.model.factory.OnProjectsLoaded;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.util.stream.Collectors.toList;
+
+/**
+ * Data object for {@link OnProjectsLoaded}.
+ *
+ * @author Anton Korneta
+ */
+@Entity(name = "OnProjectsLoaded")
+public class OnProjectsLoadedImpl implements OnProjectsLoaded {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
+ private List actions;
+
+ public OnProjectsLoadedImpl() {}
+
+ public OnProjectsLoadedImpl(List extends Action> actions) {
+ if (actions != null) {
+ this.actions = actions.stream()
+ .map(ActionImpl::new)
+ .collect(toList());
+ }
+ }
+
+ public OnProjectsLoadedImpl(OnProjectsLoaded onProjectsLoaded) {
+ this(onProjectsLoaded.getActions());
+ }
+
+ @Override
+ public List getActions() {
+ if (actions == null) {
+ return new ArrayList<>();
+ }
+ return actions;
+ }
+
+ public void setActions(List actions) {
+ this.actions = actions;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (!(obj instanceof OnProjectsLoadedImpl)) return false;
+ final OnProjectsLoadedImpl other = (OnProjectsLoadedImpl)obj;
+ return getActions().equals(other.getActions());
+ }
+
+ @Override
+ public int hashCode() {
+ return getActions().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "OnProjectsLoadedImpl{" +
+ "actions=" + actions +
+ '}';
+ }
+}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/PoliciesImpl.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/PoliciesImpl.java
new file mode 100644
index 0000000000..d0d39cc6cf
--- /dev/null
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/model/impl/PoliciesImpl.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.factory.server.model.impl;
+
+import org.eclipse.che.api.core.model.factory.Policies;
+
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import java.util.Objects;
+
+/**
+ * Data object for {@link Policies}.
+ *
+ * @author Anton Korneta
+ */
+@Embeddable
+public class PoliciesImpl implements Policies {
+
+ @Basic
+ private String referer;
+
+ @Column(name = "match_reopen")
+ private String match;
+
+ @Column(name = "creation_strategy")
+ private String create;
+
+ @Basic
+ private Long until;
+
+ @Basic
+ private Long since;
+
+ public PoliciesImpl() {}
+
+ public PoliciesImpl(String referer,
+ String match,
+ String create,
+ Long until,
+ Long since) {
+ this.referer = referer;
+ this.match = match;
+ this.create = create;
+ this.until = until;
+ this.since = since;
+ }
+
+ public PoliciesImpl(Policies policies) {
+ this(policies.getReferer(),
+ policies.getMatch(),
+ policies.getCreate(),
+ policies.getUntil(),
+ policies.getSince());
+ }
+
+ @Override
+ public String getReferer() {
+ return referer;
+ }
+
+ public void setReferer(String referer) {
+ this.referer = referer;
+ }
+
+ @Override
+ public String getMatch() {
+ return match;
+ }
+
+ public void setMatch(String match) {
+ this.match = match;
+ }
+
+ @Override
+ public String getCreate() {
+ return create;
+ }
+
+ public void setCreate(String create) {
+ this.create = create;
+ }
+
+ @Override
+ public Long getUntil() {
+ return until;
+ }
+
+ public void setUntil(Long until) {
+ this.until = until;
+ }
+
+ @Override
+ public Long getSince() {
+ return since;
+ }
+
+ public void setSince(Long since) {
+ this.since = since;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (!(obj instanceof PoliciesImpl)) return false;
+ final PoliciesImpl other = (PoliciesImpl)obj;
+ return Objects.equals(referer, other.referer)
+ && Objects.equals(match, other.match)
+ && Objects.equals(create, other.create)
+ && Objects.equals(until, other.until)
+ && Objects.equals(since, other.since);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 7;
+ result = 31 * result + Objects.hashCode(referer);
+ result = 31 * result + Objects.hashCode(match);
+ result = 31 * result + Objects.hashCode(create);
+ result = 31 * result + Long.hashCode(until);
+ result = 31 * result + Long.hashCode(since);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "PoliciesImpl{" +
+ "referer='" + referer + '\'' +
+ ", match='" + match + '\'' +
+ ", create='" + create + '\'' +
+ ", until=" + until +
+ ", since=" + since +
+ '}';
+ }
+}
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/snippet/SnippetGenerator.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/snippet/SnippetGenerator.java
index 336988400e..299eba7e1e 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/snippet/SnippetGenerator.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/snippet/SnippetGenerator.java
@@ -10,8 +10,8 @@
*******************************************************************************/
package org.eclipse.che.api.factory.server.snippet;
-import org.eclipse.che.api.factory.shared.dto.Button;
-import org.eclipse.che.api.factory.shared.dto.Factory;
+import org.eclipse.che.api.core.model.factory.Button;
+import org.eclipse.che.api.core.model.factory.Factory;
import javax.ws.rs.core.UriBuilder;
import java.util.Formatter;
@@ -37,7 +37,7 @@ public class SnippetGenerator {
throw new IllegalArgumentException("Unable to generate markdown snippet for factory without button");
}
- if (Button.ButtonType.logo.equals(factory.getButton().getType())) {
+ if (Button.Type.LOGO.equals(factory.getButton().getType())) {
if (imageId != null && factory.getId() != null) {
imgUrl = format("%s/api/factory/%s/image?imgId=%s", baseUrl, factory.getId(), imageId);
} else {
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/spi/FactoryDao.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/spi/FactoryDao.java
new file mode 100644
index 0000000000..f88b59fce2
--- /dev/null
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/spi/FactoryDao.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * 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
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.factory.server.spi;
+
+import org.eclipse.che.api.core.ConflictException;
+import org.eclipse.che.api.core.NotFoundException;
+import org.eclipse.che.api.core.ServerException;
+import org.eclipse.che.api.factory.server.model.impl.FactoryImpl;
+import org.eclipse.che.commons.lang.Pair;
+
+import java.util.List;
+
+/**
+ * Defines data access object contract for {@code FactoryImpl}.
+ *
+ * @author Max Shaposhnik
+ * @author Anton Korneta
+ */
+public interface FactoryDao {
+
+ /**
+ * Creates factory.
+ *
+ * @param factory
+ * factory to create
+ * @return created factory
+ * @throws NullPointerException
+ * when {@code factory} is null
+ * @throws ConflictException
+ * when {@code factory} with given name and creator already exists
+ * @throws ServerException
+ * when any other error occurs
+ */
+ FactoryImpl create(FactoryImpl factory) throws ConflictException, ServerException;
+
+ /**
+ * Updates factory to the new entity, using replacement strategy.
+ *
+ * @param factory
+ * factory to update
+ * @return updated factory
+ * @throws NullPointerException
+ * when {@code factory} is null
+ * @throws NotFoundException
+ * when given factory is not found
+ * @throws ConflictException
+ * when {@code factory} with given name is already exist for creator
+ * @throws ServerException
+ * when any other error occurs
+ */
+ FactoryImpl update(FactoryImpl factory) throws NotFoundException, ConflictException, ServerException;
+
+ /**
+ * Removes factory.
+ *
+ * @param id
+ * factory identifier
+ * @throws NullPointerException
+ * when {@code id} is null
+ * @throws ServerException
+ * when any other error occurs
+ */
+ void remove(String id) throws ServerException;
+
+ /**
+ * Gets factory by identifier.
+ *
+ * @param id
+ * factory identifier
+ * @return factory instance, never null
+ * @throws NullPointerException
+ * when {@code id} is null
+ * @throws NotFoundException
+ * when factory with given {@code id} is not found
+ * @throws ServerException
+ * when any other error occurs
+ */
+ FactoryImpl getById(String id) throws NotFoundException, ServerException;
+
+ /**
+ * Gets the factories for the list of attributes.
+ *
+ * @param maxItems
+ * the maximum count of items to fetch
+ * @param skipCount
+ * count of items which should be skipped
+ * @param attributes
+ * list of pairs of attributes to search for
+ * @return list of the factories which contain the specified attributes
+ * @throws IllegalArgumentException
+ * when {@code skipCount} or {@code maxItems} is negative
+ * @throws ServerException
+ * when any other error occurs
+ */
+ List getByAttribute(int maxItems,
+ int skipCount,
+ List> attributes) throws ServerException;
+}
diff --git a/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/FactoryServiceTest.java b/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/FactoryServiceTest.java
index ad9dff6d8d..cc83e006b6 100644
--- a/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/FactoryServiceTest.java
+++ b/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/FactoryServiceTest.java
@@ -10,1043 +10,523 @@
*******************************************************************************/
package org.eclipse.che.api.factory.server;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.gson.JsonSyntaxException;
import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.response.Response;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.core.NotFoundException;
+import org.eclipse.che.api.core.model.factory.Factory;
+import org.eclipse.che.api.core.model.project.ProjectConfig;
+import org.eclipse.che.api.core.model.user.User;
+import org.eclipse.che.api.core.model.workspace.WorkspaceConfig;
import org.eclipse.che.api.core.model.workspace.WorkspaceStatus;
import org.eclipse.che.api.core.rest.ApiExceptionMapper;
-import org.eclipse.che.api.core.rest.shared.dto.Link;
import org.eclipse.che.api.core.rest.shared.dto.ServiceError;
+import org.eclipse.che.api.factory.server.FactoryService.FactoryParametersResolverHolder;
import org.eclipse.che.api.factory.server.builder.FactoryBuilder;
import org.eclipse.che.api.factory.server.impl.SourceStorageParametersValidator;
-import org.eclipse.che.api.factory.shared.dto.Author;
-import org.eclipse.che.api.factory.shared.dto.Button;
-import org.eclipse.che.api.factory.shared.dto.ButtonAttributes;
-import org.eclipse.che.api.factory.shared.dto.Factory;
+import org.eclipse.che.api.factory.server.model.impl.AuthorImpl;
+import org.eclipse.che.api.factory.server.model.impl.FactoryImpl;
+import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.api.machine.shared.dto.CommandDto;
+import org.eclipse.che.api.user.server.PreferenceManager;
+import org.eclipse.che.api.user.server.UserManager;
import org.eclipse.che.api.user.server.model.impl.UserImpl;
-import org.eclipse.che.api.user.server.spi.UserDao;
import org.eclipse.che.api.workspace.server.WorkspaceManager;
+import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl;
+import org.eclipse.che.api.workspace.server.model.impl.EnvironmentRecipeImpl;
+import org.eclipse.che.api.workspace.server.model.impl.ExtendedMachineImpl;
+import org.eclipse.che.api.workspace.server.model.impl.ProjectConfigImpl;
+import org.eclipse.che.api.workspace.server.model.impl.ServerConf2Impl;
+import org.eclipse.che.api.workspace.server.model.impl.SourceStorageImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl;
import org.eclipse.che.api.workspace.shared.dto.EnvironmentDto;
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
import org.eclipse.che.api.workspace.shared.dto.SourceStorageDto;
-import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.json.JsonHelper;
import org.eclipse.che.commons.lang.Pair;
import org.eclipse.che.commons.subject.SubjectImpl;
import org.eclipse.che.dto.server.DtoFactory;
import org.everrest.assured.EverrestJetty;
-import org.everrest.assured.JettyHttpServer;
import org.everrest.core.Filter;
import org.everrest.core.GenericContainerRequest;
import org.everrest.core.RequestFilter;
-import org.mockito.Matchers;
import org.mockito.Mock;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
+import org.mockito.Mockito;
import org.mockito.testng.MockitoTestNGListener;
-import org.testng.ITestContext;
import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
import java.io.File;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
+import java.io.InputStream;
+import java.net.URI;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.stream.Collectors;
import static com.jayway.restassured.RestAssured.given;
-import static java.lang.Boolean.FALSE;
-import static java.lang.Boolean.TRUE;
import static java.lang.String.format;
import static java.lang.String.valueOf;
-import static java.net.URLEncoder.encode;
+import static java.lang.Thread.currentThread;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.emptySet;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
-import static javax.ws.rs.core.Response.Status;
+import static java.util.stream.Collectors.toSet;
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
-import static javax.ws.rs.core.Response.Status.NOT_FOUND;
-import static javax.ws.rs.core.Response.Status.OK;
-import static org.eclipse.che.api.factory.server.FactoryService.ERROR_NO_RESOLVER_AVAILABLE;
+import static org.eclipse.che.api.factory.server.DtoConverter.asDto;
import static org.eclipse.che.api.factory.server.FactoryService.VALIDATE_QUERY_PARAMETER;
-import static org.eclipse.che.api.workspace.server.DtoConverter.asDto;
+import static org.everrest.assured.JettyHttpServer.ADMIN_USER_NAME;
+import static org.everrest.assured.JettyHttpServer.ADMIN_USER_PASSWORD;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyMap;
+import static org.mockito.Matchers.anyMapOf;
import static org.mockito.Matchers.anySetOf;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
+/**
+ * Tests for {@link FactoryService}.
+ *
+ * @author Anton Korneta
+ */
@Listeners(value = {EverrestJetty.class, MockitoTestNGListener.class})
public class FactoryServiceTest {
- private final String CORRECT_FACTORY_ID = "correctFactoryId";
- private final String ILLEGAL_FACTORY_ID = "illegalFactoryId";
- private final String SERVICE_PATH = "/factory";
- private static final String userId = "id-2314";
- private final ApiExceptionMapper exceptionMapper = new ApiExceptionMapper();
+ private static final String SERVICE_PATH = "/factory";
+ private static final String FACTORY_ID = "correctFactoryId";
+ private static final String FACTORY_NAME = "factory";
+ private static final String USER_ID = "userId";
+ private static final String USER_EMAIL = "email";
+ private static final String WORKSPACE_NAME = "workspace";
+ private static final String PROJECT_SOURCE_TYPE = "git";
+ private static final String PROJECT_SOURCE_LOCATION = "http://github.com/codenvy/platform-api.git";
+ private static final String FACTORY_IMAGE_MIME_TYPE = "image/jpeg";
+ private static final String IMAGE_NAME = "image12";
- /**
- * Path of the resolver REST service.
- */
- private final String SERVICE_PATH_RESOLVER = SERVICE_PATH + "/resolver";
- private EnvironmentFilter filter = new EnvironmentFilter();
+ private static final DtoFactory DTO = DtoFactory.getInstance();
@Mock
- private FactoryStore factoryStore;
-
+ private FactoryManager factoryManager;
@Mock
- private FactoryCreateValidator createValidator;
-
+ private FactoryCreateValidator createValidator;
@Mock
- private FactoryAcceptValidator acceptValidator;
-
+ private FactoryAcceptValidator acceptValidator;
@Mock
- private FactoryEditValidator editValidator;
-
+ private PreferenceManager preferenceManager;
@Mock
- private WorkspaceManager workspaceManager;
-
+ private UserManager userManager;
@Mock
- private UserDao userDao;
-
+ private FactoryEditValidator editValidator;
@Mock
- private FactoryService.FactoryParametersResolverHolder factoryParametersResolverHolder;
-
- private FactoryBuilder factoryBuilder;
-
- private FactoryService factoryService;
- private DtoFactory dto;
-
- /**
- * Set of all resolvers available for the factory service.
- */
+ private WorkspaceManager workspaceManager;
@Mock
+ private FactoryParametersResolverHolder factoryParametersResolverHolder;
+ @Mock
+ private UriInfo uriInfo;
+
+ private FactoryBuilder factoryBuilderSpy;
+
+ private User user;
private Set factoryParametersResolvers;
+ private FactoryService service;
+
+ @SuppressWarnings("unused")
+ private ApiExceptionMapper apiExceptionMapper;
+ @SuppressWarnings("unused")
+ private EnvironmentFilter environmentFilter;
@BeforeMethod
public void setUp() throws Exception {
- //doNothing().when(acceptValidator).validateOnAccept(any(Factory.class));
- dto = DtoFactory.getInstance();
- factoryBuilder = spy(new FactoryBuilder(new SourceStorageParametersValidator()));
- doNothing().when(factoryBuilder).checkValid(any(Factory.class));
- doNothing().when(factoryBuilder).checkValid(any(Factory.class), anyBoolean());
+ factoryBuilderSpy = spy(new FactoryBuilder(new SourceStorageParametersValidator()));
+ factoryParametersResolvers = new HashSet<>();
+ doNothing().when(factoryBuilderSpy).checkValid(any(FactoryDto.class));
+ doNothing().when(factoryBuilderSpy).checkValid(any(FactoryDto.class), anyBoolean());
when(factoryParametersResolverHolder.getFactoryParametersResolvers()).thenReturn(factoryParametersResolvers);
- when(userDao.getById(anyString())).thenReturn(new UserImpl(null,
- null,
- JettyHttpServer.ADMIN_USER_NAME,
- null,
- null));
- factoryService = new FactoryService(factoryStore,
- createValidator,
- acceptValidator,
- editValidator,
- new LinksHelper(),
- factoryBuilder,
- workspaceManager,
- factoryParametersResolverHolder,
- userDao);
+ user = new UserImpl(USER_ID, USER_EMAIL, ADMIN_USER_NAME);
+ when(userManager.getById(anyString())).thenReturn(user);
+ when(preferenceManager.find(USER_ID)).thenReturn(ImmutableMap.of("preference", "value"));
+ service = new FactoryService(factoryManager,
+ userManager,
+ preferenceManager,
+ createValidator,
+ acceptValidator,
+ editValidator,
+ factoryBuilderSpy,
+ workspaceManager,
+ factoryParametersResolverHolder);
}
@Filter
public static class EnvironmentFilter implements RequestFilter {
-
public void doFilter(GenericContainerRequest request) {
EnvironmentContext context = EnvironmentContext.getCurrent();
- context.setSubject(new SubjectImpl(JettyHttpServer.ADMIN_USER_NAME, userId, "token-2323", false));
+ context.setSubject(new SubjectImpl(ADMIN_USER_NAME, USER_ID, ADMIN_USER_PASSWORD, false));
}
-
}
-
@Test
- public void shouldReturnSavedFactoryIfUserDidNotUseSpecialMethod() throws Exception {
- // given
- Factory factory = prepareFactoryWithGivenStorage("git", "http://github.com/codenvy/platform-api.git").withId(CORRECT_FACTORY_ID);
- factory.setCreator(dto.createDto(Author.class).withUserId(userId).withName(JettyHttpServer.ADMIN_USER_NAME));
- Factory expected = dto.clone(factory);
+ public void shouldSaveFactoryWithImagesFromFormData() throws Exception {
+ final Factory factory = createFactory();
+ final FactoryDto factoryDto = asDto(factory, user);
+ when(factoryManager.saveFactory(any(FactoryDto.class), anySetOf(FactoryImage.class))).thenReturn(factory);
+ when(factoryManager.getById(FACTORY_ID)).thenReturn(factory);
+ doReturn(factoryDto).when(factoryBuilderSpy).build(any(InputStream.class));
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).thenReturn(factory);
- when(factoryStore.getFactoryImages(CORRECT_FACTORY_ID, null)).thenReturn(Collections.emptySet());
-
- // when
- Response response = given().when()
- .get(SERVICE_PATH + "/" + CORRECT_FACTORY_ID);
-
- // then
- assertEquals(response.getStatusCode(), 200);
- Factory responseFactory = dto.createDtoFromJson(response.getBody()
- .asInputStream(), Factory.class);
- responseFactory.setLinks(Collections.emptyList());
- assertEquals(responseFactory, expected);
- }
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .multiPart("factory", JsonHelper.toJson(factoryDto), APPLICATION_JSON)
+ .multiPart("image", getImagePath().toFile(), FACTORY_IMAGE_MIME_TYPE)
+ .expect()
+ .statusCode(200)
+ .when()
+ .post(SERVICE_PATH);
- @Test
- public void shouldBeAbleToSaveFactory() throws Exception {
- // given
- Factory factory = prepareFactoryWithGivenStorage("git", "http://github.com/codenvy/platform-api.git");
- URL resource = Thread.currentThread().getContextClassLoader()
- .getResource("100x100_image.jpeg");
- assertNotNull(resource);
- Path path = Paths.get(resource.toURI());
-
- FactorySaveAnswer factorySaveAnswer = new FactorySaveAnswer();
- when(factoryStore.saveFactory(any(Factory.class), anySetOf(FactoryImage.class))).then(factorySaveAnswer);
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).then(factorySaveAnswer);
-
- // when, then
- Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
- .multiPart("factory", JsonHelper.toJson(factory), MediaType.APPLICATION_JSON)
- .multiPart("image", path.toFile(), "image/jpeg")
- .when()
- .post("/private" + SERVICE_PATH);
-
- assertEquals(response.getStatusCode(), 200);
- Factory responseFactory = dto.createDtoFromJson(response.getBody().asInputStream(), Factory.class);
- boolean found = false;
- for (Link link : responseFactory.getLinks()) {
- if (link.getRel().equals("image") && link.getProduces().equals("image/jpeg") && !link.getHref().isEmpty())
- found = true;
- }
+ final FactoryDto result = getFromResponse(response, FactoryDto.class);
+ final boolean found = result.getLinks()
+ .stream()
+ .anyMatch(link -> link.getRel().equals("image")
+ && link.getProduces().equals(FACTORY_IMAGE_MIME_TYPE)
+ && !link.getHref().isEmpty());
+ factoryDto.withLinks(result.getLinks())
+ .getCreator()
+ .withCreated(result.getCreator().getCreated());
+ assertEquals(result, factoryDto);
assertTrue(found);
}
@Test
- public void shouldReturnStatus400IfSaveRequestHaveNotFactoryInfo() throws Exception {
+ public void shouldSaveFactoryFromFormDataWithoutImages() throws Exception {
+ final Factory factory = createFactory();
+ final FactoryDto factoryDto = asDto(factory, user);
+ when(factoryManager.saveFactory(any(FactoryDto.class), anySetOf(FactoryImage.class))).thenReturn(factory);
+ doReturn(factoryDto).when(factoryBuilderSpy).build(any(InputStream.class));
- // when, then
- Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
- .multiPart("someOtherData", "Some content", MediaType.TEXT_PLAIN)
- .expect()
- .statusCode(BAD_REQUEST.getStatusCode())
- .when()
- .post("/private" + SERVICE_PATH);
-
- assertEquals(dto.createDtoFromJson(response.getBody().asInputStream(), ServiceError.class).getMessage(),
- "No factory information found in 'factory' section of multipart/form-data.");
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .multiPart("factory", JsonHelper.toJson(factoryDto), APPLICATION_JSON)
+ .expect()
+ .statusCode(200)
+ .when()
+ .post(SERVICE_PATH);
+ final FactoryDto result = getFromResponse(response, FactoryDto.class);
+ factoryDto.withLinks(result.getLinks())
+ .getCreator()
+ .withCreated(result.getCreator().getCreated());
+ assertEquals(result, factoryDto);
}
@Test
- public void shouldBeAbleToSaveFactoryWithOutImage(ITestContext context) throws Exception {
- // given
- Factory factory = prepareFactoryWithGivenStorage("git", "http://github.com/codenvy/platform-api.git");
+ public void shouldSaveFactoryWithImagesWhenImagesWithoutContent() throws Exception {
+ final Factory factory = createFactory();
+ when(factoryManager.saveFactory(any(FactoryDto.class), anySetOf(FactoryImage.class))).thenReturn(factory);
+ when(factoryManager.getById(FACTORY_ID)).thenReturn(factory);
+ final FactoryDto factoryDto = asDto(factory, user);
+ doReturn(factoryDto).when(factoryBuilderSpy).build(any(InputStream.class));
- Link expectedCreateProject =
- dto.createDto(Link.class).withMethod(HttpMethod.GET).withProduces("text/html").withRel("accept")
- .withHref(getServerUrl(context) + "/f?id=" + CORRECT_FACTORY_ID);
-
- FactorySaveAnswer factorySaveAnswer = new FactorySaveAnswer();
- when(factoryStore.saveFactory(any(Factory.class), anySetOf(FactoryImage.class))).then(factorySaveAnswer);
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).then(factorySaveAnswer);
-
- // when, then
- Response response =
- given().auth().basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)//
- .multiPart("factory", JsonHelper.toJson(factory), MediaType.APPLICATION_JSON).when()
- .post("/private" + SERVICE_PATH);
-
- // then
- assertEquals(response.getStatusCode(), 200);
- Factory responseFactory = dto.createDtoFromJson(response.getBody().asString(), Factory.class);
- assertTrue(responseFactory.getLinks().contains(
- dto.createDto(Link.class).withMethod(HttpMethod.GET).withProduces(MediaType.APPLICATION_JSON)
- .withHref(getServerUrl(context) + "/rest/private/factory/" +
- CORRECT_FACTORY_ID).withRel("self")
- ));
- assertTrue(responseFactory.getLinks().contains(expectedCreateProject));
- assertTrue(responseFactory.getLinks()
- .contains(dto.createDto(Link.class).withMethod(HttpMethod.GET).withProduces(MediaType.TEXT_PLAIN)
- .withHref(getServerUrl(context) +
- "/rest/private/analytics/public-metric/factory_used?factory=" +
- encode(expectedCreateProject.getHref(), "UTF-8"))
- .withRel("accepted")));
- assertTrue(responseFactory.getLinks()
- .contains(dto.createDto(Link.class).withMethod(HttpMethod.GET).withProduces(MediaType.TEXT_PLAIN)
- .withHref(getServerUrl(context) + "/rest/private/factory/" +
- CORRECT_FACTORY_ID + "/snippet?type=url")
- .withRel("snippet/url")));
- assertTrue(responseFactory.getLinks()
- .contains(dto.createDto(Link.class).withMethod(HttpMethod.GET).withProduces(MediaType.TEXT_PLAIN)
- .withHref(getServerUrl(context) + "/rest/private/factory/" +
- CORRECT_FACTORY_ID + "/snippet?type=html")
- .withRel("snippet/html")));
- assertTrue(responseFactory.getLinks()
- .contains(dto.createDto(Link.class).withMethod(HttpMethod.GET).withProduces(MediaType.TEXT_PLAIN)
- .withHref(getServerUrl(context) + "/rest/private/factory/" +
- CORRECT_FACTORY_ID + "/snippet?type=markdown")
- .withRel("snippet/markdown")));
-
-
- List expectedLinks = new ArrayList<>(8);
- expectedLinks.add(expectedCreateProject);
-
- Link self = dto.createDto(Link.class);
- self.setMethod(HttpMethod.GET);
- self.setProduces(MediaType.APPLICATION_JSON);
- self.setHref(getServerUrl(context) + "/rest/private/factory/" + CORRECT_FACTORY_ID);
- self.setRel("self");
- expectedLinks.add(self);
-
- Link accepted = dto.createDto(Link.class);
- accepted.setMethod(HttpMethod.GET);
- accepted.setProduces(MediaType.TEXT_PLAIN);
- accepted.setHref(getServerUrl(context) + "/rest/private/analytics/public-metric/factory_used?factory=" +
- encode(expectedCreateProject.getHref(), "UTF-8"));
- accepted.setRel("accepted");
- expectedLinks.add(accepted);
-
- Link snippetUrl = dto.createDto(Link.class);
- snippetUrl.setProduces(MediaType.TEXT_PLAIN);
- snippetUrl.setHref(getServerUrl(context) + "/rest/private/factory/" + CORRECT_FACTORY_ID + "/snippet?type=url");
- snippetUrl.setRel("snippet/url");
- snippetUrl.setMethod(HttpMethod.GET);
- expectedLinks.add(snippetUrl);
-
- Link snippetHtml = dto.createDto(Link.class);
- snippetHtml.setProduces(MediaType.TEXT_PLAIN);
- snippetHtml.setHref(getServerUrl(context) + "/rest/private/factory/" + CORRECT_FACTORY_ID +
- "/snippet?type=html");
- snippetHtml.setMethod(HttpMethod.GET);
- snippetHtml.setRel("snippet/html");
- expectedLinks.add(snippetHtml);
-
- Link snippetMarkdown = dto.createDto(Link.class);
- snippetMarkdown.setProduces(MediaType.TEXT_PLAIN);
- snippetMarkdown.setHref(getServerUrl(context) + "/rest/private/factory/" + CORRECT_FACTORY_ID +
- "/snippet?type=markdown");
- snippetMarkdown.setRel("snippet/markdown");
- snippetMarkdown.setMethod(HttpMethod.GET);
- expectedLinks.add(snippetMarkdown);
-
- Link snippetiFrame = dto.createDto(Link.class);
- snippetiFrame.setProduces(MediaType.TEXT_PLAIN);
- snippetiFrame.setHref(getServerUrl(context) + "/rest/private/factory/" + CORRECT_FACTORY_ID +
- "/snippet?type=iframe");
- snippetiFrame.setRel("snippet/iframe");
- snippetiFrame.setMethod(HttpMethod.GET);
- expectedLinks.add(snippetiFrame);
-
- for (Link link : responseFactory.getLinks()) {
- //This transposition need because proxy objects doesn't contains equals method.
- Link testLink = dto.createDto(Link.class);
- testLink.setProduces(link.getProduces());
- testLink.setHref(link.getHref());
- testLink.setRel(link.getRel());
- testLink.setMethod(HttpMethod.GET);
- assertTrue(expectedLinks.contains(testLink));
- }
-
- verify(factoryStore).saveFactory(Matchers.any(), eq(Collections.emptySet()));
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .multiPart("factory", DTO.toJson(factoryDto), APPLICATION_JSON)
+ .multiPart("image", File.createTempFile("img", ".jpeg"), "image/jpeg")
+ .expect()
+ .statusCode(200)
+ .when()
+ .post(SERVICE_PATH);
+ final FactoryDto result = getFromResponse(response, FactoryDto.class);
+ verify(factoryManager).saveFactory(any(FactoryDto.class), anySetOf(FactoryImage.class));
+ factoryDto.withLinks(result.getLinks())
+ .getCreator()
+ .withCreated(result.getCreator().getCreated());
+ assertEquals(result, factoryDto);
}
@Test
- public void shouldBeAbleToSaveFactoryWithOutImageWithOrgId() throws Exception {
- // given
- Factory factory = prepareFactoryWithGivenStorage("git", "http://github.com/codenvy/platform-api.git");
+ public void shouldThrowBadRequestExceptionWhenInvalidFactorySectionProvided() throws Exception {
+ doThrow(new JsonSyntaxException("Invalid json")).when(factoryBuilderSpy).build(any(InputStream.class));
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .multiPart("factory", "invalid content", FACTORY_IMAGE_MIME_TYPE)
+ .expect()
+ .statusCode(400)
+ .when()
+ .post(SERVICE_PATH);
- FactorySaveAnswer factorySaveAnswer = new FactorySaveAnswer();
- when(factoryStore.saveFactory(any(Factory.class), anySetOf(FactoryImage.class))).then(factorySaveAnswer);
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).then(factorySaveAnswer);
-
- // when, then
- Response response =
- given().auth().basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)//
- .multiPart("factory", JsonHelper.toJson(factory), MediaType.APPLICATION_JSON).when()
- .post("/private" + SERVICE_PATH);
-
- // then
- assertEquals(response.getStatusCode(), 200);
+ final ServiceError err = getFromResponse(response, ServiceError.class);
+ assertEquals(err.getMessage(), "Invalid JSON value of the field 'factory' provided");
}
@Test
- public void shouldBeAbleToSaveFactoryWithSetImageFieldButWithOutImageContent() throws Exception {
- // given
- Factory factory = prepareFactoryWithGivenStorage("git", "http://github.com/codenvy/platform-api.git");
+ public void shouldThrowBadRequestExceptionWhenNoFactorySectionProvided() throws Exception {
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .multiPart("some data", "some content", FACTORY_IMAGE_MIME_TYPE)
+ .expect()
+ .statusCode(400)
+ .when()
+ .post(SERVICE_PATH);
- FactorySaveAnswer factorySaveAnswer = new FactorySaveAnswer();
- when(factoryStore.saveFactory(any(Factory.class), anySetOf(FactoryImage.class))).then(factorySaveAnswer);
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).then(factorySaveAnswer);
-
- // when, then
- given().auth().basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)//
- .multiPart("factory", dto.toJson(factory), MediaType.APPLICATION_JSON)//
- .multiPart("image", File.createTempFile("123456", ".jpeg"), "image/jpeg")//
- .expect().statusCode(200)
- .when().post("/private" + SERVICE_PATH);
-
- verify(factoryStore).saveFactory(Matchers.any(), eq(Collections.emptySet()));
+ final ServiceError err = getFromResponse(response, ServiceError.class);
+ assertEquals(err.getMessage(), "factory configuration required");
}
@Test
- public void shouldReturnStatus409OnSaveFactoryIfImageHasUnsupportedMediaType() throws Exception {
- // given
- Factory factory = prepareFactoryWithGivenStorage("git", "http://github.com/codenvy/platform-api.git");
- URL resource = Thread.currentThread().getContextClassLoader().getResource("100x100_image.jpeg");
- assertNotNull(resource);
- Path path = Paths.get(resource.toURI());
+ public void shouldThrowServerExceptionWhenProvidedFactoryDataInvalid() throws Exception {
+ final String errMessage = "eof";
+ doThrow(new IOException(errMessage)).when(factoryBuilderSpy).build(any(InputStream.class));
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .multiPart("factory", "any content", FACTORY_IMAGE_MIME_TYPE)
+ .expect()
+ .statusCode(500)
+ .when()
+ .post(SERVICE_PATH);
- when(factoryStore.saveFactory(any(Factory.class), anySetOf(FactoryImage.class))).thenReturn(CORRECT_FACTORY_ID);
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).thenReturn(factory);
-
- // when, then
- Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)//
- .multiPart("factory", JsonHelper.toJson(factory), MediaType.APPLICATION_JSON)//
- .multiPart("image", path.toFile(), "image/tiff")//
- .expect()
- .statusCode(409)
- .when().post("/private" + SERVICE_PATH);
-
- assertEquals(dto.createDtoFromJson(response.getBody().asString(), ServiceError.class).getMessage(),
- "Image media type 'image/tiff' is unsupported.");
+ final ServiceError err = getFromResponse(response, ServiceError.class);
+ assertEquals(err.getMessage(), errMessage);
}
@Test
- public void shouldBeAbleToGetFactory(ITestContext context) throws Exception {
- // given
- String factoryName = "factoryName";
- Factory factory = dto.createDto(Factory.class);
- factory.setId(CORRECT_FACTORY_ID);
- factory.setName(factoryName);
- factory.setCreator(dto.createDto(Author.class).withUserId(userId));
- URL resource = Thread.currentThread().getContextClassLoader().getResource("100x100_image.jpeg");
- assertNotNull(resource);
- Path path = Paths.get(resource.toURI());
- byte[] data = Files.readAllBytes(path);
- FactoryImage image1 = new FactoryImage(data, "image/jpeg", "image123456789");
- FactoryImage image2 = new FactoryImage(data, "image/png", "image987654321");
- Set images = new HashSet<>();
- images.add(image1);
- images.add(image2);
- Link expectedCreateProject = dto.createDto(Link.class);
- expectedCreateProject.setProduces("text/html");
- expectedCreateProject.setHref(getServerUrl(context) + "/f?id=" + CORRECT_FACTORY_ID);
- expectedCreateProject.setRel("accept");
+ public void shouldSaveFactoryWithoutImages() throws Exception {
+ final Factory factory = createFactory();
+ final FactoryDto factoryDto = asDto(factory, user);
+ when(factoryManager.saveFactory(any(FactoryDto.class))).thenReturn(factory);
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).thenReturn(factory);
- when(factoryStore.getFactoryImages(CORRECT_FACTORY_ID, null)).thenReturn(images);
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .contentType(ContentType.JSON)
+ .body(factoryDto)
+ .expect()
+ .statusCode(200)
+ .post(SERVICE_PATH);
- // when
- Response response = given().when().get(SERVICE_PATH + "/" + CORRECT_FACTORY_ID);
-
- // then
- assertEquals(response.getStatusCode(), 200);
- Factory responseFactory = JsonHelper.fromJson(response.getBody().asString(),
- Factory.class, null);
-
- List expectedLinks = new ArrayList<>(10);
- expectedLinks.add(expectedCreateProject);
-
- Link expectedCreateProjectByName = dto.createDto(Link.class);
- expectedCreateProjectByName.setProduces("text/html");
- expectedCreateProjectByName.setHref(getServerUrl(context) + "/f?name=" + factoryName + "&user=" + JettyHttpServer.ADMIN_USER_NAME);
- expectedCreateProjectByName.setRel("accept-named");
- expectedLinks.add(expectedCreateProjectByName);
-
- Link self = dto.createDto(Link.class);
- self.setProduces(MediaType.APPLICATION_JSON);
- self.setHref(getServerUrl(context) + "/rest/factory/" + CORRECT_FACTORY_ID);
- self.setRel("self");
- expectedLinks.add(self);
-
- Link imageJpeg = dto.createDto(Link.class);
- imageJpeg.setProduces("image/jpeg");
- imageJpeg.setHref(getServerUrl(context) + "/rest/factory/" + CORRECT_FACTORY_ID +
- "/image?imgId=image123456789");
- imageJpeg.setRel("image");
- expectedLinks.add(imageJpeg);
-
- Link imagePng = dto.createDto(Link.class);
- imagePng.setProduces("image/png");
- imagePng.setHref(getServerUrl(context) + "/rest/factory/" + CORRECT_FACTORY_ID + "/image?imgId=image987654321");
- imagePng.setRel("image");
- expectedLinks.add(imagePng);
-
- Link accepted = dto.createDto(Link.class);
- accepted.setProduces(MediaType.TEXT_PLAIN);
- accepted.setHref(getServerUrl(context) + "/rest/analytics/public-metric/factory_used?factory=" +
- encode(expectedCreateProject.getHref(), "UTF-8"));
- accepted.setRel("accepted");
- expectedLinks.add(accepted);
-
- Link snippetUrl = dto.createDto(Link.class);
- snippetUrl.setProduces(MediaType.TEXT_PLAIN);
- snippetUrl.setHref(getServerUrl(context) + "/rest/factory/" + CORRECT_FACTORY_ID + "/snippet?type=url");
- snippetUrl.setRel("snippet/url");
- expectedLinks.add(snippetUrl);
-
- Link snippetHtml = dto.createDto(Link.class);
- snippetHtml.setProduces(MediaType.TEXT_PLAIN);
- snippetHtml.setHref(getServerUrl(context) + "/rest/factory/" + CORRECT_FACTORY_ID + "/snippet?type=html");
- snippetHtml.setRel("snippet/html");
- expectedLinks.add(snippetHtml);
-
- Link snippetMarkdown = dto.createDto(Link.class);
- snippetMarkdown.setProduces(MediaType.TEXT_PLAIN);
- snippetMarkdown.setHref(getServerUrl(context) + "/rest/factory/" + CORRECT_FACTORY_ID +
- "/snippet?type=markdown");
- snippetMarkdown.setRel("snippet/markdown");
- expectedLinks.add(snippetMarkdown);
-
- Link snippetiFrame = dto.createDto(Link.class);
- snippetiFrame.setProduces(MediaType.TEXT_PLAIN);
- snippetiFrame.setHref(getServerUrl(context) + "/rest/factory/" + CORRECT_FACTORY_ID +
- "/snippet?type=iframe");
- snippetiFrame.setRel("snippet/iframe");
- expectedLinks.add(snippetiFrame);
-
- for (Link link : responseFactory.getLinks()) {
- Link testLink = dto.createDto(Link.class);
- testLink.setProduces(link.getProduces());
- testLink.setHref(link.getHref());
- testLink.setRel(link.getRel());
- //This transposition need because proxy objects doesn't contains equals method.
- assertTrue(expectedLinks.contains(testLink));
- }
+ assertEquals(getFromResponse(response, FactoryDto.class).withLinks(emptyList()), factoryDto);
}
@Test
- public void shouldReturnStatus404OnGetFactoryWithIllegalId() throws Exception {
- // given
- doThrow(new NotFoundException(format("Factory with id %s is not found.", ILLEGAL_FACTORY_ID))).when(factoryStore)
- .getFactory(anyString());
-
- // when, then
- Response response = given().expect()
- .statusCode(404)
- .when()
- .get(SERVICE_PATH + "/" + ILLEGAL_FACTORY_ID);
-
- assertEquals(dto.createDtoFromJson(response.getBody().asString(), ServiceError.class).getMessage(),
- format("Factory with id %s is not found.", ILLEGAL_FACTORY_ID));
+ public void shouldThrowBadRequestExceptionWhenFactoryConfigurationNotProvided() throws Exception {
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .contentType(ContentType.JSON)
+ .expect()
+ .statusCode(400)
+ .post(SERVICE_PATH);
+ final String errMessage = getFromResponse(response, ServiceError.class).getMessage();
+ assertEquals(errMessage, "Factory configuration required");
}
@Test
- public void shouldBeAbleToGetFactoryImage() throws Exception {
- // given
- URL resource = Thread.currentThread().getContextClassLoader().getResource("100x100_image.jpeg");
- assertNotNull(resource);
- Path path = Paths.get(resource.toURI());
- byte[] imageContent = Files.readAllBytes(path);
- FactoryImage image = new FactoryImage(imageContent, "image/jpeg", "imageName");
+ public void shouldReturnFactoryByIdentifierWithoutValidation() throws Exception {
+ final Factory factory = createFactory();
+ final FactoryDto factoryDto = asDto(factory, user);
+ when(factoryManager.getById(FACTORY_ID)).thenReturn(factory);
+ when(factoryManager.getFactoryImages(FACTORY_ID)).thenReturn(emptySet());
- when(factoryStore.getFactoryImages(CORRECT_FACTORY_ID, null)).thenReturn(new HashSet<>(singletonList(image)));
+ final Response response = given().when()
+ .expect()
+ .statusCode(200)
+ .get(SERVICE_PATH + "/" + FACTORY_ID);
- // when
- Response response = given().when().get(SERVICE_PATH + "/" + CORRECT_FACTORY_ID + "/image?imgId=imageName");
-
- // then
- assertEquals(response.getStatusCode(), 200);
- assertEquals(response.getContentType(), "image/jpeg");
- assertEquals(response.getHeader("content-length"), String.valueOf(imageContent.length));
- assertEquals(response.asByteArray(), imageContent);
+ assertEquals(getFromResponse(response, FactoryDto.class).withLinks(emptyList()), factoryDto);
}
@Test
- public void shouldBeAbleToGetFactoryDefaultImage() throws Exception {
- // given
- URL resource = Thread.currentThread().getContextClassLoader().getResource("100x100_image.jpeg");
- assertNotNull(resource);
- Path path = Paths.get(resource.toURI());
- byte[] imageContent = Files.readAllBytes(path);
- FactoryImage image = new FactoryImage(imageContent, "image/jpeg", "imageName");
+ public void shouldReturnFactoryByIdentifierWithValidation() throws Exception {
+ final Factory factory = createFactory();
+ final FactoryDto factoryDto = asDto(factory, user);
+ when(factoryManager.getById(FACTORY_ID)).thenReturn(factory);
+ when(factoryManager.getFactoryImages(FACTORY_ID)).thenReturn(emptySet());
+ doNothing().when(acceptValidator).validateOnAccept(any(FactoryDto.class));
- when(factoryStore.getFactoryImages(CORRECT_FACTORY_ID, null)).thenReturn(new HashSet<>(singletonList(image)));
+ final Response response = given().when()
+ .expect()
+ .statusCode(200)
+ .get(SERVICE_PATH + "/" + FACTORY_ID + "?validate=true");
- // when
- Response response = given().when().get(SERVICE_PATH + "/" + CORRECT_FACTORY_ID + "/image");
-
- // then
- assertEquals(response.getStatusCode(), 200);
- assertEquals(response.getContentType(), "image/jpeg");
- assertEquals(response.getHeader("content-length"), String.valueOf(imageContent.length));
- assertEquals(response.asByteArray(), imageContent);
+ assertEquals(getFromResponse(response, FactoryDto.class).withLinks(emptyList()), factoryDto);
}
@Test
- public void shouldReturnStatus404OnGetFactoryImageWithIllegalId() throws Exception {
- // given
- when(factoryStore.getFactoryImages(CORRECT_FACTORY_ID, null)).thenReturn(new HashSet<>());
+ public void shouldThrowNotFoundExceptionWhenFactoryIsNotExist() throws Exception {
+ final String errMessage = format("Factory with id %s is not found", FACTORY_ID);
+ doThrow(new NotFoundException(errMessage)).when(factoryManager)
+ .getById(anyString());
- // when, then
- Response response = given().expect()
- .statusCode(404)
- .when()
- .get(SERVICE_PATH + "/" + CORRECT_FACTORY_ID + "/image?imgId=illegalImageId");
+ final Response response = given().expect()
+ .statusCode(404)
+ .when()
+ .get(SERVICE_PATH + "/" + FACTORY_ID);
- assertEquals(dto.createDtoFromJson(response.getBody().asString(), ServiceError.class).getMessage(),
- format("Image with id %s is not found.", "illegalImageId"));
+ assertEquals(getFromResponse(response, ServiceError.class).getMessage(), errMessage);
}
@Test
- public void shouldResponse404OnGetImageIfFactoryDoesNotExist() throws Exception {
- // given
- doThrow(new NotFoundException(format("Factory with id %s is not found.", ILLEGAL_FACTORY_ID))).when(factoryStore)
- .getFactoryImages(anyString(),
- anyString());
+ public void shouldReturnFactoryListByNameAttribute() throws Exception {
+ final Factory factory = createFactory();
+ when(factoryManager.getByAttribute(1, 0, ImmutableList.of(Pair.of("factory.name", factory.getName()))))
+ .thenReturn(ImmutableList.of(factory));
- // when, then
- Response response = given().expect()
- .statusCode(404)
- .when()
- .get(SERVICE_PATH + "/" + ILLEGAL_FACTORY_ID + "/image?imgId=ImageId");
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .contentType(APPLICATION_JSON)
+ .when()
+ .expect()
+ .statusCode(200)
+ .get(SERVICE_PATH + "/find?maxItems=1&skipCount=0&factory.name=" + factory.getName());
- assertEquals(dto.createDtoFromJson(response.getBody().asString(), ServiceError.class).getMessage(),
- format("Factory with id %s is not found.", ILLEGAL_FACTORY_ID));
+ final List res = unwrapDtoList(response, FactoryDto.class);
+ assertEquals(res.size(), 1);
+ assertEquals(res.get(0).withLinks(emptyList()), asDto(factory, user));
}
@Test
- public void shouldBeAbleToReturnUrlSnippet(ITestContext context) throws Exception {
- // given
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).thenReturn(dto.createDto
- (Factory.class));
+ public void shouldReturnFactoryListByCreatorAttribute() throws Exception {
+ final Factory factory1 = createNamedFactory("factory1");
+ final Factory factory2 = createNamedFactory("factory2");
+ when(factoryManager.getByAttribute(2, 0, ImmutableList.of(Pair.of("factory.creator.name", user.getName()))))
+ .thenReturn(ImmutableList.of(factory1, factory2));
- // when, then
- given().expect()
- .statusCode(200)
- .contentType(MediaType.TEXT_PLAIN)
- .body(equalTo(getServerUrl(context) + "/factory?id=" + CORRECT_FACTORY_ID))
- .when()
- .get(SERVICE_PATH + "/" + CORRECT_FACTORY_ID + "/snippet?type=url");
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .contentType(APPLICATION_JSON)
+ .when()
+ .expect()
+ .statusCode(200)
+ .get(SERVICE_PATH + "/find?maxItems=2&skipCount=0&factory.creator.name=" + user.getName());
+
+ final Set res = unwrapDtoList(response, FactoryDto.class).stream()
+ .map(f -> f.withLinks(emptyList()))
+ .collect(toSet());
+ assertEquals(res.size(), 2);
+ assertTrue(res.containsAll(ImmutableList.of(asDto(factory1, user), asDto(factory2, user))));
}
@Test
- public void shouldBeAbleToReturnUrlSnippetIfTypeIsNotSet(ITestContext context) throws Exception {
- // given
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).thenReturn(dto.createDto
- (Factory.class));
+ public void shouldThrowBadRequestWhenGettingFactoryByEmptyAttributeList() throws Exception {
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .contentType(APPLICATION_JSON)
+ .when()
+ .expect()
+ .get(SERVICE_PATH + "/find?maxItems=1&skipCount=0");
- // when, then
- given().expect()
- .statusCode(200)
- .contentType(MediaType.TEXT_PLAIN)
- .body(equalTo(getServerUrl(context) + "/factory?id=" + CORRECT_FACTORY_ID))
- .when()
- .get(SERVICE_PATH + "/" + CORRECT_FACTORY_ID + "/snippet");
+ assertEquals(response.getStatusCode(), 400);
+ assertEquals(DTO.createDtoFromJson(response.getBody().asString(), ServiceError.class)
+ .getMessage(), "Query must contain at least one attribute");
}
- @Test
- public void shouldBeAbleToReturnHtmlSnippet(ITestContext context) throws Exception {
- // given
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).thenReturn(dto.createDto(Factory.class));
-
- // when, then
- Response response = given().expect()
- .statusCode(200)
- .contentType(MediaType.TEXT_PLAIN)
- .when()
- .get(SERVICE_PATH + "/" + CORRECT_FACTORY_ID + "/snippet?type=html");
-
- assertEquals(response.body().asString(), "");
- }
-
- @Test
- public void shouldBeAbleToReturnMarkdownSnippetForFactory1WithImage(ITestContext context) throws Exception {
- // given
- SourceStorageDto storageDto = dto.createDto(SourceStorageDto.class)
- .withType("git")
- .withLocation("http://github.com/codenvy/platform-api.git");
- Factory factory = dto.createDto(Factory.class)
- .withV("4.0")
- .withWorkspace(dto.createDto(WorkspaceConfigDto.class)
- .withProjects(singletonList(dto.createDto(ProjectConfigDto.class)
- .withSource(storageDto))))
- .withId(CORRECT_FACTORY_ID)
- .withButton(dto.createDto(Button.class)
- .withType(Button.ButtonType.logo));
- String imageName = "1241234";
- FactoryImage image = new FactoryImage();
- image.setName(imageName);
-
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).thenReturn(factory);
- when(factoryStore.getFactoryImages(CORRECT_FACTORY_ID, null)).thenReturn(new HashSet<>(singletonList(image)));
- // when, then
- given().expect()
- .statusCode(200)
- .contentType(MediaType.TEXT_PLAIN)
- .body(
- equalTo("[ + "/api/factory/" + CORRECT_FACTORY_ID + "/image?imgId=" +
- imageName + ")](" +
- getServerUrl(context) + "/factory?id=" +
- CORRECT_FACTORY_ID + ")")
- )
- .when()
- .get(SERVICE_PATH + "/" + CORRECT_FACTORY_ID + "/snippet?type=markdown");
- }
-
-
- @Test
- public void shouldBeAbleToReturnMarkdownSnippetForFactory2WithImage(ITestContext context) throws Exception {
- // given
- String imageName = "1241234";
- Factory factory = dto.createDto(Factory.class);
- factory.setId(CORRECT_FACTORY_ID);
- factory.setV("2.0");
- factory.setButton(dto.createDto(Button.class).withType(Button.ButtonType.logo));
-
- FactoryImage image = new FactoryImage();
- image.setName(imageName);
-
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).thenReturn(factory);
- when(factoryStore.getFactoryImages(CORRECT_FACTORY_ID, null)).thenReturn(new HashSet<>(singletonList(image)));
- // when, then
- given().expect()
- .statusCode(200)
- .contentType(MediaType.TEXT_PLAIN)
- .body(
- equalTo("[ + "/api/factory/" + CORRECT_FACTORY_ID + "/image?imgId=" +
- imageName + ")](" +
- getServerUrl(context) + "/factory?id=" +
- CORRECT_FACTORY_ID + ")")
- )
- .when()
- .get(SERVICE_PATH + "/" + CORRECT_FACTORY_ID + "/snippet?type=markdown");
- }
-
- @Test
- public void shouldBeAbleToReturnMarkdownSnippetForFactory1WithoutImage(ITestContext context) throws Exception {
- // given
- Factory factory = prepareFactoryWithGivenStorage("git", "http://github.com/codenvy/platform-api.git")
- .withId(CORRECT_FACTORY_ID)
- .withButton(dto.createDto(Button.class)
- .withType(Button.ButtonType.nologo)
- .withAttributes(dto.createDto(ButtonAttributes.class)
- .withColor("white")));
-
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).thenReturn(factory);
- // when, then
- given().expect()
- .statusCode(200)
- .contentType(MediaType.TEXT_PLAIN)
- .body(
- equalTo("[ + "/factory/resources/factory-white.png)](" + getServerUrl
- (context) +
- "/factory?id=" +
- CORRECT_FACTORY_ID + ")")
- )
- .when()
- .get(SERVICE_PATH + "/" + CORRECT_FACTORY_ID + "/snippet?type=markdown");
- }
-
- @Test
- public void shouldNotBeAbleToGetMarkdownSnippetForFactory1WithoutStyle() throws Exception {
- // given
- Factory factory = prepareFactoryWithGivenStorage("git", "http://github.com/codenvy/platform-api.git").withId(CORRECT_FACTORY_ID);
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).thenReturn(factory);
- // when, then
- Response response = given().expect()
- .statusCode(400)
- .when()
- .get(SERVICE_PATH + "/" + CORRECT_FACTORY_ID + "/snippet?type=markdown");
-
- assertEquals(dto.createDtoFromJson(response.getBody().asInputStream(), ServiceError.class).getMessage(),
- "Unable to generate markdown snippet for factory without button");
- }
-
- @Test
- public void shouldNotBeAbleToGetMarkdownSnippetForFactory2WithoutColor() throws Exception {
- // given
- Factory factory = prepareFactoryWithGivenStorage("git", "http://github.com/codenvy/platform-api.git")
- .withId(CORRECT_FACTORY_ID)
- .withButton(dto.createDto(Button.class)
- .withType(Button.ButtonType.nologo)
- .withAttributes(dto.createDto(ButtonAttributes.class)
- .withColor(null)));
-
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).thenReturn(factory);
- // when, then
- Response response = given().expect()
- .statusCode(400)
- .when()
- .get(SERVICE_PATH + "/" + CORRECT_FACTORY_ID + "/snippet?type=markdown");
-
- assertEquals(dto.createDtoFromJson(response.getBody().asInputStream(), ServiceError.class).getMessage(),
- "Unable to generate markdown snippet with nologo button and empty color");
- }
-
- @Test
- public void shouldResponse404OnGetSnippetIfFactoryDoesNotExist() throws Exception {
- // given
- doThrow(new NotFoundException("Factory URL with id " + ILLEGAL_FACTORY_ID + " is not found.")).when(factoryStore)
- .getFactory(anyString());
-
- // when, then
- Response response = given().expect()
- .statusCode(404)
- .when()
- .get(SERVICE_PATH + "/" + ILLEGAL_FACTORY_ID + "/snippet?type=url");
-
- assertEquals(dto.createDtoFromJson(response.getBody().asString(), ServiceError.class).getMessage(),
- "Factory URL with id " + ILLEGAL_FACTORY_ID + " is not found.");
- }
-
-
- /**
- * Checks that the user can remove an existing factory
- */
- @Test
- public void shouldBeAbleToRemoveAFactory() throws Exception {
- // given
- Factory factory = prepareFactoryWithGivenStorage("git", "http://github.com/codenvy/platform-api.git");
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).thenReturn(factory);
-
- // when, then
- Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
- .param("id", CORRECT_FACTORY_ID)
- .when()
- .delete("/private" + SERVICE_PATH + "/" + CORRECT_FACTORY_ID);
-
- assertEquals(response.getStatusCode(), 204);
-
- // check there was a call on the remove operation with expected ID
- verify(factoryStore).removeFactory(CORRECT_FACTORY_ID);
- }
-
- /**
- * Checks that the user can not remove an unknown factory
- */
- @Test
- public void shouldNotBeAbleToRemoveNotExistingFactory() throws Exception {
- doThrow(new NotFoundException("Not found")).when(factoryStore).removeFactory(anyString());
-
- // when, then
- Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
- .param("id", ILLEGAL_FACTORY_ID)
- .when()
- .delete("/private" + SERVICE_PATH + "/" + ILLEGAL_FACTORY_ID);
-
- assertEquals(response.getStatusCode(), 404);
- }
-
- /**
- * Checks that the user can update an existing factory
- */
@Test
public void shouldBeAbleToUpdateFactory() throws Exception {
+ final Factory existed = createFactory();
+ final Factory update = createFactoryWithStorage(null, "git", "http://github.com/codenvy/platform-api1.git");
+ when(factoryManager.getById(FACTORY_ID)).thenReturn(existed);
+ when(factoryManager.updateFactory(any())).thenReturn(update);
- // given
- Factory beforeFactory = prepareFactoryWithGivenStorage("git", "http://github.com/codenvy/platform-api.git")
- .withCreator(dto.createDto(Author.class).withCreated(System.currentTimeMillis()));
- beforeFactory.setId(CORRECT_FACTORY_ID);
- Factory afterFactory = prepareFactoryWithGivenStorage("git", "http://github.com/codenvy/platform-api2.git");
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .contentType(APPLICATION_JSON)
+ .body(JsonHelper.toJson(asDto(existed, user)))
+ .when()
+ .expect()
+ .statusCode(200)
+ .put(SERVICE_PATH + "/" + FACTORY_ID);
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).thenReturn(beforeFactory);
-
- // when, then
- Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
- .contentType(MediaType.APPLICATION_JSON)
- .body(JsonHelper.toJson(afterFactory))
- .when()
- .put("/private" + SERVICE_PATH + "/" + CORRECT_FACTORY_ID);
-
- assertEquals(response.getStatusCode(), 200);
-
- Factory responseFactory = dto.createDtoFromJson(response.getBody().asInputStream(), Factory.class);
- assertEquals(responseFactory.getWorkspace(), afterFactory.getWorkspace());
-
-
- // check there was a call on the update operation with expected ID
- verify(factoryStore).updateFactory(eq(CORRECT_FACTORY_ID), any(Factory.class));
+ final FactoryDto result = getFromResponse(response, FactoryDto.class);
+ verify(factoryManager, times(1)).updateFactory(any());
+ assertEquals(result.withLinks(emptyList()), asDto(update, user));
}
- /**
- * Checks that the user can not update an unknown existing factory
- */
@Test
- public void shouldNotBeAbleToUpdateAnUnknownFactory() throws Exception {
- // given
- Factory factory = prepareFactoryWithGivenStorage("git", "http://github.com/codenvy/platform-api.git");
- doThrow(new NotFoundException(format("Factory with id %s is not found.", ILLEGAL_FACTORY_ID))).when(factoryStore)
- .getFactory(anyString());
+ public void shouldThrowNotFoundExceptionWhenUpdatingNonExistingFactory() throws Exception {
+ final Factory factory = createFactoryWithStorage(FACTORY_NAME,
+ "git",
+ "http://github.com/codenvy/platform-api.git");
+ doThrow(new NotFoundException(format("Factory with id %s is not found.", FACTORY_ID))).when(factoryManager)
+ .getById(anyString());
- // when, then
- Response response = given().auth().basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
- .contentType(MediaType.APPLICATION_JSON)
- .body(JsonHelper.toJson(factory))
- .when()
- .put("/private" + SERVICE_PATH + "/" + ILLEGAL_FACTORY_ID);
+ final Response response = given().auth().basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .contentType(APPLICATION_JSON)
+ .body(JsonHelper.toJson(factory))
+ .when()
+ .put(SERVICE_PATH + "/" + FACTORY_ID);
assertEquals(response.getStatusCode(), 404);
- assertEquals(dto.createDtoFromJson(response.getBody().asString(), ServiceError.class).getMessage(),
- format("Factory with id %s is not found.", ILLEGAL_FACTORY_ID));
+ assertEquals(DTO.createDtoFromJson(response.getBody().asString(), ServiceError.class).getMessage(),
+ format("Factory with id %s is not found.", FACTORY_ID));
}
- /**
- * Checks that the user can not update a factory with a null one
- */
@Test
public void shouldNotBeAbleToUpdateANullFactory() throws Exception {
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .contentType(APPLICATION_JSON)
+ .when()
+ .put(SERVICE_PATH + "/" + FACTORY_ID);
- // when, then
- Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
- .contentType(MediaType.APPLICATION_JSON)
- .when()
- .put("/private" + SERVICE_PATH + "/" + ILLEGAL_FACTORY_ID);
-
- assertEquals(response.getStatusCode(), BAD_REQUEST.getStatusCode());
- assertEquals(dto.createDtoFromJson(response.getBody().asString(), ServiceError.class).getMessage(),
- "The factory information is not updateable");
-
- }
-
- @Test(dataProvider = "badSnippetTypeProvider")
- public void shouldResponse409OnGetSnippetIfTypeIsIllegal(String type) throws Exception {
- // given
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).thenReturn(dto.createDto(Factory.class));
-
- // when, then
- Response response = given().expect()
- .statusCode(BAD_REQUEST.getStatusCode())
- .when()
- .get(SERVICE_PATH + "/" + CORRECT_FACTORY_ID + "/snippet?type=" + type);
-
- assertEquals(dto.createDtoFromJson(response.getBody().asString(), ServiceError.class).getMessage(),
- format("Snippet type \"%s\" is unsupported.", type));
- }
-
- @DataProvider(name = "badSnippetTypeProvider")
- public Object[][] badSnippetTypeProvider() {
- return new String[][]{{""},
- {null},
- {"mark"}};
- }
-
- private String getServerUrl(ITestContext context) {
- String serverPort = String.valueOf(context.getAttribute(EverrestJetty.JETTY_PORT));
- return "http://localhost:" + serverPort;
- }
-
-
- @Test
- public void shouldNotFindWhenNoAttributesProvided() throws Exception {
- // when
- Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
- .when()
- .get("/private" + SERVICE_PATH + "/find");
- // then
- assertEquals(response.getStatusCode(), BAD_REQUEST.getStatusCode());
+ assertEquals(response.getStatusCode(), 400);
+ assertEquals(DTO.createDtoFromJson(response.getBody().asString(), ServiceError.class)
+ .getMessage(), "Factory configuration required");
}
@Test
- public void shouldFindByAttribute() throws Exception {
- // given
- Factory factory = prepareFactoryWithGivenStorage("git", "http://github.com/codenvy/platform-api.git")
- .withId(CORRECT_FACTORY_ID)
- .withCreator(dto.createDto(Author.class).withUserId("uid-123"));
+ public void shouldRemoveFactoryByGivenIdentifier() throws Exception {
+ final Factory factory = createFactory();
+ when(factoryManager.getById(FACTORY_ID)).thenReturn(factory);
- List> expected = singletonList(Pair.of("creator.userid", "uid-123"));
- when(factoryStore.findByAttribute(anyInt(), anyInt(), eq(expected))).thenReturn(
- Arrays.asList(factory, factory));
+ given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .param("id", FACTORY_ID)
+ .expect()
+ .statusCode(204)
+ .when()
+ .delete(SERVICE_PATH + "/" + FACTORY_ID);
- // when
- Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
- .when()
- .get("/private" + SERVICE_PATH + "/find?creator.userid=uid-123");
-
- // then
- assertEquals(response.getStatusCode(), 200);
- List responseFactories = dto.createListDtoFromJson(response.getBody().asString(), Factory.class);
- assertEquals(responseFactories.size(), 2);
+ verify(factoryManager).removeFactory(FACTORY_ID);
}
-
@Test
- public void shouldGenerateFactoryJsonIncludeAllProjects() throws Exception {
- // given
- final String wsId = "workspace123234";
- WorkspaceImpl.WorkspaceImplBuilder userWs = WorkspaceImpl.builder();
- WorkspaceConfigImpl.WorkspaceConfigImplBuilder wsConfig = WorkspaceConfigImpl.builder();
+ public void shouldNotThrowAnyExceptionWhenRemovingNonExistingFactory() throws Exception {
+ doNothing().when(factoryManager).removeFactory(anyString());
- wsConfig.setProjects(Arrays.asList(dto.createDto(ProjectConfigDto.class)
- .withSource(dto.createDto(SourceStorageDto.class)
- .withType("git")
- .withLocation("location"))
- .withPath("path"),
- dto.createDto(ProjectConfigDto.class)
- .withSource(dto.createDto(SourceStorageDto.class)
- .withType("git")
- .withLocation("location"))
- .withPath("path")));
- wsConfig.setName("wsname");
- wsConfig.setDefaultEnv("env1");
- wsConfig.setEnvironments(singletonMap("env1", dto.createDto(EnvironmentDto.class)));
- wsConfig.setCommands(singletonList(dto.createDto(CommandDto.class)
- .withName("MCI")
- .withType("mvn")
- .withCommandLine("clean install")));
- userWs.setId(wsId);
- userWs.setNamespace("id-2314");
- userWs.setStatus(WorkspaceStatus.RUNNING);
- userWs.setConfig(wsConfig.build());
-
- WorkspaceImpl usersWorkspace = userWs.build();
- when(workspaceManager.getWorkspace(eq(wsId))).thenReturn(usersWorkspace);
-
- // when
Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .param("id", FACTORY_ID)
.when()
- .get("/private" + SERVICE_PATH + "/workspace/" + wsId);
+ .delete(SERVICE_PATH + "/" + FACTORY_ID);
- // then
- assertEquals(response.getStatusCode(), 200);
- Factory result = dto.createDtoFromJson(response.getBody().asString(), Factory.class);
- assertEquals(result.getWorkspace().getProjects().size(), 2);
- assertEquals(result.getWorkspace().getName(), usersWorkspace.getConfig().getName());
- assertEquals(result.getWorkspace()
- .getEnvironments()
- .toString(),
- usersWorkspace.getConfig()
- .getEnvironments()
- .entrySet()
- .stream()
- .collect(Collectors.toMap(Map.Entry::getKey, entry -> asDto(entry.getValue())))
- .toString());
- assertEquals(result.getWorkspace().getCommands().get(0), asDto(usersWorkspace.getConfig().getCommands().get(0)));
+ assertEquals(response.getStatusCode(), 204);
}
@Test
@@ -1056,22 +536,21 @@ public class FactoryServiceTest {
WorkspaceImpl.WorkspaceImplBuilder ws = WorkspaceImpl.builder();
WorkspaceConfigImpl.WorkspaceConfigImplBuilder wsConfig = WorkspaceConfigImpl.builder();
ws.setId(wsId);
- wsConfig.setProjects(Arrays.asList(dto.createDto(ProjectConfigDto.class)
- .withPath("/proj1")
- .withSource(dto.createDto(SourceStorageDto.class)
- .withType("git")
- .withLocation("location")),
- dto.createDto(ProjectConfigDto.class)
- .withPath("/proj2")
- .withSource(dto.createDto(SourceStorageDto.class)
- .withType("git")
- .withLocation("location"))));
+ wsConfig.setProjects(Arrays.asList(DTO.createDto(ProjectConfigDto.class)
+ .withPath("/proj1")
+ .withSource(DTO.createDto(SourceStorageDto.class)
+ .withType("git")
+ .withLocation("location")),
+ DTO.createDto(ProjectConfigDto.class)
+ .withPath("/proj2")
+ .withSource(DTO.createDto(SourceStorageDto.class)
+ .withType("git")
+ .withLocation("location"))));
wsConfig.setName("wsname");
- ws.setNamespace("id-2314");
- wsConfig.setEnvironments(singletonMap("env1", dto.createDto(EnvironmentDto.class)));
+ wsConfig.setEnvironments(singletonMap("env1", DTO.createDto(EnvironmentDto.class)));
wsConfig.setDefaultEnv("env1");
ws.setStatus(WorkspaceStatus.RUNNING);
- wsConfig.setCommands(singletonList(dto.createDto(CommandDto.class)
+ wsConfig.setCommands(singletonList(DTO.createDto(CommandDto.class)
.withName("MCI")
.withType("mvn")
.withCommandLine("clean install")));
@@ -1081,158 +560,72 @@ public class FactoryServiceTest {
// when
Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.when()
.get("/private" + SERVICE_PATH + "/workspace/" + wsId);
// then
assertEquals(response.getStatusCode(), 200);
- Factory result = dto.createDtoFromJson(response.getBody().asString(), Factory.class);
+ FactoryDto result = DTO.createDtoFromJson(response.getBody().asString(), FactoryDto.class);
assertEquals(result.getWorkspace().getProjects().size(), 2);
}
@Test
- public void shouldThrowServerExceptionDuringSaveFactory() throws Exception {
- // given
- Factory factory = prepareFactoryWithGivenStorage("git", "http://github.com/codenvy/che-core.git");
- URL resource = Thread.currentThread().getContextClassLoader().getResource("100x100_image.jpeg");
- assertNotNull(resource);
- Path path = Paths.get(resource.toURI());
- doThrow(IOException.class).when(factoryStore).saveFactory(any(Factory.class), anySetOf(FactoryImage.class));
+ public void shouldReturnFactoryImageWithGivenName() throws Exception {
+ final byte[] imageContent = Files.readAllBytes(getImagePath());
+ final FactoryImage image = new FactoryImage(imageContent, FACTORY_IMAGE_MIME_TYPE, IMAGE_NAME);
+ when(factoryManager.getFactoryImages(FACTORY_ID, IMAGE_NAME)).thenReturn(ImmutableSet.of(image));
- // when, then
- Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
- .multiPart("factory", JsonHelper.toJson(factory), MediaType.APPLICATION_JSON)
- .multiPart("image", path.toFile(), "image/jpeg")
- .when()
- .post("/private" + SERVICE_PATH);
- assertEquals(response.getStatusCode(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
+ final Response response = given().when()
+ .expect()
+ .statusCode(200)
+ .get(SERVICE_PATH + "/" + FACTORY_ID + "/image?imgId=" + IMAGE_NAME);
+
+ assertEquals(response.getContentType(), FACTORY_IMAGE_MIME_TYPE);
+ assertEquals(response.getHeader("content-length"), String.valueOf(imageContent.length));
+ assertEquals(response.asByteArray(), imageContent);
}
@Test
- public void shouldThrowBadRequestExceptionWhenInvalidFactoryPost() throws Exception {
- // given
- URL resource = Thread.currentThread().getContextClassLoader().getResource("100x100_image.jpeg");
- assertNotNull(resource);
- Path path = Paths.get(resource.toURI());
+ public void shouldReturnFirstFoundFactoryImageWhenImageNameNotSpecified() throws Exception {
+ final byte[] imageContent = Files.readAllBytes(getImagePath());
+ final FactoryImage image = new FactoryImage(imageContent, FACTORY_IMAGE_MIME_TYPE, IMAGE_NAME);
+ when(factoryManager.getFactoryImages(FACTORY_ID)).thenReturn(ImmutableSet.of(image));
- // when, then
- Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
- .multiPart("factory", "invalid factory", MediaType.APPLICATION_JSON)
- .multiPart("image", path.toFile(), "image/jpeg")
- .when()
- .post("/private" + SERVICE_PATH);
- assertEquals(response.getStatusCode(), BAD_REQUEST.getStatusCode());
+ final Response response = given().when()
+ .expect()
+ .statusCode(200)
+ .get(SERVICE_PATH + "/" + FACTORY_ID + "/image");
+
+ assertEquals(response.getContentType(), "image/jpeg");
+ assertEquals(response.getHeader("content-length"), String.valueOf(imageContent.length));
+ assertEquals(response.asByteArray(), imageContent);
}
@Test
- public void shouldSaveFactoryWithoutImages() throws Exception {
- // given
- Factory factory = prepareFactoryWithGivenStorage("git", "http://github.com/codenvy/che-core.git");
- factory.withCreator(dto.createDto(Author.class).withName("username"));
- FactorySaveAnswer factorySaveAnswer = new FactorySaveAnswer();
+ public void shouldThrowNotFoundExceptionWhenFactoryImageWithGivenIdentifierIsNotExist() throws Exception {
+ final String errMessage = "Image with name " + IMAGE_NAME + " is not found";
+ when(factoryManager.getFactoryImages(FACTORY_ID, IMAGE_NAME)).thenThrow(new NotFoundException(errMessage));
- when(factoryStore.saveFactory(any(Factory.class), anySetOf(FactoryImage.class))).then(factorySaveAnswer);
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).then(factorySaveAnswer);
+ final Response response = given().expect()
+ .statusCode(404)
+ .when()
+ .get(SERVICE_PATH + "/" + FACTORY_ID + "/image?imgId=" + IMAGE_NAME);
- // when, then
- Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
- .contentType(ContentType.JSON)
- .body(factory)
- .post("/private" + SERVICE_PATH);
- assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+ assertEquals(getFromResponse(response, ServiceError.class).getMessage(), errMessage);
}
@Test
- public void shouldThrowBadRequestExceptionWhenTriedToStoreInvalidFactory() throws Exception {
- // given
- Factory factory = prepareFactoryWithGivenStorage("git", "http://github.com/codenvy/che-core.git");
- factory.withCreator(dto.createDto(Author.class).withName("username"));
-
- // when, then
- Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
- .contentType(ContentType.JSON)
- .body("")
- .post("/private" + SERVICE_PATH);
- assertEquals(response.getStatusCode(), BAD_REQUEST.getStatusCode());
- }
-
- @Test
- public void shouldThrowServerExceptionWhenImpossibleCreateLinksForSavedFactory() throws Exception {
- // given
- Factory factory = prepareFactoryWithGivenStorage("git", "http://github.com/codenvy/che-core.git");
- factory.withCreator(dto.createDto(Author.class).withName("username"));
- doThrow(UnsupportedEncodingException.class).when(factoryStore).getFactory(anyString());
-
- // when, then
- Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
- .contentType(ContentType.JSON)
- .body("{}")
- .post("/private" + SERVICE_PATH);
- assertEquals(response.getStatusCode(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
- }
-
- @Test
- public void shouldThrowExceptionDuringGetFactory() throws Exception {
- // given
- doThrow(UnsupportedEncodingException.class).when(factoryStore).getFactoryImages(anyString(), anyString());
-
- // when, then
- Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
- .get("/private" + SERVICE_PATH + "/factoryId");
- assertEquals(response.getStatusCode(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
- }
-
- @Test
- public void shouldGetFactoryAndValidateItOnAccept() throws Exception {
- // given
- Factory factory = dto.createDto(Factory.class)
- .withCreator(dto.createDto(Author.class)
- .withName(JettyHttpServer.ADMIN_USER_NAME)
- .withUserId(userId))
- .withId(CORRECT_FACTORY_ID);
- when(factoryStore.getFactory(CORRECT_FACTORY_ID)).thenReturn(factory);
- doNothing().when(acceptValidator).validateOnAccept(factory);
-
- // when, then
- Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
- .get("/private" + SERVICE_PATH + '/' + CORRECT_FACTORY_ID + "?validate=true");
- assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
- }
-
- @Test
- public void should() throws Exception {
- // given
- Factory factory = dto.createDto(Factory.class)
- .withCreator(dto.createDto(Author.class)
- .withName(JettyHttpServer.ADMIN_USER_NAME)
- .withUserId(userId))
- .withId(CORRECT_FACTORY_ID);
- factory.setId(CORRECT_FACTORY_ID);
-
- Factory storedFactory = dto.createDto(Factory.class)
- .withId(CORRECT_FACTORY_ID)
- .withCreator(dto.createDto(Author.class).withCreated(10L));
- when(factoryStore.getFactory(anyString())).thenReturn(storedFactory);
- doThrow(UnsupportedEncodingException.class).when(factoryStore).getFactoryImages(anyString(), anyString());
-
- // when, then
- Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
- .contentType(MediaType.APPLICATION_JSON)
- .body(JsonHelper.toJson(factory))
- .when()
- .put("/private" + SERVICE_PATH + "/" + CORRECT_FACTORY_ID);
-
- assertEquals(response.getStatusCode(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
+ public void shouldBeAbleToReturnUrlSnippet() throws Exception {
+ final String result = "snippet";
+ when(factoryManager.getFactorySnippet(anyString(), anyString(), any(URI.class))).thenReturn(result);
+ given().expect()
+ .statusCode(200)
+ .contentType(TEXT_PLAIN)
+ .body(equalTo(result))
+ .when()
+ .get(SERVICE_PATH + "/" + FACTORY_ID + "/snippet?type=url");
}
@Test
@@ -1242,17 +635,16 @@ public class FactoryServiceTest {
WorkspaceImpl.WorkspaceImplBuilder ws = WorkspaceImpl.builder();
WorkspaceConfigImpl.WorkspaceConfigImplBuilder wsConfig = WorkspaceConfigImpl.builder();
ws.setId(wsId);
- wsConfig.setProjects(Arrays.asList(dto.createDto(ProjectConfigDto.class)
- .withPath("/proj1"),
- dto.createDto(ProjectConfigDto.class)
- .withPath("/proj2")));
+ wsConfig.setProjects(Arrays.asList(DTO.createDto(ProjectConfigDto.class)
+ .withPath("/proj1"),
+ DTO.createDto(ProjectConfigDto.class)
+ .withPath("/proj2")));
wsConfig.setName("wsname");
- ws.setNamespace("id-2314");
- wsConfig.setEnvironments(singletonMap("env1", dto.createDto(EnvironmentDto.class)));
+ wsConfig.setEnvironments(singletonMap("env1", DTO.createDto(EnvironmentDto.class)));
wsConfig.setDefaultEnv("env1");
ws.setStatus(WorkspaceStatus.RUNNING);
wsConfig.setCommands(singletonList(
- dto.createDto(CommandDto.class).withName("MCI").withType("mvn").withCommandLine("clean install")));
+ DTO.createDto(CommandDto.class).withName("MCI").withType("mvn").withCommandLine("clean install")));
ws.setConfig(wsConfig.build());
WorkspaceImpl usersWorkspace = ws.build();
@@ -1260,203 +652,160 @@ public class FactoryServiceTest {
// when
Response response = given().auth()
- .basic(JettyHttpServer.ADMIN_USER_NAME, JettyHttpServer.ADMIN_USER_PASSWORD)
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.when()
- .get("/private" + SERVICE_PATH + "/workspace/" + wsId);
+ .get(SERVICE_PATH + "/workspace/" + wsId);
// then
assertEquals(response.getStatusCode(), BAD_REQUEST.getStatusCode());
}
-
-
- /**
- * Check that if no resolver is plugged, we have correct error
- */
@Test
- public void noResolver() throws Exception {
- Set resolvers = new HashSet<>();
- when(factoryParametersResolvers.stream()).thenReturn(resolvers.stream());
+ public void shouldResponse404OnGetSnippetIfFactoryDoesNotExist() throws Exception {
+ // given
+ doThrow(new NotFoundException("Factory URL with id " + FACTORY_ID + " is not found."))
+ .when(factoryManager).getFactorySnippet(anyString(), anyString(), any());
- Map map = new HashMap<>();
- // when
- Response response = given().contentType(ContentType.JSON).when().body(map).post(SERVICE_PATH_RESOLVER);
+ // when, then
+ final Response response = given().expect()
+ .statusCode(404)
+ .when()
+ .get(SERVICE_PATH + "/" + FACTORY_ID + "/snippet?type=url");
- // then check we have a not found
- assertEquals(response.getStatusCode(), NOT_FOUND.getStatusCode());
- assertTrue(response.getBody().prettyPrint().contains(ERROR_NO_RESOLVER_AVAILABLE));
- }
-
-
- /**
- * Check that if there is a matching resolver, factory is created
- */
- @Test
- public void matchingResolver() throws Exception {
- Set resolvers = new HashSet<>();
- when(factoryParametersResolvers.stream()).thenReturn(resolvers.stream());
- FactoryParametersResolver dummyResolver = mock(FactoryParametersResolver.class);
- resolvers.add(dummyResolver);
-
- // create factory
- Factory expectFactory = dto.createDto(Factory.class).withV("4.0").withName("matchingResolverFactory");
-
- // accept resolver
- when(dummyResolver.accept(anyMap())).thenReturn(TRUE);
- when(dummyResolver.createFactory(anyMap())).thenReturn(expectFactory);
-
- // when
- Map map = new HashMap<>();
- Response response = given().contentType(ContentType.JSON).when().body(map).post(SERVICE_PATH_RESOLVER);
-
- // then check we have a not found
- assertEquals(response.getStatusCode(), OK.getStatusCode());
- Factory responseFactory = dto.createDtoFromJson(response.getBody().asInputStream(), Factory.class);
- assertNotNull(responseFactory);
- assertEquals(responseFactory.getName(), expectFactory.getName());
- assertEquals(responseFactory.getV(), expectFactory.getV());
-
- // check we call resolvers
- verify(dummyResolver).accept(anyMap());
- verify(dummyResolver).createFactory(anyMap());
- }
-
-
- /**
- * Check that if there is no matching resolver, there is error
- */
- @Test
- public void notMatchingResolver() throws Exception {
- Set resolvers = new HashSet<>();
- when(factoryParametersResolvers.stream()).thenReturn(resolvers.stream());
-
- FactoryParametersResolver dummyResolver = mock(FactoryParametersResolver.class);
- resolvers.add(dummyResolver);
- FactoryParametersResolver fooResolver = mock(FactoryParametersResolver.class);
- resolvers.add(fooResolver);
-
-
- // accept resolver
- when(dummyResolver.accept(anyMap())).thenReturn(FALSE);
- when(fooResolver.accept(anyMap())).thenReturn(FALSE);
-
- // when
- Map map = new HashMap<>();
- Response response = given().contentType(ContentType.JSON).when().body(map).post(SERVICE_PATH_RESOLVER);
-
- // then check we have a not found
- assertEquals(response.getStatusCode(), NOT_FOUND.getStatusCode());
-
- // check we never call create factories on resolver
- verify(dummyResolver, never()).createFactory(anyMap());
- verify(fooResolver, never()).createFactory(anyMap());
+ assertEquals(getFromResponse(response, ServiceError.class).getMessage(),
+ "Factory URL with id " + FACTORY_ID + " is not found.");
}
/**
- * Check that if there is a matching resolver and other not matching, factory is created
+ * Checks that the user can remove an existing factory
*/
@Test
- public void onlyOneMatchingResolver() throws Exception {
- Set resolvers = new HashSet<>();
- when(factoryParametersResolvers.stream()).thenReturn(resolvers.stream());
+ public void shouldBeAbleToRemoveFactory() throws Exception {
+ final Factory factory = createFactory();
+ when(factoryManager.getById(FACTORY_ID)).thenReturn(factory);
- FactoryParametersResolver dummyResolver = mock(FactoryParametersResolver.class);
- resolvers.add(dummyResolver);
- FactoryParametersResolver fooResolver = mock(FactoryParametersResolver.class);
- resolvers.add(fooResolver);
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .param("id", FACTORY_ID)
+ .when()
+ .delete(SERVICE_PATH + "/" + FACTORY_ID);
- // create factory
- Factory expectFactory = dto.createDto(Factory.class).withV("4.0").withName("matchingResolverFactory");
+ assertEquals(response.getStatusCode(), 204);
- // accept resolver
- when(dummyResolver.accept(anyMap())).thenReturn(TRUE);
- when(dummyResolver.createFactory(anyMap())).thenReturn(expectFactory);
- when(fooResolver.accept(anyMap())).thenReturn(FALSE);
-
- // when
- Map map = new HashMap<>();
- Response response = given().contentType(ContentType.JSON).when().body(map).post(SERVICE_PATH_RESOLVER);
-
- // then check we have a not found
- assertEquals(response.getStatusCode(), OK.getStatusCode());
- Factory responseFactory = dto.createDtoFromJson(response.getBody().asInputStream(), Factory.class);
- assertNotNull(responseFactory);
- assertEquals(responseFactory.getName(), expectFactory.getName());
- assertEquals(responseFactory.getV(), expectFactory.getV());
-
- // check we call resolvers
- verify(dummyResolver).accept(anyMap());
- verify(dummyResolver).createFactory(anyMap());
- // never called this resolver
- verify(fooResolver, never()).createFactory(anyMap());
+ // check there was a call on the remove operation with expected ID
+ verify(factoryManager).removeFactory(FACTORY_ID);
}
+ @Test
+ public void shouldNotThrowExceptionWhenRemoveNoExistingFactory() throws Exception {
+ doNothing().when(factoryManager).removeFactory(FACTORY_ID);
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .param("id", FACTORY_ID)
+ .when()
+ .delete(SERVICE_PATH + "/" + FACTORY_ID);
+
+ assertEquals(response.getStatusCode(), 204);
+ }
- /**
- * Check that if there is a matching resolver, that factory is valid
- */
@Test
public void checkValidateResolver() throws Exception {
- Set resolvers = new HashSet<>();
- when(factoryParametersResolvers.stream()).thenReturn(resolvers.stream());
-
- FactoryParametersResolver dummyResolver = mock(FactoryParametersResolver.class);
- resolvers.add(dummyResolver);
+ final FactoryParametersResolver dummyResolver = Mockito.mock(FactoryParametersResolver.class);
+ factoryParametersResolvers.add(dummyResolver);
// invalid factory
- String invalidFactoryMessage = "invalid factory";
+ final String invalidFactoryMessage = "invalid factory";
doThrow(new BadRequestException(invalidFactoryMessage)).when(acceptValidator).validateOnAccept(any());
// create factory
- Factory expectFactory = dto.createDto(Factory.class).withV("4.0").withName("matchingResolverFactory");
+ final FactoryDto expectFactory = DTO.createDto(FactoryDto.class).withV("4.0").withName("matchingResolverFactory");
// accept resolver
- when(dummyResolver.accept(anyMap())).thenReturn(TRUE);
- when(dummyResolver.createFactory(anyMap())).thenReturn(expectFactory);
+ when(dummyResolver.accept(anyMapOf(String.class, String.class))).thenReturn(true);
+ when(dummyResolver.createFactory(anyMapOf(String.class, String.class))).thenReturn(expectFactory);
// when
- Map map = new HashMap<>();
- Response response = given().contentType(ContentType.JSON).when().body(map).queryParam(VALIDATE_QUERY_PARAMETER, valueOf(true)).post(
- SERVICE_PATH_RESOLVER);
+ final Map map = new HashMap<>();
+ final Response response = given().contentType(ContentType.JSON)
+ .when()
+ .body(map)
+ .queryParam(VALIDATE_QUERY_PARAMETER, valueOf(true))
+ .post(SERVICE_PATH + "/resolver");
// then check we have a not found
assertEquals(response.getStatusCode(), BAD_REQUEST.getStatusCode());
assertTrue(response.getBody().prettyPrint().contains(invalidFactoryMessage));
// check we call resolvers
- verify(dummyResolver).accept(anyMap());
- verify(dummyResolver).createFactory(anyMap());
+ verify(dummyResolver).accept(anyMapOf(String.class, String.class));
+ verify(dummyResolver).createFactory(anyMapOf(String.class, String.class));
// check we call validator
verify(acceptValidator).validateOnAccept(any());
-
}
- private Factory prepareFactoryWithGivenStorage(String type, String location) {
- return dto.createDto(Factory.class)
- .withV("4.0")
- .withWorkspace(dto.createDto(WorkspaceConfigDto.class)
- .withProjects(singletonList(dto.createDto(ProjectConfigDto.class)
- .withSource(dto.createDto(SourceStorageDto.class)
- .withType(type)
- .withLocation(location)))));
+ private Factory createFactory() {
+ return createNamedFactory(FACTORY_NAME);
}
- private class FactorySaveAnswer implements Answer