/******************************************************************************* * Copyright (c) 2012-2015 EclipseSource Muenchen GmbH and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Otto von Wesendonk, Edgar Mueller - initial API and implementation ******************************************************************************/ package org.eclipse.emf.emfstore.internal.client.ui.dialogs.login; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import org.eclipse.core.runtime.Platform; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.emfstore.client.ESServer; import org.eclipse.emf.emfstore.client.ESUsersession; import org.eclipse.emf.emfstore.client.util.RunESCommand; import org.eclipse.emf.emfstore.internal.client.model.ESWorkspaceProviderImpl; import org.eclipse.emf.emfstore.internal.client.model.ServerInfo; import org.eclipse.emf.emfstore.internal.client.model.Usersession; import org.eclipse.emf.emfstore.internal.client.model.impl.api.ESUsersessionImpl; import org.eclipse.emf.emfstore.internal.client.model.impl.api.ESWorkspaceImpl; import org.eclipse.emf.emfstore.internal.client.model.util.WorkspaceUtil; import org.eclipse.emf.emfstore.internal.client.ui.common.RunInUI; import org.eclipse.emf.emfstore.internal.client.ui.dialogs.AbstractLoginDialog; import org.eclipse.emf.emfstore.internal.server.exceptions.AccessControlException; import org.eclipse.emf.emfstore.server.exceptions.ESException; import org.eclipse.jface.window.Window; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.osgi.framework.Bundle; /** * The login dialog controller manages a given {@link ESUsersession} and/or a {@link ESServer} to determine when it is * necessary to open a {@link AbstractLoginDialog} in order to authenticate the user. It does not, however, * open a dialog, if the {@link Usersession} is already logged in. * * @author ovonwesen * @author emueller */ public class LoginDialogController implements ILoginDialogController { private static final String CLIENT_UI_BUNDLE = "org.eclipse.emf.emfstore.client.ui"; //$NON-NLS-1$ private ESUsersession usersession; private ESServer server; private AbstractLoginDialog dialog; /** * * {@inheritDoc} * * @see org.eclipse.emf.emfstore.internal.client.ui.dialogs.login.ILoginDialogController#getKnownUsersessions() */ public List<ESUsersession> getKnownUsersessions() { final EList<Usersession> usersessions = ESWorkspaceProviderImpl.getInstance().getWorkspace().toInternalAPI() .getUsersessions(); final List<ESUsersession> knownSessions = new ArrayList<ESUsersession>(); for (final Usersession session : usersessions) { final ServerInfo serverInfo = session.getServerInfo(); // server info should never be null, but in case it is (whatever the reason may be) // make sure it does not kill the initialization of the login dialog if (serverInfo != null && serverInfo.toAPI() == server) { knownSessions.add(session.toAPI()); } } return knownSessions; } private ESUsersession login(final boolean force) throws ESException { if (server != null && server.getLastUsersession() != null && server.getLastUsersession().isLoggedIn() && !force) { // session seems to be valid, renew just in case the session timed out server.getLastUsersession().refresh(); return server.getLastUsersession(); } final Integer userInput = RunInUI.runWithResult(new Callable<Integer>() { public Integer call() throws Exception { dialog = newInstanceOf( "org.eclipse.emf.emfstore.internal.client.ui.dialogs.login.LoginDialog", //$NON-NLS-1$ Display.getCurrent().getActiveShell(), LoginDialogController.this); dialog.setBlockOnOpen(true); return dialog.open(); } }); if (userInput != Window.OK) { throw new AccessControlException(Messages.LoginDialogController_LoginFailed); } final Usersession session = dialog.getSelectedUsersession(); if (session == null) { throw new AccessControlException(Messages.LoginDialogController_LoginFailed); } final String password = dialog.getPassword(); final boolean savePassword = dialog.isSavePassword(); final boolean passwordModified = dialog.isPasswordModified(); RunESCommand.run(new Callable<Void>() { public Void call() throws Exception { session.setSavePassword(savePassword); if (passwordModified) { session.setPassword(password); } return null; } }); validate(session.toAPI()); // contract: #validate() sets the usersession; // TODO: validate can simply return the usersession.. return usersession; } private <T> T newInstanceOf(String clazz, Shell parentShell, ILoginDialogController controller) { try { final Class<T> c = loadClass(CLIENT_UI_BUNDLE, clazz); final T newInstance = c.getConstructor(Shell.class, ILoginDialogController.class).newInstance(parentShell, controller); return newInstance; } catch (final ClassNotFoundException ex) { WorkspaceUtil.logException(ex.getMessage(), ex); } catch (final InstantiationException ex) { WorkspaceUtil.logException(ex.getMessage(), ex); } catch (final IllegalAccessException ex) { WorkspaceUtil.logException(ex.getMessage(), ex); } catch (final IllegalArgumentException ex) { WorkspaceUtil.logException(ex.getMessage(), ex); } catch (final InvocationTargetException ex) { WorkspaceUtil.logException(ex.getMessage(), ex); } catch (final NoSuchMethodException ex) { WorkspaceUtil.logException(ex.getMessage(), ex); } catch (final SecurityException ex) { WorkspaceUtil.logException(ex.getMessage(), ex); } return null; } @SuppressWarnings("unchecked") private static <T> Class<T> loadClass(String bundleName, String clazz) throws ClassNotFoundException { final Bundle bundle = Platform.getBundle(bundleName); if (bundle == null) { throw new ClassNotFoundException(clazz + " cannot be loaded because bundle " + bundleName //$NON-NLS-1$ + " cannot be resolved"); //$NON-NLS-1$ } return (Class<T>) bundle.loadClass(clazz); } /** * Returns the server name. * * @return the label */ public String getServerLabel() { return getServer().getName(); } /** * * {@inheritDoc} * * @see org.eclipse.emf.emfstore.internal.client.ui.dialogs.login.ILoginDialogController#validate(org.eclipse.emf.emfstore.client.ESUsersession) */ public void validate(final ESUsersession session) throws ESException { final Usersession usersession = ((ESUsersessionImpl) session).toInternalAPI(); final ESWorkspaceImpl workspace = ESWorkspaceProviderImpl.getInstance().getWorkspace(); final EList<Usersession> usersessions = workspace.toInternalAPI().getUsersessions(); RunESCommand.WithException.run(ESException.class, new Callable<Void>() { public Void call() throws Exception { // TODO login code usersession.logIn(); // if successful, else exception is thrown prior reaching this code if (!usersessions.contains(usersession)) { usersessions.add(usersession); } return null; } }); this.usersession = session; ESWorkspaceProviderImpl.getInstance().getWorkspace().toInternalAPI().save(); } /** * * {@inheritDoc} * * @see org.eclipse.emf.emfstore.internal.client.ui.dialogs.login.ILoginDialogController#getUsersession() */ public ESUsersession getUsersession() { return usersession; } /** * * {@inheritDoc} * * @see org.eclipse.emf.emfstore.internal.client.ui.dialogs.login.ILoginDialogController#getServer() */ public ESServer getServer() { if (server != null) { return server; } return usersession.getServer(); } /** * Perform a login using an {@link ESUsersession} that can be determined with * the given {@link ESServer}. * * * @param server * the server info to be used in order to determine a valid * usersession * @param force * whether to force requesting the password * @return a logged-in usersession * @throws ESException * in case the login fails */ public ESUsersession login(ESServer server, boolean force) throws ESException { this.server = server; usersession = null; return login(force); } /** * Perform a login using the given {@link ESUsersession}. * * @param usersession * the usersession to be used during login * @param force * whether to force requesting the password * @throws ESException * in case the login fails */ public void login(ESUsersession usersession, boolean force) throws ESException { server = null; this.usersession = usersession; login(force); } /** * Perform a login using an {@link ESUsersession} that can be determined with * the given {@link ESServer}. * * * @param server * the server info to be used in order to determine a valid * usersession * @return a logged-in usersession * @throws ESException * in case the login fails */ public ESUsersession login(ESServer server) throws ESException { this.server = server; usersession = null; return login(false); } /** * Perform a login using the given {@link ESUsersession}. * * @param usersession * the usersession to be used during login * @return usersession * @throws ESException * in case the login fails */ public ESUsersession login(ESUsersession usersession) throws ESException { this.usersession = usersession; server = usersession.getServer(); return login(false); } }