/*
* This file is part of the WfMOpen project.
* Copyright (C) 2001-2006 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: ToolAgentTestBase.java 2368 2007-05-03 21:58:25Z mlipp $
*
* $Log$
* Revision 1.2 2007/03/27 21:59:43 mlipp
* Fixed lots of checkstyle warnings.
*
* Revision 1.1 2007/03/22 15:49:12 schnelle
* Component renamed.
*
* Revision 1.1 2007/03/22 13:49:12 schnelle
* Initial release.
*
*/
package de.danet.an.workflow.tools.test;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.TextOutputCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;
import junit.framework.TestCase;
import org.xml.sax.SAXException;
import de.danet.an.workflow.api.Activity;
import de.danet.an.workflow.api.ActivityUniqueKey;
import de.danet.an.workflow.api.AlreadyAssignedException;
import de.danet.an.workflow.api.FormalParameter;
import de.danet.an.workflow.api.Activity.Info;
import de.danet.an.workflow.localapi.ActivityLocal;
import de.danet.an.workflow.omgcore.AlreadySuspendedException;
import de.danet.an.workflow.omgcore.CannotCompleteException;
import de.danet.an.workflow.omgcore.CannotResumeException;
import de.danet.an.workflow.omgcore.CannotStopException;
import de.danet.an.workflow.omgcore.CannotSuspendException;
import de.danet.an.workflow.omgcore.HistoryNotAvailableException;
import de.danet.an.workflow.omgcore.InvalidDataException;
import de.danet.an.workflow.omgcore.InvalidPerformerException;
import de.danet.an.workflow.omgcore.InvalidPriorityException;
import de.danet.an.workflow.omgcore.InvalidResourceException;
import de.danet.an.workflow.omgcore.InvalidStateException;
import de.danet.an.workflow.omgcore.NotAssignedException;
import de.danet.an.workflow.omgcore.NotRunningException;
import de.danet.an.workflow.omgcore.NotSuspendedException;
import de.danet.an.workflow.omgcore.ProcessData;
import de.danet.an.workflow.omgcore.ResultNotAvailableException;
import de.danet.an.workflow.omgcore.TransitionNotAllowedException;
import de.danet.an.workflow.omgcore.UpdateNotAllowedException;
import de.danet.an.workflow.omgcore.WfAssignment;
import de.danet.an.workflow.omgcore.WfAuditEvent;
import de.danet.an.workflow.omgcore.WfProcess;
import de.danet.an.workflow.omgcore.WfResource;
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.SAXEventBufferImpl;
/**
* Basic unit test for {@link ToolAgent}s.
*
* @author Dirk Schnelle
*/
public abstract class ToolAgentTestBase extends TestCase {
private static final org.apache.commons.logging.Log logger
= org.apache.commons.logging.LogFactory.getLog(ToolAgentTestBase.class);
/** Expected parameter type string. */
public static final Object FP_TYPE_STRING = String.class;
/** Expected parameter type boolean. */
public static final Object FP_TYPE_BOOL = Boolean.class;
/** Expected parameter type long. */
public static final Object FP_TYPE_INT = Long.class;
/** Expected parameter type date. */
public static final Object FP_TYPE_DATE = Date.class;
/** Expected parameter schema type. */
public static final Object FP_TYPE_FLOAT = Double.class;
/** Expected parameter type schema with a {@link SAXEventBuffer}. */
public static final Object FP_TYPE_SCHEMA_SAX = new SAXEventBufferImpl();
/** Expected parameter type schema as a W3C DOM tree. */
public static final Object FP_TYPE_SCHEMA_W3C_DOM;
/** Expected parameter type schema as a JDOM tree. */
public static final Object FP_TYPE_SCHEMA_JDOM
= new org.jdom.Element("dummy");
/** Expected parameter type schema. */
public static final Object FP_TYPE_SCHEMA = FP_TYPE_SCHEMA_SAX;
static {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Object document = null;
try {
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.newDocument();
} catch (ParserConfigurationException e) {
logger.fatal("unable to create DOM document");
}
FP_TYPE_SCHEMA_W3C_DOM = document;
}
/** The tool agent to test. */
private ToolAgent tool;
/** The login context. */
private UnitTestLoginContext login;
/** The tool result. */
private Object result;
/**
* Constructs a test case without a name.
*/
public ToolAgentTestBase() {
this(null);
}
/**
* Constructs a test case with the specified name.
* @param name name of the test.
*/
public ToolAgentTestBase(String name) {
super(name);
}
/**
* Factory method to create the tool agent to test.
* @return the tool instance.
*/
public abstract ToolAgent createToolAgent();
/**
* {@inheritDoc}
*/
protected void setUp() throws Exception {
super.setUp();
tool = createToolAgent();
}
/**
* Retrieves a reference to the tool.
* @return the tool.
*/
protected ToolAgent getTool() {
return tool;
}
/**
* Login with with the default settings.
* @throws LoginException
* Unable to log in.
*/
protected void login() throws LoginException {
if (login == null) {
login = new UnitTestLoginContext();
}
login.login();
}
/**
* Logout.
* @throws LoginException
* Error logging out.
*/
protected void logout() throws LoginException {
if (login == null) {
return;
}
login.logout();
}
/**
* Convenient method to read an XML document.
* @param name filename of the document to load.
* @return Loaded document
* @throws IOException
* Error reading the document.
* @throws SAXException
* Error in the document.
*/
protected SAXEventBufferImpl loadDocument(String name)
throws IOException, SAXException {
File file = new File(name);
URL url = file.toURL();
String systemID = url.toExternalForm();
StreamSource source = new StreamSource(systemID);
SAXEventBufferImpl buffer = new SAXEventBufferImpl();
SAXResult result = new SAXResult(buffer);
try {
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.transform(source, result);
} catch (TransformerException e) {
throw new SAXException(e.getMessage(), e);
}
return buffer;
}
/**
* Invoke the tool with the given script.
* @param formPars
* @param map
* @throws RemoteException
* @throws CannotExecuteException
*/
protected void invokeTool(FormalParameter[] formPars, Map map)
throws RemoteException, CannotExecuteException {
Activity activity = new TestActivity();
tool.invoke(activity, formPars, map);
}
/**
* Retrieves the result after a tool invocation.
* @return result.
* @exception NoSuchElementException
* Tool does not provide a result.
*/
protected Object getToolResult() throws NoSuchElementException {
if (result != null) {
return result;
}
if (tool instanceof ResultProvider) {
ResultProvider provider = (ResultProvider) tool;
result = provider.result();
return result;
}
throw new NoSuchElementException("Tool does not provide a result");
}
/**
* Shortcut to retrieve the tool result for the given formal parameter.
* @param fp the formal parameter
* @return result.
* @exception NoSuchElementException
* Tool does not provide a result.
*/
protected Object getToolResult(FormalParameter fp)
throws NoSuchElementException {
Map result = (Map) getToolResult();
String id = fp.id();
return result.get(id);
}
/**
* Dummy activity for tests.
*/
public class TestActivity implements Activity {
public void abandon(String exceptionName) throws RemoteException,
TransitionNotAllowedException {
}
public Info activityInfo() throws RemoteException {
return null;
}
public String blockActivity() throws RemoteException {
return null;
}
public void changeAssignment(WfResource oldResource,
WfResource newResource) throws RemoteException,
InvalidResourceException, AlreadyAssignedException,
NotAssignedException {
}
public boolean choose() throws RemoteException,
TransitionNotAllowedException {
return false;
}
public DeadlineInfo[] deadlines() throws RemoteException {
return null;
}
public Implementation executor() throws RemoteException {
return null;
}
public WfResource getResource(WfAssignment asnmnt)
throws RemoteException {
return null;
}
public String[] handledExceptions() throws RemoteException {
return null;
}
public Implementation[] implementation() throws RemoteException {
return null;
}
public JoinAndSplitMode joinMode() throws RemoteException {
return null;
}
public List nextActivities() throws RemoteException {
return null;
}
public String performer() throws RemoteException {
return null;
}
public void removeAssignment(WfResource resource)
throws RemoteException, InvalidResourceException,
NotAssignedException {
}
public JoinAndSplitMode splitMode() throws RemoteException {
return null;
}
public ActivityUniqueKey uniqueKey() throws RemoteException {
return null;
}
public void changeState(State newState) throws RemoteException,
InvalidStateException, TransitionNotAllowedException {
}
public boolean debugEnabled() throws RemoteException {
return false;
}
public State typedState() throws RemoteException {
return null;
}
public void abort() throws RemoteException, CannotStopException,
NotRunningException {
}
public void changeState(String newState) throws RemoteException,
InvalidStateException, TransitionNotAllowedException {
}
public String description() throws RemoteException {
return null;
}
public Collection history() throws RemoteException,
HistoryNotAvailableException {
return null;
}
public State howClosed() throws RemoteException {
return null;
}
public String key() throws RemoteException {
return null;
}
public Date lastStateTime() throws RemoteException {
return null;
}
public String name() throws RemoteException {
return null;
}
public int priority() throws RemoteException {
return 0;
}
public ProcessData processContext() throws RemoteException {
return null;
}
public void resume() throws RemoteException, CannotResumeException,
NotRunningException, NotSuspendedException {
}
public void setDescription(String newValue) throws RemoteException {
}
public void setName(String newValue) throws RemoteException {
}
public void setPriority(int newValue) throws RemoteException,
InvalidPriorityException, UpdateNotAllowedException {
}
public void setProcessContext(ProcessData newValue)
throws RemoteException, InvalidDataException,
UpdateNotAllowedException {
}
public String state() throws RemoteException {
return null;
}
public void suspend() throws RemoteException, CannotSuspendException,
NotRunningException, AlreadySuspendedException {
}
public void terminate() throws RemoteException, CannotStopException,
NotRunningException {
}
public Collection validStates() throws RemoteException {
return null;
}
public State whileOpen() throws RemoteException {
return null;
}
public State whyNotRunning() throws RemoteException {
return null;
}
public State workflowState() throws RemoteException {
return null;
}
public Collection assignments() throws RemoteException {
return null;
}
public void complete() throws RemoteException, CannotCompleteException {
}
public boolean isMemberOfAssignments(WfAssignment member)
throws RemoteException {
return false;
}
public ProcessData result() throws RemoteException,
ResultNotAvailableException {
return null;
}
public void setResult(ProcessData result) throws RemoteException,
InvalidDataException {
}
public boolean isMemberOfPerformers(WfProcess member)
throws RemoteException {
return false;
}
public Collection performers() throws RemoteException {
return null;
}
public void receiveEvent(WfAuditEvent e)
throws InvalidPerformerException, RemoteException {
}
public de.danet.an.workflow.omgcore.WfProcess container()
throws RemoteException {
return null;
}
}
/**
* Simple login context for unit tests.
*/
public class UnitTestLoginContext extends LoginContext {
public UnitTestLoginContext () throws LoginException {
super ("danetworkflow", new CBH("ML", "ML"));
}
public UnitTestLoginContext (String name, String user, String password)
throws LoginException {
super (name, new CBH(user, password));
}
}
private class CBH implements CallbackHandler {
private String user;
private String password;
public CBH(String user, String password) {
this.user = user;
this.password = password;
}
public void handle (Callback[] callbacks)
throws UnsupportedCallbackException, IOException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof TextOutputCallback) {
// display the message according to the specified type
TextOutputCallback toc
= (TextOutputCallback)callbacks[i];
switch (toc.getMessageType()) {
case TextOutputCallback.INFORMATION:
System.err.println(toc.getMessage());
break;
case TextOutputCallback.ERROR:
System.err.println("ERROR: " + toc.getMessage());
break;
case TextOutputCallback.WARNING:
System.err.println("WARNING: " + toc.getMessage());
break;
default:
throw new IOException("Unsupported message type: "
+ toc.getMessageType());
}
} else if (callbacks[i] instanceof NameCallback) {
// prompt the user for a username
NameCallback nc = (NameCallback)callbacks[i];
nc.setName(user);
} else if (callbacks[i] instanceof PasswordCallback) {
// prompt the user for sensitive information
PasswordCallback pc = (PasswordCallback)callbacks[i];
pc.setPassword(password.toCharArray());
} else if (callbacks[i].getClass().getName().equals
("weblogic.security.auth.callback.URLCallback")) {
} else {
throw new UnsupportedCallbackException
(callbacks[i], "Unrecognized Callback \""
+ callbacks[i].getClass().getName() + "\"");
}
}
}
}
}