/*******************************************************************************
* Copyright (c) 2009, 2010 Progress Software Corporation.
* 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
******************************************************************************/
package org.fusesource.tools.messaging;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.IServerLifecycleListener;
import org.eclipse.wst.server.core.internal.DeletedModule;
import org.fusesource.tools.messaging.cnf.model.DataModelManager;
import org.fusesource.tools.messaging.cnf.model.IModelConstants;
import org.fusesource.tools.messaging.cnf.model.Listeners;
import org.fusesource.tools.messaging.cnf.model.Senders;
import org.fusesource.tools.messaging.core.IConnection;
import org.fusesource.tools.messaging.core.IListener;
import org.fusesource.tools.messaging.core.IProvider;
import org.fusesource.tools.messaging.core.ISender;
import org.fusesource.tools.messaging.server.MessagingServersUtil;
/**
* Handles the state updates for Messaging Projects. Clients can listen to the project state changes
* by adding a listener
*/
@SuppressWarnings("restriction")
public class MsgProjectStateManager {
public static MsgProjectStateManager stateManager;
private final ServersChangeListener serversChangeListener;
private final List<ProjectStateListener> prjStateListeners = new ArrayList<ProjectStateListener>();;
private MsgProjectStateManager() {
serversChangeListener = new ServersChangeListener();
}
public static MsgProjectStateManager getInstance() {
if (stateManager == null) {
stateManager = new MsgProjectStateManager();
}
return stateManager;
}
// Listens to server add/change/remove actions
// For now, handling remove action - Closes the connection, forces the deployed
// projects to be offline when the server is removed
class ServersChangeListener implements IServerLifecycleListener {
public void serverAdded(IServer server) {
}
public void serverChanged(IServer server) {
}
public void serverRemoved(IServer server) {
if (!MessagingServersUtil.isMsgServer(server)) {
return;
}
IProvider provider = MessagingServersUtil.getProvider(server);
if (provider != null) {
try {
provider.getConnection().closeConnection();
} catch (MessagingException e) {
e.printStackTrace();
}
}
// Forcing the projects to be in offline state as we know no
// connection is available for the project(s) and fire project
// state change event
makeMsgProjectsOffline(server.getModules());
fireProjectStateChanges(server.getModules(), false);
}
}
public ServersChangeListener getServersChangeListener() {
return serversChangeListener;
}
/**
* Given IServer - retrieves the Messaging Modules and forces the projects to be online or
* offline based on the server's connection status
*
* @param server
*/
public void updateMsgProjectsState(IServer server, IModule[] msgModules) {
boolean isOnline = MessagingServersUtil.isMsgServerOnline(server);
updateMsgProjectsState(server, msgModules, isOnline);
}
public void updateMsgProjectsState(IServer server, IModule[] msgModules, boolean isOnline) {
if (!canProceed(msgModules)) {
return;
}
if (isOnline) {
makeMsgProjectsOnline(server, msgModules);
} else {
makeMsgProjectsOffline(msgModules);
}
// Notify Listeners about the Project state change
fireProjectStateChanges(msgModules, isOnline);
}
private void makeMsgProjectsOnline(IServer server, IModule[] modules) {
if (!canProceed(modules)) {
return;
}
IConnection activeConnection = null;
try {
activeConnection = getActiveConnection(server);
} catch (Exception e) {
MessageDialog
.openError(Display.getDefault().getActiveShell(),
"Failed to activate the projects. You may not be able to send or receive messages.", e
.getMessage());
e.printStackTrace();
return;
}
if (activeConnection != null) {
makeListenersOnline(activeConnection, modules);
makeSendersOnline(activeConnection, modules);
}
}
private IConnection getActiveConnection(IServer server) throws Exception {
IProvider provider = MessagingServersUtil.getProvider(server);
if (provider == null) {
throw new MessagingException("Provider is not associated with the server " + server.getName() + ".");
}
IConnection connection = provider.getConnection();
if (connection == null) {
throw new MessagingException("Connection is not established with the server " + server.getName() + ".");
}
return connection;
}
private void makeListenersOnline(IConnection activeConnection, IModule[] modules) {
for (IModule module : modules) {
Object object = getDataModelObject(module, IModelConstants.LISTENERS_FILE_PATH);
if (object instanceof Listeners) {
Listeners listenersModel = (Listeners) object;
List<IListener> listenersList = listenersModel.getListeners();
for (IListener listener : listenersList) {
try {
listener.getDestination().setConnection(activeConnection);
if (listener.canReceive()) {
listener.start();
}
} catch (MessagingException e) {
e.printStackTrace();
// TODO Collect and show after operation
}
}
}
}
}
private void makeSendersOnline(IConnection activeConnection, IModule[] modules) {
for (IModule module : modules) {
Object object = getDataModelObject(module, IModelConstants.SENDERS_FILE_PATH);
if (object instanceof Senders) {
Senders sendersModel = (Senders) object;
List<ISender> sendersList = sendersModel.getSenders();
for (ISender sender : sendersList) {
try {
sender.getDestination().setConnection(activeConnection);
sender.start();
} catch (MessagingException e) {
e.printStackTrace();
// TODO Collect and show after operation
}
}
}
}
}
private void makeMsgProjectsOffline(IModule[] modules) {
if (!canProceed(modules)) {
return;
}
makeListenersOffline(modules);
makeSendersOffline(modules);
}
private void makeSendersOffline(IModule[] modules) {
for (IModule module : modules) {
Object object = getDataModelObject(module, IModelConstants.SENDERS_FILE_PATH);
if (object instanceof Senders) {
Senders sendersModel = (Senders) object;
List<ISender> sendersList = sendersModel.getSenders();
for (ISender sender : sendersList) {
try {
sender.stop();
} catch (MessagingException e) {
e.printStackTrace();
// TODO Collect and show after operation
}
}
}
}
}
private void makeListenersOffline(IModule[] modules) {
for (IModule module : modules) {
Object object = getDataModelObject(module, IModelConstants.LISTENERS_FILE_PATH);
if (object instanceof Listeners) {
Listeners listenersModel = (Listeners) object;
List<IListener> listenersList = listenersModel.getListeners();
for (IListener listener : listenersList) {
try {
listener.stop();
} catch (MessagingException e) {
e.printStackTrace();
// TODO Collect and show after operation
}
}
}
}
}
private boolean canProceed(IModule[] modules) {
if (modules == null || modules.length == 0) {
return false;
}
return true;
}
private Object getDataModelObject(IModule module, String filePath) {
if (module instanceof DeletedModule) {
return null;
}
IProject project = module.getProject();
IFile modelFile = project.getFile(filePath);
return DataModelManager.getInstance().getModel(modelFile);
}
public synchronized void addProjectStateListener(ProjectStateListener stateListener) {
if (stateListener == null) {
return;
}
prjStateListeners.add(stateListener);
}
public synchronized void removeProjectStateListener(ProjectStateListener stateListener) {
if (stateListener == null) {
return;
}
prjStateListeners.remove(stateListener);
}
private void fireProjectStateChanges(IModule[] msgModules, boolean isOnline) {
ProjectStateEvent event = createEvent(msgModules, isOnline);
List<ProjectStateListener> listeners = new ArrayList<ProjectStateListener>(prjStateListeners);
for (ProjectStateListener listener : listeners) {
listener.stateChanged(event);
}
}
private ProjectStateEvent createEvent(IModule[] msgModules, boolean isOnline) {
int state = getStateConstant(isOnline);
List<IProject> projectsList = new ArrayList<IProject>();
for (IModule module : msgModules) {
projectsList.add(module.getProject());
}
IProject[] projectsArray = projectsList.toArray(new IProject[] {});
return new ProjectStateEvent(projectsArray, state);
}
private int getStateConstant(boolean isOnline) {
if (isOnline) {
return ProjectStateEvent.PROJECT_STATE_ONLINE;
}
return ProjectStateEvent.PROJECT_STATE_OFFLINE;
}
}