/******************************************************************************* * Copyright (c) 2013 RelationWare, Benno Luthiger * 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: * RelationWare, Benno Luthiger ******************************************************************************/ package org.ripla.rap.internal.services; import java.util.Collections; import java.util.Hashtable; import java.util.Map; import org.eclipse.rap.rwt.RWT; import org.eclipse.swt.widgets.Composite; import org.osgi.framework.Bundle; import org.osgi.service.useradmin.UserAdmin; import org.ripla.exceptions.NoControllerFoundException; import org.ripla.interfaces.IControllerConfiguration; import org.ripla.interfaces.IControllerSet; import org.ripla.rap.Constants; import org.ripla.rap.interfaces.IPluggable; import org.ripla.rap.internal.menu.DropDownMenu; import org.ripla.rap.internal.views.DefaultRiplaView; import org.ripla.rap.util.UseCaseHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The controller manager class.<br /> * Instances of this class are responsible for managing controllers provided by * the use case bundles. All controller classes are registered here. Therefore, * when the application calls a controller, this manager instance has to look up * the controller class and load it using the providing bundle's class loader. * Then, the controller instance is executed and the created view component are * returned to the application. * * @author Luthiger */ public final class ControllerManager { private static final Logger LOG = LoggerFactory .getLogger(ControllerManager.class); private final transient Map<String, BundleClassLoader> controllerMappingTable = Collections .synchronizedMap(new Hashtable<String, BundleClassLoader>()); private UserAdmin userAdmin = new NoOpUserAdmin(); /** * Loads the specified controller. This is the central part of the Ripla * application: The specified controller is looked up and ran for that it * returns the view it controls. * * @param inControllerName * String * @param inParent * {@link Composite} the parent the created component is placed * on * @return {@link Composite} */ public Composite getContent(final String inControllerName, final Composite inParent) throws NoControllerFoundException { final BundleClassLoader lLoader = controllerMappingTable .get(inControllerName); if (lLoader == null) { throw new NoControllerFoundException(inControllerName); } return runController(lLoader, inParent); } private Composite runController(final BundleClassLoader inLoader, final Composite inParent) { try { final IPluggable lController = inLoader.createLoader(); lController.setUserAdmin(userAdmin); lController.setParent(inParent); menuActivationHandling(inLoader.getSymbolicName()); return lController.run(); } catch (final Exception exc) { final Throwable lThrowable = exc; LOG.error("Problem during task execution.", lThrowable); //$NON-NLS-1$ return new DefaultRiplaView(inParent, exc); } } @SuppressWarnings("unchecked") private void menuActivationHandling(final String inBundleName) { final DropDownMenu lOldItem = (DropDownMenu) RWT.getUISession() .getAttribute(Constants.RS_MENU_ACTIVE); if (lOldItem != null && !lOldItem.isDisposed()) { lOldItem.setSelected(false); } final Map<String, DropDownMenu> lMenuMap = (Map<String, DropDownMenu>) RWT .getUISession().getAttribute(Constants.RS_MENU_MAP); final DropDownMenu lNewItem = lMenuMap.get(inBundleName); if (lNewItem != null) { lNewItem.setSelected(true); } RWT.getUISession().setAttribute(Constants.RS_MENU_ACTIVE, lNewItem); } /** * Registers the specified controller to the manager. * * @param inControllerSet * {@link IControllerSet} */ public void addControllerSet(final IControllerSet inControllerSet) { for (final IControllerConfiguration lControllerConfiguration : inControllerSet .getControllerConfigurations()) { final Bundle lBundle = lControllerConfiguration.getBundle(); final String lControllerName = lControllerConfiguration .getControllerName(); controllerMappingTable.put(UseCaseHelper .createFullyQualifiedControllerName(lBundle, lControllerName), new BundleClassLoader( // NOPMD lControllerName, lBundle)); } } /** * Unregisters the specified controller from the manager. * * @param inControllerSet * {@link IControllerSet} */ public void removeControllerSet(final IControllerSet inControllerSet) { for (final IControllerConfiguration lControllerConfiguration : inControllerSet .getControllerConfigurations()) { final Bundle lBundle = lControllerConfiguration.getBundle(); final String lControllerName = lControllerConfiguration .getControllerName(); final BundleClassLoader lLoader = controllerMappingTable .get(UseCaseHelper.createFullyQualifiedControllerName( lBundle, lControllerName)); if (lLoader != null) { lLoader.dispose(); controllerMappingTable.remove(lLoader); } } } /** * @param inUserAdmin */ public void setUserAdmin(final UserAdmin inUserAdmin) { userAdmin = inUserAdmin == null ? new NoOpUserAdmin() : inUserAdmin; } /** * @return {@link UserAdmin} the user admin instance */ public UserAdmin getUserAdmin() { return userAdmin; } // --- private static class BundleClassLoader { private final transient String controllerName; private transient Bundle bundle; public BundleClassLoader(final String inControllerName, final Bundle inBundle) { controllerName = inControllerName; bundle = inBundle; } /** * Uses the registered <code>Bundle</code> to load the controller. * * @return IPluggable The controller * @throws ClassNotFoundException * @throws InstantiationException * @throws IllegalAccessException */ public IPluggable createLoader() throws ClassNotFoundException, InstantiationException, IllegalAccessException { final Class<?> lClass = bundle.loadClass(controllerName); return (IPluggable) lClass.newInstance(); } @Override public String toString() { return controllerName; } protected String getSymbolicName() { return bundle.getSymbolicName(); } public void dispose() { bundle = null; // NOPMD by Luthiger on 09.09.12 23:46 } } }