Skip to content

Commit

Permalink
Merge pull request #1393 from eclipse/CHE-1078
Browse files Browse the repository at this point in the history
CHE-1078: UserService structural refactorings
  • Loading branch information
Yevhenii Voevodin authored Jul 5, 2016
2 parents 8550a30 + d1aa2cf commit 2929688
Show file tree
Hide file tree
Showing 117 changed files with 5,188 additions and 2,568 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import org.eclipse.che.api.project.server.ProjectApiModule;
import org.eclipse.che.api.ssh.server.HttpSshServiceClient;
import org.eclipse.che.api.ssh.server.SshServiceClient;
import org.eclipse.che.api.user.server.dao.PreferenceDao;
import org.eclipse.che.api.user.server.spi.PreferenceDao;
import org.eclipse.che.commons.lang.Pair;
import org.eclipse.che.everrest.CheAsynchronousJobPool;
import org.eclipse.che.api.git.LocalGitUserResolver;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.google.inject.name.Names;

import org.eclipse.che.api.machine.shared.Constants;
import org.eclipse.che.api.user.server.ProfileService;
import org.eclipse.che.inject.DynaModule;
import org.everrest.guice.ServiceBindingHelper;

Expand All @@ -30,7 +31,8 @@ protected void configure() {
bind(org.eclipse.che.api.ssh.server.SshService.class);
bind(org.eclipse.che.api.machine.server.recipe.RecipeService.class);
bind(org.eclipse.che.api.user.server.UserService.class);
bind(org.eclipse.che.api.user.server.UserProfileService.class);
bind(org.eclipse.che.api.user.server.ProfileService.class);
bind(org.eclipse.che.api.user.server.PreferencesService.class);
bind(org.eclipse.che.api.workspace.server.stack.StackLoader.class);
bind(org.eclipse.che.api.workspace.server.stack.StackService.class);
bind(org.eclipse.che.api.workspace.server.WorkspaceService.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -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.api.core.model.user;

import java.util.Map;

/**
* Defines the user's profile model.
*
* <p>User's profile describes an additional user information such as his
* job title or company name which is not related to application business logic.
* If it is necessary to manage business logic related attributes then
* user's preferences should be used instead.
*
* @author Yevhenii Voevodin
* @see User
*/
public interface Profile {

/**
* Returns the identifier of the user {@link User#getId()}
* whom this profile belongs to.
*/
String getUserId();

/**
* Returns the user profile attributes (e.g. job title).
*/
Map<String, String> getAttributes();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*******************************************************************************
* 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.user;

import org.eclipse.che.commons.annotation.Nullable;

import java.util.List;

/**
* Defines the user model.
*
* @author Yevhenii Voevodin
*/
public interface User {

/**
* Returns the identifier of the user (e.g. "user0x124567890").
* The identifier value is unique and mandatory.
*/
String getId();

/**
* Returns the user's email (e.g. [email protected]).
* The email is unique, mandatory and updatable.
*/
String getEmail();

/**
* Returns the user's name (e.g. name_example).
* The name is unique, mandatory and updatable.
*/
String getName();

/**
* Returns the list of the user's aliases, the aliases are the values
* which identify user in the system with third party ids (e.g. if user is registered
* within google oauth the aliases list may contain 'google:user_identifier' alias).
*
* <p>Note that user's {@link #getEmail() email} and {@link #getName() name}
* are not a part of the result, and returned list never contains those values.
* Also note that returned aliases are unique, so there are no two users
* who have the alias in common.
*/
List<String> getAliases();

/**
* Returns the user's password.
* The returned value may be the password placeholder such as 'none' or
* even null, depends on the context.
*/
@Nullable
String getPassword();
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@
<source path="machine"/>
<source path="project"/>
<source path="workspace"/>
<source path="user"/>

</module>
22 changes: 22 additions & 0 deletions core/commons/che-core-commons-test/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,32 @@
<artifactId>che-core-commons-test</artifactId>
<packaging>jar</packaging>
<name>Che Core :: Commons :: Utilities for tests</name>
<properties>
<findbugs.failonerror>true</findbugs.failonerror>
</properties>
<dependencies>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*******************************************************************************
* 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 com.google.inject.AbstractModule;
import com.google.inject.Module;

import org.testng.IModuleFactory;
import org.testng.ITestContext;

import java.util.ServiceLoader;

/**
* Abstract class for those Guice {@link Module modules} which provide
* TCK tests components, which will be injected directly into the test class.
*
* <p>The {@link ServiceLoader} mechanism is used for loading such modules
* and for injecting them later. So each module which is TCK module must
* provide the implementations list(as described by {@code ServiceLoader} mechanism)
* in the file named <i>org.eclipse.che.commons.test.tck.TckModule</i> usually under
* <i>test/resources/META-INF/services</i> directory, then the {@link TckModuleFactory}
* will recognise and load it.
*
* @author Yevhenii Voevodin
* @see TckModuleFactory
*/
public abstract class TckModule extends AbstractModule {

/**
* It is guaranteed that this field is always present and
* can be reused by implementation, the value is equal to the
* {@link IModuleFactory#createModule(ITestContext, Class)} first
* parameter and will be set by {@link TckModuleFactory} immediately after module
* implementation is loaded by {@link ServiceLoader}.
*/
private ITestContext testContext;

/** Returns the {@link ITestContext context} of currently executing test suite. */
protected ITestContext getTestContext() {
return testContext;
}

/**
* Sets the context of currently executing test suite.
* This method designed to be used by {@link TckModuleFactory} for setting
* the context before installing modules.
*/
void setTestContext(ITestContext testContext) {
this.testContext = testContext;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*******************************************************************************
* 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 com.google.inject.AbstractModule;
import com.google.inject.Module;

import org.testng.IModuleFactory;
import org.testng.ITestContext;

import java.util.Iterator;
import java.util.ServiceLoader;

import static java.lang.String.format;

/**
* The factory is designed to instantiate {@link TckModule tck modules}
* using {@link ServiceLoader} mechanism. The components
* provided by those modules will be injected into a test class
* whether it's necessary to do so.
*
* <p>The factory expects at least one implementation of {@code TckModule}
* to be configured, if it doesn't find any of the {@code TckModule}
* implementations then it will report an appropriate exception
* and TckTest will fail(as it requires components to be injected into it).
* If it finds more than one {@code TckModule} implementation it will
* use all of the found.
*
* <p>The usage example:
* <pre>
* package org.eclipse.mycomponent;
*
* &#064;org.testng.annotations.Guice(moduleFactory = TckModuleFactory.class)
* // Good practice to define suiteName for TCK tests as it makes easier
* // to implement logic related to certain tests in ITestNGListener implementations
* &#064;org.testng.annotations.Test(suiteName = "MySuite")
* class SubjectTest {
*
* &#064;javax.inject.Inject
* private Component1 component1.
* &#064;javax.inject.Inject
* private Component2 component2;
*
* &#064;org.testng.annotations.Test
* public void test() {
* // use components
* }
* }
*
* class MyTckModule extends TckModule {
* public void configure() {
* bind(Component1.class).to(...);
* bind(Component2.class).toInstance(new Component2(() -> testContext.getAttribute("server_url").toString()));
* }
* }
*
* // Allows to add pre/post test actions like db server start/stop
* class DBServerListener implements ITestListener {
* // ...
* public void onStart(ITestContext context) {
* String url = dbServer.start();
* context.setAttribute("server_url", url)l
* }
*
* public void onFinish(ITestContext context) {
* dbServer.stop();
* }
* // ...
* }
* </pre>
*
* <p>Configuring:
* <pre>
* <i>META-INF/services/org.eclipse.che.commons.test.tck.TckModule</i>
* org.eclipse.mycomponent.MyTckModule
*
* <i>META-INF/services/org.testng.ITestNGListener</i>
* org.eclipse.mycomponent.DBServerListener
* </pre>
*
* @author Yevhenii Voevodin
* @see org.testng.annotations.Guice
* @see IModuleFactory
*/
public class TckModuleFactory implements IModuleFactory {

@Override
public Module createModule(ITestContext context, Class<?> testClass) {
final Iterator<TckModule> moduleIterator = ServiceLoader.load(TckModule.class).iterator();
if (!moduleIterator.hasNext()) {
throw new IllegalStateException(format("Couldn't find a TckModule configuration. " +
"You probably forgot to configure resources/META-INF/services/%s, or even " +
"provide an implementation of the TckModule which is required by the tck test class %s",
TckModule.class.getName(),
testClass.getName()));
}
return new CompoundModule(context, moduleIterator);
}

private static class CompoundModule extends AbstractModule {
private final ITestContext testContext;
private final Iterator<TckModule> moduleIterator;

private CompoundModule(ITestContext testContext, Iterator<TckModule> moduleIterator) {
this.testContext = testContext;
this.moduleIterator = moduleIterator;
}

@Override
protected void configure() {
bind(ITestContext.class).toInstance(testContext);
while (moduleIterator.hasNext()) {
final TckModule module = moduleIterator.next();
module.setTestContext(testContext);
install(module);
}
}
}
}
Loading

0 comments on commit 2929688

Please sign in to comment.