at.spardat.xma.session.XMASessionClient Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2003, 2007 s IT Solutions AT Spardat GmbH .
* 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:
* s IT Solutions AT Spardat GmbH - initial API and implementation
*******************************************************************************/
// @(#) $Id: XMASessionClient.java 2611 2008-06-23 13:01:55Z gub $
package at.spardat.xma.session;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Timer;
import java.util.TimerTask;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import at.spardat.enterprise.exc.Notification;
import at.spardat.enterprise.exc.SysException;
import at.spardat.xma.baserpc.BaseRPCClient;
import at.spardat.xma.boot.BootRuntime;
import at.spardat.xma.boot.comp.AppContainer;
import at.spardat.xma.boot.component.IComponent;
import at.spardat.xma.boot.component.IRtXMASessionClient;
import at.spardat.xma.boot.logger.LogLevel;
import at.spardat.xma.boot.logger.Logger;
import at.spardat.xma.boot.transport.XMA_URI;
import at.spardat.xma.component.ComponentClient;
import at.spardat.xma.component.IComponentClient;
import at.spardat.xma.component.ProxyHandler;
import at.spardat.xma.event.global.GlobalEvent;
import at.spardat.xma.event.global.GlobalEventListener;
import at.spardat.xma.exception.Codes;
import at.spardat.xma.page.NotificationBox;
import at.spardat.xma.pipes.XMAPipe;
import at.spardat.xma.plugins.PluginManager;
import at.spardat.xma.plugins.PluginManagerClient;
import at.spardat.xma.security.XMACallbackHandler;
import at.spardat.xma.security.XMAContext;
import at.spardat.xma.security.XMALoginContext;
/**
* Manages all active Components at the client that are executing in a single
* JVM and belong to exactly one server side application instance.
*/
public class XMASessionClient extends XMASession implements IRtXMASessionClient {
private static final String PIPE_NAME = "at.spardat.xma.pipename";
/**
* The highest id assigned to a component in this session so far.
*/
private short lastComponentId_;
/**
* Holds a collection of Short s which are ids of components
* which have been destructed at the client but the server does not know
* anything about the destruction yet. Only stateful components needs to be
* managed here.
*/
private ArrayList deadComponents_ = new ArrayList();
/**
* Manages a collection of Component s that have been registered
* but not yet removed.
*/
private ArrayList components_ = new ArrayList();
/**
* The Id of the Session. If HTTP is used for Communiction the Id is the
* cookie.
*/
private String id;
/**
* The PluginManager is responsible for providing plugin implementations for
* provided interface names at the session level.
*/
private PluginManagerClient pluginManager_ = new PluginManagerClient(this);
/**
* for client side login via JAAS.
*/
private XMALoginContext loginContext;
/**
* the uri of the corresponding server application
*/
private XMA_URI baseUri;
/**
* informations about the application prepared by the boot runtime.
*/
private AppContainer appContainer_;
/**
* client side logger
*/
private Logger log;
/**
* timer for calling keepAlive periodically
*/
private Timer keepAliveTimer;
/**
* default intervall between keepAlive calls in seconds. It is only used if
* the property boot.session.keepalive_interval cannot be read from
* at.spardat.xma.boot.bootcfg.properties or is not a number.
*/
public final static int defaultKeepAliveInterval = 3300;
/**
* allready logged in on the server
*/
private boolean serverLoggedIn = false;
/**
* need to encrypt the communication for preLoginInfo, login, contextchange,
* logout
*/
private boolean needEncryption = false;
/**
* client side properties vom XProperties-system.
*/
private Properties runtimeProperties;
/**
* contains all external-event-listeners for this Session
*/
private List externalEventlisteners;
/**
* The thread listening for external events via Pipes
*/
private PipeListenerThread pipeListenerThread;
/**
* display needed for showException() and syncExec().
*/
Display display;
/**
* if display was created newly it has to be disposed on logout().
*/
private boolean doDisposeDisplay;
/**
* stores the GlobalEventListeners
*/
private List globalEventListeners;
/**
* Constructor.
*/
public XMASessionClient(XMA_URI uri, AppContainer appcIn) {
appContainer_ = appcIn;
baseUri = uri;
log = Logger.getLogger("Session: " + uri.toString());
}
/**
* Does a client and server side login with the configured authentication plugin.
* @return true if the login succeeded, false otherwise
* @throws SysException if the authentication plugin does not provide
* exactly one {@link XMAContext}, or some Exception occured in the
* authentication plugin.
*/
public boolean login() {
return login(new Properties());
}
/**
* Does a client and server side login with the configured authentication plugin.
* @param props input data for the login module; will be propagated as options to initialize.
* @return true if the login succeeded, false otherwise
* @throws SysException if the authentication plugin does not provide
* exactly one {@link XMAContext}, or some Exception occured in the
* authentication plugin.
*/
public boolean login(Properties props) {
boolean success = false;
try {
createDisplay();
serverLoggedIn=false;
loginContext = new XMALoginContext(new XMACallbackHandler(this), pluginManager_,props);
loginContext.login();
Set principals = loginContext.getSubject().getPrincipals(XMAContext.class);
if (principals.size() != 1) {
throw new RuntimeException("ambigous user: "
+ loginContext.getSubject().toString());
}
if (serverLoggedIn) {
success = true;
} else {
success = loginServer(loginContext.getSubject());
if (!success) {
showException(new Notification(Codes
.getText(Codes.LOGIN_DENIED_SERVER))
.setCode(Codes.LOGIN_DENIED_SERVER));
loginContext.logout();
}
}
} catch (LoginException lexc) {
showException(new Notification(Codes.getText(Codes.LOGIN_DENIED))
.setCode(Codes.LOGIN_DENIED));
return false;
} catch (Exception exc) {
showException(new SysException(exc, Codes
.getText(Codes.LOGIN_TECHNICAL_ERROR)).setCode(
Codes.LOGIN_TECHNICAL_ERROR).setShowToEndUser(true));
if (loginContext != null) {
try {
loginContext.logout();
} catch (Exception e) {
log.log(LogLevel.WARNING, "exception:", e);
}
}
return false;
}
//create Pipe and start listener
if(success){
try {
startPipeListener(props);
} catch (IOException e) {
showException(new SysException(e, Codes
.getText(Codes.WINREUSE_STARTUP)).setCode(
Codes.WINREUSE_STARTUP).setShowToEndUser(true));
logout();
return false;
}
}
return success;
}
/**
* Creates the Display (getCurrent() / getDefault()).
*
* @since version_number
* @author s3460
*/
private void createDisplay() {
display = Display.getCurrent();
if (display == null) {
display = Display.getDefault();
doDisposeDisplay = true;
} else {
doDisposeDisplay = false;
}
}
/**
* Creates und starts the PipeListenerThread daemon.
*
* @since version_number
* @author s3460
*/
private void startPipeListener(Properties prop) throws IOException {
String pipeName = getPipeName(prop);
if (pipeName != null) {
pipeListenerThread = new PipeListenerThread(this, createPipe(pipeName));
pipeListenerThread.start();
}
}
/**
* creates a Pipe
* @param pipeName
* @return
* @throws IOException
* @since version_number
* @author s3460
*/
private XMAPipe createPipe(String pipeName) throws IOException{
XMAPipe pipe = null;
for (int i = 0; i < 2; i++) {
try {
pipe = XMAPipe.getInstance(pipeName);
break;
} catch (IOException e) {
log.log(LogLevel.WARNING, "can't create XMAPipe " + i + ". Try :", e);
if (i == 1) {
log.log(LogLevel.SEVERE, "No pipe can be created -> throw IOException",e);
throw e;
}
}
//sleep for 2. try
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
return pipe;
}
/**
* The pipename can be set by the XMABootruntime caller.
* TODO: also set or enable by XProperties
* @return
* @since version_number
* @author s3460
*/
private String getPipeName(Properties prop){
return prop.getProperty(PIPE_NAME);
}
/**
* Shows an Exception in a MessageBox.
*
* @param exc
* the catched Exception
*/
private void showException(Object exc) {
Shell shell = display.getActiveShell();
if (shell == null)
shell = new Shell(display);
XMAContext context = null;
if (loginContext != null) {
Set principals = loginContext.getSubject().getPrincipals(XMAContext.class);
if (principals.size() > 0) {
context = (XMAContext) principals.iterator().next();
}
}
if (context == null) {
context = new XMAContext() {
public Locale getLocale() {
return Locale.getDefault();
}
public String getMandant() {
return "";
}
public String getEnvironment() {
return XMAContext.prod;
}
public boolean isLocal() {
return false;
}
public String getName() {
return "";
}
};
}
NotificationBox.show(exc, shell, context, this);
if (exc instanceof Throwable) {
log.log(LogLevel.WARNING, "exception:", (Throwable) exc);
} else {
log.log(LogLevel.WARNING, "notification: {0}", exc);
}
}
/**
* Returns the execution context of this session. All callers of this method
* may rely on the fact that the information stored in the
* XMAContext remain stable, i.e., won't change over the lifetime
* of this session. This pertains to the authenticated user, the mandant and
* the environment.
*
* @return context never null.
*/
public XMAContext getContext() {
Set principals = loginContext.getSubject().getPrincipals(XMAContext.class);
return (XMAContext) principals.iterator().next();
}
/**
* Returns the subject as supplied by the JAAS conforming login module.
*
* @return the subject provided by the login module.
*/
public Subject getSubject() {
return loginContext.getSubject();
}
/**
* Registers a Component with this Session. Must only be called
* from class ComponentClient.
*
* @param c
* the Component to register.
*/
public void registerComponent(ComponentClient c) {
components_.add(c);
c.setId(++lastComponentId_);
}
/**
* Deregisters a given Component. The same component must have
* been registered before. Must only be called from class
* ComponentClient.
*
* @param c
* the Component to deregister.
*/
public void removeComponent(ComponentClient c) {
if (!components_.remove(c))
throw new IllegalStateException();
if (!c.isStateless()) {
deadComponents_.add(new Short(c.getId()));
}
}
/**
* Returns a newly created array of ids of dead components.
*
* @return an array of component ids. The length of the array may be zero if
* there are no dead components.
*/
public short[] getIdsOfDeadComponents() {
short[] ids = new short[deadComponents_.size()];
for (int i = 0; i < ids.length; i++) {
ids[i] = ((Short) deadComponents_.get(i)).shortValue();
}
return ids;
}
/**
* Empties the list of dead component ids.
*/
public void resetDeadComponentList() {
deadComponents_.clear();
}
/**
* Returns an Iterator over the list of registered Components.
*/
public Iterator getComponents() {
return components_.iterator();
}
/**
* Gets the id of the session; with http-comunication this is the session
* cookie.
*
* @return the id of the session
*/
public String getId() {
return id;
}
/**
* Sets the id of the session; with http-comunication this is the session
* cookie. This method must only be called by the runtime!
*
* @param string
* the new session id.
*/
public void setId(String string) {
id = string;
}
/**
* Gets the application-uri
*
* @return the uri of the corresponding server application
*/
public XMA_URI getUri() {
return new XMA_URI(baseUri);
}
/**
* Returns the PluginManager that must be used to retrieve client side
* plugin implementations.
*
* @return a PluginManagerClient that is never null.
*/
public PluginManager getPluginManager() {
return pluginManager_;
}
/**
* Does a client and server side logout with the configured authentication
* plugin. This method must only be called by the runtime!
*/
public void logout() {
try {
loginContext.logout();
} catch (LoginException exc) {
log.log(LogLevel.WARNING, "exception:", exc);
}
if (serverLoggedIn) {
logoutServer();
}
if (pipeListenerThread != null)
pipeListenerThread.stopThread();
if (doDisposeDisplay && display != null)
display.dispose();
}
/**
* Does a server side login. This creates an authenticated Session on the
* server on success. This method must only be called by the login module or
* the runtime!
*
* @return true if the login succeeds
* false otherwise
*/
public boolean loginServer(Subject subject) {
if (runtimeProperties == null) {
serverGetPreLoginInfo();
}
BaseRPCClient rpc = new BaseRPCClient("login", "session", this);
rpc.setNeedEncryption(needEncryption);
rpc.setUnserializableCollection(0, subject.getPrincipals());
rpc.setUnserializableCollection(1, subject.getPublicCredentials());
rpc.execute();
boolean loginOk = ((Boolean) rpc.getParameter(0)).booleanValue();
subject.getPrincipals().clear();
subject.getPrincipals().addAll(rpc.getUnserializableCollection(1));
subject.getPublicCredentials().clear();
subject.getPublicCredentials().addAll(rpc.getUnserializableCollection(2));
if (loginOk) {
startKeepAlive();
serverLoggedIn = true;
return true;
} else {
return false;
}
}
/**
* Gets the pre login information from the server. This method must only be
* called by the login module or the runtime!
*
* @return the information send by the server
*/
public Object serverGetPreLoginInfo() {
runtimeProperties = new Properties();
BaseRPCClient rpc = new BaseRPCClient("getPreLoginInfo", "session", this);
// rpc.setNeedEncryption(needEncryption);
String version;
try {
Class cl = Class.forName("at.spardat.xma.boot.util.Version");
Object obj = cl.newInstance();
version = (String) cl.getMethod("getVersion",null).invoke(obj,null);
} catch (Exception e) {
version = "<1.4.0";
log.log(LogLevel.INFO,"at.spardat.xma.boot.util.Version is not available -> Bootrt-Version: <1.4.0");
}
rpc.setParameter(0,version);
try {
rpc.setParameter(1,InetAddress.getLocalHost().getHostAddress());
} catch (UnknownHostException e) {
log.log(LogLevel.WARNING,"The clients IP adress can not be resolved and is not transmitted to the server",e);
}
rpc.execute();
boolean loginOk = ((Boolean) rpc.getParameter(0)).booleanValue();
Object result = null;
if (loginOk) {
result = rpc.getParameter(1);
}
// handle properties for client side
String props = (String) rpc.getParameter(2);
for (StringTokenizer tok = new StringTokenizer(props, "\n"); tok.hasMoreTokens();) {
String key = tok.nextToken();
String value = tok.nextToken();
runtimeProperties.setProperty(key, value);
}
return result;
}
/**
* Starts the keepAliveTimer. keepAlive() will be called periodically.
* The intervall is defined in the property xma.runtime.keepalive_interval.
* If this property is not set, the bootruntime property boot.session.keepalive_interval is used.
* If it cannot be read or is not a number, defaultKeepAliveInterval (55 min) is used instead.
*
* Keepalive can be disabled completeley by setting the property
* xma.runtime.doKeepAlive=false.
*/
private void startKeepAlive() {
if("false".equalsIgnoreCase(getRuntimeProperty("doKeepAlive","true"))) return;
keepAliveTimer = new Timer(true);
long timeout;
try {
String number = getRuntimeProperty("keepAliveInterval");
if(number==null) {
Properties props = BootRuntime.getInstance().getConfigProperties();
number = props.getProperty("boot.session.keepalive_interval");
}
timeout = Integer.parseInt(number) * 1000;
if (timeout <= 0)
timeout = defaultKeepAliveInterval * 1000;
} catch (Exception e) {
timeout = defaultKeepAliveInterval * 1000;
}
keepAliveTimer.schedule(new TimerTask() {
public void run() {
keepAlive();
}
}, timeout, timeout);
}
/**
* Does an empty server request to prevent inactivity timeout.
*
* @return true on success
* false in case of communication problems
*/
public boolean keepAlive() {
try {
new BaseRPCClient("keepAlive", "session", this).execute();
return true;
} catch (Exception e) {
log.log(LogLevel.WARNING, "exception:", e);
return false;
}
}
/**
* Stops the keepAliveTimer. No more periodically keepAlives will be send.
*/
private void stopKeepAlive() {
if(keepAliveTimer!=null) keepAliveTimer.cancel();
}
// /**
// * Does a server side logout. This destroyes the server session.
// * This method must only be called by the runtime!
// * @return true on success
// * false in case of communication problems
// */
// private boolean logoutServer() {
// serverLoggedIn=false;
// stopKeepAlive();
// XMA_URI uri = new XMA_URI(baseUri);
// uri.setResource("session");
// uri.addParameter("operation","logout");
// if(needEncryption&&!"https".equals(uri.getProtocol_())) {
// String port = runtimeProperties.getProperty("SSLPort","443");
// uri.setProtocol("https");
// uri.setPort(new Integer(port).intValue());
// }
// try{
// Transport.getTransport().callServerEvent(this,uri,new byte[0]);
// return true;
// } catch (CommunicationException e) {
// log.log(LogLevel.WARNING, "exception:", e);
// return false;
// }
// }
/**
* Does a server side logout. This destroyes the server session. This method
* must only be called by the runtime!
*
* @return true on success
* false in case of communication problems
*/
private boolean logoutServer() {
serverLoggedIn = false;
stopKeepAlive();
try {
BaseRPCClient rpc = new BaseRPCClient("logout", "session", this);
rpc.setNeedEncryption(needEncryption);
rpc.execute();
return true;
} catch (Exception e) {
log.log(LogLevel.WARNING, "exception:", e);
return false;
}
}
/**
* Does a server side context change. This changes the subject in the server
* side session on success. This method must only be called by the login
* module or the runtime!
*
* @return true if the login succeeds
* false otherwise
*/
public boolean contextChangeServer(Subject subject) {
BaseRPCClient rpc = new BaseRPCClient("contextChanged", "session", this);
rpc.setNeedEncryption(needEncryption);
rpc.setUnserializableCollection(0, subject.getPrincipals());
rpc.setUnserializableCollection(1, subject.getPublicCredentials());
rpc.execute();
boolean loginOk = ((Boolean) rpc.getParameter(0)).booleanValue();
subject.getPrincipals().clear();
subject.getPrincipals().addAll(rpc.getUnserializableCollection(1));
subject.getPublicCredentials().clear();
subject.getPublicCredentials().addAll(rpc.getUnserializableCollection(2));
if (loginOk) {
return true;
} else {
return false;
}
}
/**
* Get the application container used by the boot runtime to manage the
* component files of this application.
*
* @return the application container of this session.
*/
public AppContainer getAppContainer() {
return appContainer_;
}
/**
* Creates a Component of the same application. The implementation of the
* component is located and downloaded if necessary.
*
* @param componentName
* the relative uri of the desired component. relative uris are
* relative to the uri of this session (see {@link #getUri}).
* @return the initialized Component
*/
public IComponentClient getComponent(String componentName) {
try {
XMA_URI application = new XMA_URI(this.getUri());
application.setComponent(componentName);
String url = application.getHTTP_URI().toString();
return (IComponentClient) appContainer_.getAppManager().getComponent(url);
} catch (Exception e) {
throw new SysException(e, Codes.getText(Codes.CANNOT_CONSTRUCT_COMPONENT))
.setCode(Codes.CANNOT_CONSTRUCT_COMPONENT).setShowToEndUser(true);
}
}
/**
* Creates a Component from an other application. The implementation of the
* component is located and downloaded if necessary.
*
* @param componentName
* the absolute uri of the desired component in another
* webapplication.
* @return the initialized Component
*/
public IComponentClient getComponentExtern(String componentName) {
try {
Object comp = appContainer_.getAppManager().getComponent(componentName);
return (IComponentClient) ProxyHandler.bridgeClassLoaders(this.getClass()
.getClassLoader(), comp);
} catch (Exception e) {
throw new SysException(e, Codes.getText(Codes.CANNOT_CONSTRUCT_COMPONENT))
.setCode(Codes.CANNOT_CONSTRUCT_COMPONENT).setShowToEndUser(true);
}
}
/**
* Launch method for modal Components of the same application.
*
* @param component
* relative name of the component within the application
* @param input
* input properties
* @return Properties
*/
public Properties launchRelative(String component, Properties input, Composite parent) {
IComponent cmp = null;
try {
cmp = getComponent(component);
cmp.setProperties(input);
cmp.invoke(parent);
Properties out = cmp.getProperties();
return out;
} finally {
if (cmp != null)
cmp.dispose();
}
}
/**
* Launch method for modal Components of other applications.
*
* @param component
* abslute uri of the component
* @param input
* input properties
* @return Properties
*/
public Properties launchExtern(String component, Properties input, Composite parent) {
IComponent cmp = null;
try {
cmp = getComponentExtern(component);
cmp.setProperties(input);
cmp.invoke(parent);
Properties out = cmp.getProperties();
return out;
} finally {
if (cmp != null)
cmp.dispose();
}
}
/**
* Get the client side logger
*
* @return the client side logger
*/
public Logger getLogger() {
return log;
}
/**
* Application Hash-Code built from application descriptors.
*
* @return Application Version Hash-Code
*/
public byte[] getApplicationVersion() {
return getAppContainer().getDigest();
}
/**
* Get if this session uses SSL-Encryption for session management calls to
* the server. (login, logoff, prelogininfo, contextchange)
*
* @return if SSL-Encryption will be used
* @since 1.4.0
*/
public boolean isNeedEncryption() {
return needEncryption;
}
/**
* Sets if SSL-Encryption is neccessary for session management calls to the
* server. (login, logoff, prelogininfo, contextchange)
*
* @param enc
* true means use SSL-Encryption
* @since 1.4.0
*/
public void setNeedEncryption(boolean enc) {
if (enc) {
try {
baseUri.getClass().getMethod("setProtocol", new Class[] { String.class });
} catch (Exception e) {
throw new IllegalStateException("encryption not supported");
}
}
needEncryption = enc;
}
/**
* Returns the property with the specified key in the runtime properties.
* The method returns null
if the property is not found.
*
* @param key
* the hashtable key.
* @return the value for the specified key.
*/
public String getRuntimeProperty(String key) {
return runtimeProperties!=null?runtimeProperties.getProperty(key):null;
}
/**
* Returns the property with the specified key in the runtime properties.
* The method returns the default value argument if the property is not
* found.
*
* @param key
* the hashtable key.
* @param defaultValue
* a default value.
* @return the value for the specified key.
*/
public String getRuntimeProperty(String key, String defaultValue) {
return runtimeProperties!=null?runtimeProperties.getProperty(key, defaultValue):defaultValue;
}
public byte[] inverseTransform(String transform, byte[] data) {
return Transform.decode(transform, data);
}
/**
* Adds an ExternalEventListener to the listeners of the session.
*
* @param listener
* @since version_number
* @author s3460
*/
public void addExternalEventListener(ExternalEventListener listener) {
if (externalEventlisteners == null)
externalEventlisteners = new ArrayList(1);
if (!externalEventlisteners.contains(listener))
externalEventlisteners.add(listener);
}
/**
* Removes an ExternalEventListener to the listeners of the session.
*
* @param listener
* @since version_number
* @author s3460
*/
public void removeExternalEventListener(ExternalEventListener listener) {
if (externalEventlisteners != null) {
externalEventlisteners.remove(listener);
if (externalEventlisteners.size() == 0)
externalEventlisteners = null;
}
}
/**
* notifies all listeners of the ExternalEvent.
*
* @param event
* @return null if there are not return values
* @since version_number
* @author s3460
*/
public Properties notifyExternalEvent(ExternalEvent event) {
Properties allProps = null;
if (externalEventlisteners != null) {
for (Iterator it = externalEventlisteners.iterator(); it.hasNext();) {
ExternalEventListener listener = (ExternalEventListener) it.next();
try {
Properties prop = listener.externalEvent(event);
if (prop != null) {
if (allProps == null) {
allProps = new Properties();
}
allProps.putAll(prop);
}
} catch (Exception e) {
showException(e);
}
}
}
return allProps;
}
/**
* @see at.spardat.xma.session.XMASession#isAtServer()
*/
public boolean isAtServer() {
return false;
}
/**
* The added GlobalEventListener will be notifyed by server events.
* (by pollServerSideEvents()).
*/
public void addGlobalEventListener(GlobalEventListener listener) {
if (globalEventListeners == null){
globalEventListeners = new ArrayList(1);
}
if (!globalEventListeners.contains(listener)) {
globalEventListeners.add(listener);
}
}
/**
* removes the GlobalEventListener.
*/
public boolean removeGlobalEventListener(GlobalEventListener listener) {
boolean removed = false;
if (globalEventListeners != null) {
removed = globalEventListeners.remove(listener);
if (globalEventListeners.size() == 0)
globalEventListeners = null;
}
return removed;
}
/**
* iterates over the registered GlobalEventsListers and calls globalEvent().
* @param event
* @since version_number
* @author s3460
*/
private void iterateGlobalEventListener(GlobalEvent event){
if (globalEventListeners != null) {
for (Iterator iter = globalEventListeners.iterator(); iter.hasNext();) {
GlobalEventListener element = (GlobalEventListener) iter.next();
try {
element.globalEvent(event);
} catch (Exception e) {
getLogger().log(LogLevel.SEVERE,"Exception in GlobalEventListener " + element.toString(),e);
showException(e);
}
}
}
}
/**
* Calls globalEvent() at the registered listeners with the
* GlobalEvents from the paramter globalEvents.
* The listeners are called by display.asyncExec().
*
* @param globalEvents Collection with GlobalEvents.
* @since version_number
* @author s3460
*/
public void callGlobalEventListener(Collection globalEvents){
//inner class - to execute in display.asyncExec()
class GlobalEventListenerRunner implements Runnable {
Collection events;
GlobalEventListenerRunner(Collection events){
this.events = events;
}
public void run() {
if(serverLoggedIn){//execute events only if still logged in
for (Iterator iter = events.iterator(); iter.hasNext();) {
GlobalEvent element = (GlobalEvent) iter.next();
iterateGlobalEventListener(element);
}
}
}
}
//execution of inner class
GlobalEventListenerRunner runner = new GlobalEventListenerRunner(globalEvents);
display.asyncExec(runner);
}
}