/**
* This file is part of the WfMOpen project.
* Copyright (C) 2001-2004 Danet GmbH (www.danet.de), BU BTS.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: MBeanInvoker.java 2320 2007-03-22 13:51:09Z schnelle $
*
* $Log$
* Revision 1.5 2007/02/09 20:45:33 mlipp
* Handling multiple MBean servers correctly.
*
* Revision 1.4 2006/11/21 12:33:08 drmlipp
* Fixed W3C DOM handling.
*
* Revision 1.3 2006/09/29 12:32:10 drmlipp
* Consistently using WfMOpen as projct name now.
*
* Revision 1.2 2005/11/30 22:30:08 mlipp
* Merged changes from 1.3.3p2.
*
* Revision 1.1.2.5 2005/11/30 22:14:37 drmlipp
* Updated argument handling.
*
* Revision 1.1.2.4 2005/11/28 08:20:19 drmlipp
* Better formal parameter checking.
*
* Revision 1.1.2.3 2005/11/26 21:59:56 drmlipp
* Fixed signature evaluation.
*
* Revision 1.1.2.2 2005/11/25 13:17:58 drmlipp
* Finished initial version.
*
* Revision 1.1.2.1 2005/11/24 22:42:09 drmlipp
* Started MBeanInvoker.
*
*/
package de.danet.an.workflow.tools;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import de.danet.an.workflow.api.Activity;
import de.danet.an.workflow.api.FormalParameter;
import de.danet.an.workflow.api.SAXEventBuffer;
import de.danet.an.workflow.spis.aii.ApplicationNotStoppedException;
import de.danet.an.workflow.spis.aii.CannotExecuteException;
import de.danet.an.workflow.spis.aii.ResultProvider;
import de.danet.an.workflow.spis.aii.ToolAgent;
import de.danet.an.workflow.util.XPDLUtil;
/**
* @author mnl
*
*/
public class MBeanInvoker implements ToolAgent, ResultProvider {
private static final org.apache.commons.logging.Log logger
= org.apache.commons.logging.LogFactory.getLog(MBeanInvoker.class);
/** The result container. */
private ThreadLocal result = new ThreadLocal ();
private MBeanServer server = null;
private String objectName = null;
private String operation = null;
/**
* Create a new instance of this tool agent.
*/
public MBeanInvoker() {
}
/**
* @return Returns the objectName.
*/
public String getObjectName() {
return objectName;
}
/**
* @param objectName The objectName to set.
*/
public void setObjectName(String objectName) {
this.objectName = objectName;
}
/**
* @return Returns the operation.
*/
public String getOperation() {
return operation;
}
/**
* @param operation The operation to set.
*/
public void setOperation(String operation) {
this.operation = operation;
}
/* Comment copied from interface. */
public void invoke(Activity activity, FormalParameter[] fps, Map map)
throws RemoteException, CannotExecuteException {
if (objectName == null) {
throw new CannotExecuteException ("Must specify objectName");
}
ObjectName on = null;
try {
on = new ObjectName(objectName);
} catch (MalformedObjectNameException e) {
throw new CannotExecuteException (e.getMessage ());
}
if (operation == null) {
throw new CannotExecuteException ("Must specify operation");
}
if (server == null) {
List serverList = MBeanServerFactory.findMBeanServer(null);
for (Iterator i = serverList.iterator(); i.hasNext();) {
MBeanServer s = (MBeanServer)i.next();
if (s.isRegistered(on)) {
server = s;
break;
}
}
if (server == null) {
throw new CannotExecuteException
("MBean with object name " + objectName
+ " not registered with any server.");
}
}
Object[] params = new Object[fps.length - 1];
String[] sig = new String[fps.length - 1];
boolean haveOut = fps.length > 0
&& fps[0].mode() == FormalParameter.Mode.OUT;
for (int i = haveOut ? 1 : 0, pi = 0; i < fps.length; i++, pi++) {
if (i > 0 && fps[i].mode() == FormalParameter.Mode.OUT) {
throw new CannotExecuteException
("Only first parameter may have mode OUT");
}
params[pi] = map.get(fps[i].id());
if (XPDLUtil.isXMLType(fps[i].type())) {
if (params[pi] instanceof SAXEventBuffer) {
sig[i - 1] = SAXEventBuffer.class.getName();
} else if (params[pi] instanceof org.w3c.dom.DocumentFragment) {
sig[i - 1] = org.w3c.dom.DocumentFragment.class.getName();
} else if (params[pi] instanceof org.jdom.Element) {
sig[i - 1] = org.jdom.Element.class.getName();
} else {
String msg = "Got argument of XML type, but cannot"
+ " recognize value's class: " + params[pi].getClass();
logger.error(msg);
throw new CannotExecuteException (msg);
}
} else {
sig[i - 1] = ((Class)fps[i].type()).getName();
}
}
if (logger.isDebugEnabled()) {
StringBuffer args = new StringBuffer();
for (int i = 0; i < params.length; i++) {
if (i > 0) {
args.append(", ");
}
args.append(sig[i].toString());
args.append(" ");
args.append(params[i].toString());
}
logger.debug("Invoking " + operation + "(" + args.toString() + ")");
}
Object res = null;
try {
res = server.invoke(on, operation, params, sig);
} catch (ReflectionException e) {
throw new CannotExecuteException
("No matching operation (or signature): " + e.getMessage());
} catch (InstanceNotFoundException e) {
throw new CannotExecuteException
("Cannot find MBean with object name " + objectName
+ ": " + e.getMessage());
} catch (MBeanException e) {
throw new CannotExecuteException
("Problem invoking operation: " + e.getMessage());
}
if (res instanceof Throwable) {
throw (CannotExecuteException)
(new CannotExecuteException (((Throwable)res).getMessage())
.initCause((Throwable)res));
}
if (fps.length > 0 && fps[0].mode() != FormalParameter.Mode.IN) {
Map resMap = new HashMap ();
resMap.put(fps[0].id(), res);
result.set(resMap);
} else {
result.set (null);
}
}
/* Comment copied from interface. */
public Object result () {
Object res = result.get();
result.set (null);
return res;
}
/* Comment copied from interface. */
public void terminate(Activity activity)
throws ApplicationNotStoppedException {
throw new ApplicationNotStoppedException
("Terminate not implemented for MBeanInvoker.");
}
}