001: /**
002: * This file is part of the WfMOpen project.
003: * Copyright (C) 2001-2004 Danet GmbH (www.danet.de), BU BTS.
004: * All rights reserved.
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU General Public License as published by
008: * the Free Software Foundation; either version 2 of the License, or
009: * (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * $Id: MBeanInvoker.java,v 1.6 2007/03/22 13:51:09 schnelle Exp $
021: *
022: * $Log: MBeanInvoker.java,v $
023: * Revision 1.6 2007/03/22 13:51:09 schnelle
024: * Corrected error message for terminate.
025: *
026: * Revision 1.5 2007/02/09 20:45:33 mlipp
027: * Handling multiple MBean servers correctly.
028: *
029: * Revision 1.4 2006/11/21 12:33:08 drmlipp
030: * Fixed W3C DOM handling.
031: *
032: * Revision 1.3 2006/09/29 12:32:10 drmlipp
033: * Consistently using WfMOpen as projct name now.
034: *
035: * Revision 1.2 2005/11/30 22:30:08 mlipp
036: * Merged changes from 1.3.3p2.
037: *
038: * Revision 1.1.2.5 2005/11/30 22:14:37 drmlipp
039: * Updated argument handling.
040: *
041: * Revision 1.1.2.4 2005/11/28 08:20:19 drmlipp
042: * Better formal parameter checking.
043: *
044: * Revision 1.1.2.3 2005/11/26 21:59:56 drmlipp
045: * Fixed signature evaluation.
046: *
047: * Revision 1.1.2.2 2005/11/25 13:17:58 drmlipp
048: * Finished initial version.
049: *
050: * Revision 1.1.2.1 2005/11/24 22:42:09 drmlipp
051: * Started MBeanInvoker.
052: *
053: */package de.danet.an.workflow.tools;
054:
055: import java.rmi.RemoteException;
056: import java.util.HashMap;
057: import java.util.Iterator;
058: import java.util.List;
059: import java.util.Map;
060:
061: import javax.management.InstanceNotFoundException;
062: import javax.management.MBeanException;
063: import javax.management.MBeanServer;
064: import javax.management.MBeanServerFactory;
065: import javax.management.MalformedObjectNameException;
066: import javax.management.ObjectName;
067: import javax.management.ReflectionException;
068:
069: import de.danet.an.workflow.api.Activity;
070: import de.danet.an.workflow.api.FormalParameter;
071: import de.danet.an.workflow.api.SAXEventBuffer;
072: import de.danet.an.workflow.spis.aii.ApplicationNotStoppedException;
073: import de.danet.an.workflow.spis.aii.CannotExecuteException;
074: import de.danet.an.workflow.spis.aii.ResultProvider;
075: import de.danet.an.workflow.spis.aii.ToolAgent;
076: import de.danet.an.workflow.util.XPDLUtil;
077:
078: /**
079: * @author mnl
080: *
081: */
082: public class MBeanInvoker implements ToolAgent, ResultProvider {
083:
084: private static final org.apache.commons.logging.Log logger = org.apache.commons.logging.LogFactory
085: .getLog(MBeanInvoker.class);
086:
087: /** The result container. */
088: private ThreadLocal result = new ThreadLocal();
089:
090: private MBeanServer server = null;
091: private String objectName = null;
092: private String operation = null;
093:
094: /**
095: * Create a new instance of this tool agent.
096: */
097: public MBeanInvoker() {
098: }
099:
100: /**
101: * @return Returns the objectName.
102: */
103: public String getObjectName() {
104: return objectName;
105: }
106:
107: /**
108: * @param objectName The objectName to set.
109: */
110: public void setObjectName(String objectName) {
111: this .objectName = objectName;
112: }
113:
114: /**
115: * @return Returns the operation.
116: */
117: public String getOperation() {
118: return operation;
119: }
120:
121: /**
122: * @param operation The operation to set.
123: */
124: public void setOperation(String operation) {
125: this .operation = operation;
126: }
127:
128: /* Comment copied from interface. */
129: public void invoke(Activity activity, FormalParameter[] fps, Map map)
130: throws RemoteException, CannotExecuteException {
131: if (objectName == null) {
132: throw new CannotExecuteException("Must specify objectName");
133: }
134: ObjectName on = null;
135: try {
136: on = new ObjectName(objectName);
137: } catch (MalformedObjectNameException e) {
138: throw new CannotExecuteException(e.getMessage());
139: }
140: if (operation == null) {
141: throw new CannotExecuteException("Must specify operation");
142: }
143: if (server == null) {
144: List serverList = MBeanServerFactory.findMBeanServer(null);
145: for (Iterator i = serverList.iterator(); i.hasNext();) {
146: MBeanServer s = (MBeanServer) i.next();
147: if (s.isRegistered(on)) {
148: server = s;
149: break;
150: }
151: }
152: if (server == null) {
153: throw new CannotExecuteException(
154: "MBean with object name " + objectName
155: + " not registered with any server.");
156: }
157: }
158:
159: Object[] params = new Object[fps.length - 1];
160: String[] sig = new String[fps.length - 1];
161: boolean haveOut = fps.length > 0
162: && fps[0].mode() == FormalParameter.Mode.OUT;
163: for (int i = haveOut ? 1 : 0, pi = 0; i < fps.length; i++, pi++) {
164: if (i > 0 && fps[i].mode() == FormalParameter.Mode.OUT) {
165: throw new CannotExecuteException(
166: "Only first parameter may have mode OUT");
167: }
168: params[pi] = map.get(fps[i].id());
169: if (XPDLUtil.isXMLType(fps[i].type())) {
170: if (params[pi] instanceof SAXEventBuffer) {
171: sig[i - 1] = SAXEventBuffer.class.getName();
172: } else if (params[pi] instanceof org.w3c.dom.DocumentFragment) {
173: sig[i - 1] = org.w3c.dom.DocumentFragment.class
174: .getName();
175: } else if (params[pi] instanceof org.jdom.Element) {
176: sig[i - 1] = org.jdom.Element.class.getName();
177: } else {
178: String msg = "Got argument of XML type, but cannot"
179: + " recognize value's class: "
180: + params[pi].getClass();
181: logger.error(msg);
182: throw new CannotExecuteException(msg);
183: }
184: } else {
185: sig[i - 1] = ((Class) fps[i].type()).getName();
186: }
187: }
188: if (logger.isDebugEnabled()) {
189: StringBuffer args = new StringBuffer();
190: for (int i = 0; i < params.length; i++) {
191: if (i > 0) {
192: args.append(", ");
193: }
194: args.append(sig[i].toString());
195: args.append(" ");
196: args.append(params[i].toString());
197: }
198: logger.debug("Invoking " + operation + "("
199: + args.toString() + ")");
200: }
201: Object res = null;
202: try {
203: res = server.invoke(on, operation, params, sig);
204: } catch (ReflectionException e) {
205: throw new CannotExecuteException(
206: "No matching operation (or signature): "
207: + e.getMessage());
208: } catch (InstanceNotFoundException e) {
209: throw new CannotExecuteException(
210: "Cannot find MBean with object name " + objectName
211: + ": " + e.getMessage());
212: } catch (MBeanException e) {
213: throw new CannotExecuteException(
214: "Problem invoking operation: " + e.getMessage());
215: }
216: if (res instanceof Throwable) {
217: throw (CannotExecuteException) (new CannotExecuteException(
218: ((Throwable) res).getMessage())
219: .initCause((Throwable) res));
220: }
221: if (fps.length > 0 && fps[0].mode() != FormalParameter.Mode.IN) {
222: Map resMap = new HashMap();
223: resMap.put(fps[0].id(), res);
224: result.set(resMap);
225: } else {
226: result.set(null);
227: }
228: }
229:
230: /* Comment copied from interface. */
231: public Object result() {
232: Object res = result.get();
233: result.set(null);
234: return res;
235: }
236:
237: /* Comment copied from interface. */
238: public void terminate(Activity activity)
239: throws ApplicationNotStoppedException {
240: throw new ApplicationNotStoppedException(
241: "Terminate not implemented for MBeanInvoker.");
242: }
243:
244: }
|