001: /*
002: * This file is part of the WfMOpen project.
003: * Copyright (C) 2001-2006 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: ToolAgentTestBase.java,v 1.3 2007/05/03 21:58:25 mlipp Exp $
021: *
022: * $Log: ToolAgentTestBase.java,v $
023: * Revision 1.3 2007/05/03 21:58:25 mlipp
024: * Internal refactoring for making better use of local EJBs.
025: *
026: * Revision 1.2 2007/03/27 21:59:43 mlipp
027: * Fixed lots of checkstyle warnings.
028: *
029: * Revision 1.1 2007/03/22 15:49:12 schnelle
030: * Component renamed.
031: *
032: * Revision 1.1 2007/03/22 13:49:12 schnelle
033: * Initial release.
034: *
035: */
036:
037: package de.danet.an.workflow.tools.test;
038:
039: import java.io.File;
040: import java.io.IOException;
041: import java.net.URL;
042: import java.rmi.RemoteException;
043: import java.util.Collection;
044: import java.util.Date;
045: import java.util.List;
046: import java.util.Map;
047: import java.util.NoSuchElementException;
048:
049: import javax.security.auth.callback.Callback;
050: import javax.security.auth.callback.CallbackHandler;
051: import javax.security.auth.callback.NameCallback;
052: import javax.security.auth.callback.PasswordCallback;
053: import javax.security.auth.callback.TextOutputCallback;
054: import javax.security.auth.callback.UnsupportedCallbackException;
055: import javax.security.auth.login.LoginContext;
056: import javax.security.auth.login.LoginException;
057: import javax.xml.parsers.DocumentBuilder;
058: import javax.xml.parsers.DocumentBuilderFactory;
059: import javax.xml.parsers.ParserConfigurationException;
060: import javax.xml.transform.Transformer;
061: import javax.xml.transform.TransformerException;
062: import javax.xml.transform.TransformerFactory;
063: import javax.xml.transform.sax.SAXResult;
064: import javax.xml.transform.stream.StreamSource;
065:
066: import junit.framework.TestCase;
067:
068: import org.xml.sax.SAXException;
069:
070: import de.danet.an.workflow.api.Activity;
071: import de.danet.an.workflow.api.ActivityUniqueKey;
072: import de.danet.an.workflow.api.AlreadyAssignedException;
073: import de.danet.an.workflow.api.FormalParameter;
074: import de.danet.an.workflow.api.Activity.Info;
075: import de.danet.an.workflow.localapi.ActivityLocal;
076: import de.danet.an.workflow.omgcore.AlreadySuspendedException;
077: import de.danet.an.workflow.omgcore.CannotCompleteException;
078: import de.danet.an.workflow.omgcore.CannotResumeException;
079: import de.danet.an.workflow.omgcore.CannotStopException;
080: import de.danet.an.workflow.omgcore.CannotSuspendException;
081: import de.danet.an.workflow.omgcore.HistoryNotAvailableException;
082: import de.danet.an.workflow.omgcore.InvalidDataException;
083: import de.danet.an.workflow.omgcore.InvalidPerformerException;
084: import de.danet.an.workflow.omgcore.InvalidPriorityException;
085: import de.danet.an.workflow.omgcore.InvalidResourceException;
086: import de.danet.an.workflow.omgcore.InvalidStateException;
087: import de.danet.an.workflow.omgcore.NotAssignedException;
088: import de.danet.an.workflow.omgcore.NotRunningException;
089: import de.danet.an.workflow.omgcore.NotSuspendedException;
090: import de.danet.an.workflow.omgcore.ProcessData;
091: import de.danet.an.workflow.omgcore.ResultNotAvailableException;
092: import de.danet.an.workflow.omgcore.TransitionNotAllowedException;
093: import de.danet.an.workflow.omgcore.UpdateNotAllowedException;
094: import de.danet.an.workflow.omgcore.WfAssignment;
095: import de.danet.an.workflow.omgcore.WfAuditEvent;
096: import de.danet.an.workflow.omgcore.WfProcess;
097: import de.danet.an.workflow.omgcore.WfResource;
098: import de.danet.an.workflow.spis.aii.CannotExecuteException;
099: import de.danet.an.workflow.spis.aii.ResultProvider;
100: import de.danet.an.workflow.spis.aii.ToolAgent;
101: import de.danet.an.workflow.util.SAXEventBufferImpl;
102:
103: /**
104: * Basic unit test for {@link ToolAgent}s.
105: *
106: * @author Dirk Schnelle
107: */
108: public abstract class ToolAgentTestBase extends TestCase {
109: private static final org.apache.commons.logging.Log logger = org.apache.commons.logging.LogFactory
110: .getLog(ToolAgentTestBase.class);
111:
112: /** Expected parameter type string. */
113: public static final Object FP_TYPE_STRING = String.class;
114:
115: /** Expected parameter type boolean. */
116: public static final Object FP_TYPE_BOOL = Boolean.class;
117:
118: /** Expected parameter type long. */
119: public static final Object FP_TYPE_INT = Long.class;
120:
121: /** Expected parameter type date. */
122: public static final Object FP_TYPE_DATE = Date.class;
123:
124: /** Expected parameter schema type. */
125: public static final Object FP_TYPE_FLOAT = Double.class;
126:
127: /** Expected parameter type schema with a {@link SAXEventBuffer}. */
128: public static final Object FP_TYPE_SCHEMA_SAX = new SAXEventBufferImpl();
129:
130: /** Expected parameter type schema as a W3C DOM tree. */
131: public static final Object FP_TYPE_SCHEMA_W3C_DOM;
132:
133: /** Expected parameter type schema as a JDOM tree. */
134: public static final Object FP_TYPE_SCHEMA_JDOM = new org.jdom.Element(
135: "dummy");
136:
137: /** Expected parameter type schema. */
138: public static final Object FP_TYPE_SCHEMA = FP_TYPE_SCHEMA_SAX;
139:
140: static {
141: DocumentBuilderFactory factory = DocumentBuilderFactory
142: .newInstance();
143: Object document = null;
144: try {
145: DocumentBuilder builder = factory.newDocumentBuilder();
146: document = builder.newDocument();
147: } catch (ParserConfigurationException e) {
148: logger.fatal("unable to create DOM document");
149: }
150:
151: FP_TYPE_SCHEMA_W3C_DOM = document;
152: }
153:
154: /** The tool agent to test. */
155: private ToolAgent tool;
156:
157: /** The login context. */
158: private UnitTestLoginContext login;
159:
160: /** The tool result. */
161: private Object result;
162:
163: /**
164: * Constructs a test case without a name.
165: */
166: public ToolAgentTestBase() {
167: this (null);
168: }
169:
170: /**
171: * Constructs a test case with the specified name.
172: * @param name name of the test.
173: */
174: public ToolAgentTestBase(String name) {
175: super (name);
176: }
177:
178: /**
179: * Factory method to create the tool agent to test.
180: * @return the tool instance.
181: */
182: public abstract ToolAgent createToolAgent();
183:
184: /**
185: * {@inheritDoc}
186: */
187: protected void setUp() throws Exception {
188: super .setUp();
189: tool = createToolAgent();
190: }
191:
192: /**
193: * Retrieves a reference to the tool.
194: * @return the tool.
195: */
196: protected ToolAgent getTool() {
197: return tool;
198: }
199:
200: /**
201: * Login with with the default settings.
202: * @throws LoginException
203: * Unable to log in.
204: */
205: protected void login() throws LoginException {
206: if (login == null) {
207: login = new UnitTestLoginContext();
208: }
209:
210: login.login();
211: }
212:
213: /**
214: * Logout.
215: * @throws LoginException
216: * Error logging out.
217: */
218: protected void logout() throws LoginException {
219: if (login == null) {
220: return;
221: }
222:
223: login.logout();
224: }
225:
226: /**
227: * Convenient method to read an XML document.
228: * @param name filename of the document to load.
229: * @return Loaded document
230: * @throws IOException
231: * Error reading the document.
232: * @throws SAXException
233: * Error in the document.
234: */
235: protected SAXEventBufferImpl loadDocument(String name)
236: throws IOException, SAXException {
237: File file = new File(name);
238: URL url = file.toURL();
239: String systemID = url.toExternalForm();
240: StreamSource source = new StreamSource(systemID);
241:
242: SAXEventBufferImpl buffer = new SAXEventBufferImpl();
243: SAXResult result = new SAXResult(buffer);
244: try {
245: TransformerFactory factory = TransformerFactory
246: .newInstance();
247: Transformer transformer = factory.newTransformer();
248: transformer.transform(source, result);
249: } catch (TransformerException e) {
250: throw new SAXException(e.getMessage(), e);
251: }
252:
253: return buffer;
254: }
255:
256: /**
257: * Invoke the tool with the given script.
258: * @param formPars
259: * @param map
260: * @throws RemoteException
261: * @throws CannotExecuteException
262: */
263: protected void invokeTool(FormalParameter[] formPars, Map map)
264: throws RemoteException, CannotExecuteException {
265:
266: Activity activity = new TestActivity();
267:
268: tool.invoke(activity, formPars, map);
269: }
270:
271: /**
272: * Retrieves the result after a tool invocation.
273: * @return result.
274: * @exception NoSuchElementException
275: * Tool does not provide a result.
276: */
277: protected Object getToolResult() throws NoSuchElementException {
278: if (result != null) {
279: return result;
280: }
281:
282: if (tool instanceof ResultProvider) {
283: ResultProvider provider = (ResultProvider) tool;
284:
285: result = provider.result();
286:
287: return result;
288: }
289:
290: throw new NoSuchElementException(
291: "Tool does not provide a result");
292: }
293:
294: /**
295: * Shortcut to retrieve the tool result for the given formal parameter.
296: * @param fp the formal parameter
297: * @return result.
298: * @exception NoSuchElementException
299: * Tool does not provide a result.
300: */
301: protected Object getToolResult(FormalParameter fp)
302: throws NoSuchElementException {
303: Map result = (Map) getToolResult();
304: String id = fp.id();
305:
306: return result.get(id);
307: }
308:
309: /**
310: * Dummy activity for tests.
311: */
312: public class TestActivity implements Activity {
313:
314: public void abandon(String exceptionName)
315: throws RemoteException, TransitionNotAllowedException {
316: }
317:
318: public Info activityInfo() throws RemoteException {
319: return null;
320: }
321:
322: public String blockActivity() throws RemoteException {
323: return null;
324: }
325:
326: public void changeAssignment(WfResource oldResource,
327: WfResource newResource) throws RemoteException,
328: InvalidResourceException, AlreadyAssignedException,
329: NotAssignedException {
330: }
331:
332: public boolean choose() throws RemoteException,
333: TransitionNotAllowedException {
334: return false;
335: }
336:
337: public DeadlineInfo[] deadlines() throws RemoteException {
338: return null;
339: }
340:
341: public Implementation executor() throws RemoteException {
342: return null;
343: }
344:
345: public WfResource getResource(WfAssignment asnmnt)
346: throws RemoteException {
347: return null;
348: }
349:
350: public String[] handledExceptions() throws RemoteException {
351: return null;
352: }
353:
354: public Implementation[] implementation() throws RemoteException {
355: return null;
356: }
357:
358: public JoinAndSplitMode joinMode() throws RemoteException {
359: return null;
360: }
361:
362: public List nextActivities() throws RemoteException {
363: return null;
364: }
365:
366: public String performer() throws RemoteException {
367: return null;
368: }
369:
370: public void removeAssignment(WfResource resource)
371: throws RemoteException, InvalidResourceException,
372: NotAssignedException {
373: }
374:
375: public JoinAndSplitMode splitMode() throws RemoteException {
376: return null;
377: }
378:
379: public ActivityUniqueKey uniqueKey() throws RemoteException {
380: return null;
381: }
382:
383: public void changeState(State newState) throws RemoteException,
384: InvalidStateException, TransitionNotAllowedException {
385: }
386:
387: public boolean debugEnabled() throws RemoteException {
388: return false;
389: }
390:
391: public State typedState() throws RemoteException {
392: return null;
393: }
394:
395: public void abort() throws RemoteException,
396: CannotStopException, NotRunningException {
397: }
398:
399: public void changeState(String newState)
400: throws RemoteException, InvalidStateException,
401: TransitionNotAllowedException {
402: }
403:
404: public String description() throws RemoteException {
405: return null;
406: }
407:
408: public Collection history() throws RemoteException,
409: HistoryNotAvailableException {
410: return null;
411: }
412:
413: public State howClosed() throws RemoteException {
414: return null;
415: }
416:
417: public String key() throws RemoteException {
418: return null;
419: }
420:
421: public Date lastStateTime() throws RemoteException {
422: return null;
423: }
424:
425: public String name() throws RemoteException {
426: return null;
427: }
428:
429: public int priority() throws RemoteException {
430: return 0;
431: }
432:
433: public ProcessData processContext() throws RemoteException {
434: return null;
435: }
436:
437: public void resume() throws RemoteException,
438: CannotResumeException, NotRunningException,
439: NotSuspendedException {
440: }
441:
442: public void setDescription(String newValue)
443: throws RemoteException {
444: }
445:
446: public void setName(String newValue) throws RemoteException {
447: }
448:
449: public void setPriority(int newValue) throws RemoteException,
450: InvalidPriorityException, UpdateNotAllowedException {
451: }
452:
453: public void setProcessContext(ProcessData newValue)
454: throws RemoteException, InvalidDataException,
455: UpdateNotAllowedException {
456: }
457:
458: public String state() throws RemoteException {
459: return null;
460: }
461:
462: public void suspend() throws RemoteException,
463: CannotSuspendException, NotRunningException,
464: AlreadySuspendedException {
465: }
466:
467: public void terminate() throws RemoteException,
468: CannotStopException, NotRunningException {
469: }
470:
471: public Collection validStates() throws RemoteException {
472: return null;
473: }
474:
475: public State whileOpen() throws RemoteException {
476: return null;
477: }
478:
479: public State whyNotRunning() throws RemoteException {
480: return null;
481: }
482:
483: public State workflowState() throws RemoteException {
484: return null;
485: }
486:
487: public Collection assignments() throws RemoteException {
488: return null;
489: }
490:
491: public void complete() throws RemoteException,
492: CannotCompleteException {
493: }
494:
495: public boolean isMemberOfAssignments(WfAssignment member)
496: throws RemoteException {
497: return false;
498: }
499:
500: public ProcessData result() throws RemoteException,
501: ResultNotAvailableException {
502: return null;
503: }
504:
505: public void setResult(ProcessData result)
506: throws RemoteException, InvalidDataException {
507: }
508:
509: public boolean isMemberOfPerformers(WfProcess member)
510: throws RemoteException {
511: return false;
512: }
513:
514: public Collection performers() throws RemoteException {
515: return null;
516: }
517:
518: public void receiveEvent(WfAuditEvent e)
519: throws InvalidPerformerException, RemoteException {
520: }
521:
522: public de.danet.an.workflow.omgcore.WfProcess container()
523: throws RemoteException {
524: return null;
525: }
526: }
527:
528: /**
529: * Simple login context for unit tests.
530: */
531: public class UnitTestLoginContext extends LoginContext {
532:
533: public UnitTestLoginContext() throws LoginException {
534: super ("danetworkflow", new CBH("ML", "ML"));
535: }
536:
537: public UnitTestLoginContext(String name, String user,
538: String password) throws LoginException {
539: super (name, new CBH(user, password));
540: }
541: }
542:
543: private class CBH implements CallbackHandler {
544: private String user;
545: private String password;
546:
547: public CBH(String user, String password) {
548: this .user = user;
549: this .password = password;
550: }
551:
552: public void handle(Callback[] callbacks)
553: throws UnsupportedCallbackException, IOException {
554: for (int i = 0; i < callbacks.length; i++) {
555: if (callbacks[i] instanceof TextOutputCallback) {
556: // display the message according to the specified type
557: TextOutputCallback toc = (TextOutputCallback) callbacks[i];
558: switch (toc.getMessageType()) {
559: case TextOutputCallback.INFORMATION:
560: System.err.println(toc.getMessage());
561: break;
562: case TextOutputCallback.ERROR:
563: System.err
564: .println("ERROR: " + toc.getMessage());
565: break;
566: case TextOutputCallback.WARNING:
567: System.err.println("WARNING: "
568: + toc.getMessage());
569: break;
570: default:
571: throw new IOException(
572: "Unsupported message type: "
573: + toc.getMessageType());
574: }
575: } else if (callbacks[i] instanceof NameCallback) {
576: // prompt the user for a username
577: NameCallback nc = (NameCallback) callbacks[i];
578: nc.setName(user);
579: } else if (callbacks[i] instanceof PasswordCallback) {
580: // prompt the user for sensitive information
581: PasswordCallback pc = (PasswordCallback) callbacks[i];
582: pc.setPassword(password.toCharArray());
583: } else if (callbacks[i].getClass().getName().equals(
584: "weblogic.security.auth.callback.URLCallback")) {
585: } else {
586: throw new UnsupportedCallbackException(
587: callbacks[i], "Unrecognized Callback \""
588: + callbacks[i].getClass().getName()
589: + "\"");
590: }
591: }
592: }
593: }
594: }
|