0001: /*
0002: * Copyright 2007 Outerthought bvba and Schaubroeck nv
0003: *
0004: * Licensed under the Apache License, Version 2.0 (the "License");
0005: * you may not use this file except in compliance with the License.
0006: * You may obtain a copy of the License at
0007: *
0008: * http://www.apache.org/licenses/LICENSE-2.0
0009: *
0010: * Unless required by applicable law or agreed to in writing, software
0011: * distributed under the License is distributed on an "AS IS" BASIS,
0012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013: * See the License for the specific language governing permissions and
0014: * limitations under the License.
0015: */
0016: package org.outerj.daisy.repository.test;
0017:
0018: import org.outerj.daisy.repository.testsupport.AbstractDaisyTestCase;
0019: import org.outerj.daisy.repository.*;
0020: import org.outerj.daisy.repository.query.SortOrder;
0021: import org.outerj.daisy.repository.acl.*;
0022: import org.outerj.daisy.repository.schema.DocumentType;
0023: import org.outerj.daisy.repository.user.Role;
0024: import org.outerj.daisy.repository.user.User;
0025: import org.outerj.daisy.workflow.*;
0026: import org.outerx.daisy.x10Workflow.SearchResultDocument;
0027: import org.apache.xmlbeans.XmlString;
0028:
0029: import java.io.*;
0030: import java.util.*;
0031: import java.util.zip.ZipOutputStream;
0032: import java.util.zip.ZipEntry;
0033:
0034: public abstract class AbstractWorkflowTest extends
0035: AbstractDaisyTestCase {
0036: protected boolean resetDataStores() {
0037: return true;
0038: }
0039:
0040: protected Set<String> getDisabledContainerIds() {
0041: return Collections.emptySet();
0042: }
0043:
0044: protected abstract RepositoryManager getRepositoryManager()
0045: throws Exception;
0046:
0047: public void testWorkflow() throws Exception {
0048: RepositoryManager repositoryManager = getRepositoryManager();
0049: Repository repository = repositoryManager
0050: .getRepository(new Credentials("testuser", "testuser"));
0051: repository.switchRole(Role.ADMINISTRATOR);
0052: Role userRole = repository.getUserManager().getRole("User",
0053: false);
0054:
0055: WorkflowManager workflowManager = (WorkflowManager) repository
0056: .getExtension("WorkflowManager");
0057: Locale locale = Locale.US;
0058:
0059: // Create a dummy user (a normal user)
0060: User dummyUser = repository.getUserManager()
0061: .createUser("dummy");
0062: dummyUser.setPassword("dummy");
0063: dummyUser.addToRole(repository.getUserManager().getRole("User",
0064: false));
0065: dummyUser.save();
0066: Repository dummyRepo = repositoryManager
0067: .getRepository(new Credentials("dummy", "dummy"));
0068: WorkflowManager dummyWfManager = (WorkflowManager) dummyRepo
0069: .getExtension("WorkflowManager");
0070:
0071: // Some basic deployment tests
0072: {
0073: String workflowWithoutStartState = "<process-definition name='boe'>"
0074: + " <state name='s'>"
0075: + " <transition to='end' />"
0076: + " </state>"
0077: + " <end-state name='end' />"
0078: + "</process-definition>";
0079:
0080: try {
0081: workflowManager.deployProcessDefinition(
0082: new ByteArrayInputStream(
0083: workflowWithoutStartState.getBytes()),
0084: "text/xml", locale);
0085: fail("Deploying a process definition without a start state should fail.");
0086: } catch (RepositoryException e) {
0087: // expected
0088: assertTrue(e.getMessage().indexOf("start state") != -1);
0089: }
0090:
0091: String validWorkflow = "<process-definition name='boe'>"
0092: + " <swimlane name='initiator'/>"
0093: + " <start-state name='start'>"
0094: + " <task name='start-task' swimlane='initiator'/>"
0095: + " <transition name='to-s' to='s' />"
0096: + " <transition name='to-x' to='x' />"
0097: + " </start-state>" + " <state name='s'>"
0098: + " <transition name='to-end' to='end' />"
0099: + " </state>" + " <end-state name='end' />"
0100: + "</process-definition>";
0101:
0102: WfProcessDefinition workflowDefinition = workflowManager
0103: .deployProcessDefinition(new ByteArrayInputStream(
0104: validWorkflow.getBytes()), "text/xml",
0105: locale);
0106: assertTrue(
0107: "Invalid transition should give a warning (among other things)",
0108: workflowDefinition.getProblems().size() > 1);
0109:
0110: // Non-admin user cannot deploy workflow definitions
0111: repository.switchRole(userRole.getId());
0112: try {
0113: workflowManager.deployProcessDefinition(
0114: new ByteArrayInputStream(validWorkflow
0115: .getBytes()), "text/xml", locale);
0116: fail("Non-admin user should not be able to deploy workflow definitions.");
0117: } catch (WfAuthorizationException e) {
0118: // expected
0119: }
0120: repository.switchRole(Role.ADMINISTRATOR);
0121:
0122: // Save it again to have a second version
0123: workflowManager.deployProcessDefinition(
0124: new ByteArrayInputStream(validWorkflow.getBytes()),
0125: "text/xml", locale);
0126:
0127: // Save another workflow (with a different name)
0128: String anotherWorkflow = "<process-definition name='boe2'>"
0129: + " <start-state name='start'>"
0130: + " <transition name='to-s' to='s' />"
0131: + " </start-state>" + " <state name='s'>"
0132: + " <transition name='to-end' to='end' />"
0133: + " </state>" + " <end-state name='end' />"
0134: + "</process-definition>";
0135: workflowManager
0136: .deployProcessDefinition(new ByteArrayInputStream(
0137: anotherWorkflow.getBytes()), "text/xml",
0138: locale);
0139:
0140: // Note: when new workflow samples are added to the default repo setup, the
0141: // below numbers need to be augmented for the test to succeed
0142: List<WfProcessDefinition> workflowDefinitions = workflowManager
0143: .getAllLatestProcessDefinitions(locale);
0144: assertEquals(5, workflowDefinitions.size());
0145:
0146: workflowDefinitions = workflowManager
0147: .getAllProcessDefinitions(locale);
0148: assertEquals(6, workflowDefinitions.size());
0149: }
0150:
0151: {
0152: // Test exceptions in case of trying to load workflow definitions which don't exist
0153: try {
0154: workflowManager.getProcessDefinition("555555", locale);
0155: fail("Expected a ProcessDefinitionNotFoundException");
0156: } catch (ProcessDefinitionNotFoundException e) {
0157: }
0158:
0159: try {
0160: workflowManager.getLatestProcessDefinition(
0161: "a name which doesn't exist", locale);
0162: fail("Expected a ProcessDefinitionNotFoundException");
0163: } catch (ProcessDefinitionNotFoundException e) {
0164: }
0165:
0166: try {
0167: workflowManager.startProcess("555555", null, null,
0168: locale);
0169: fail("Expected a ProcessDefinitionNotFoundException");
0170: } catch (ProcessDefinitionNotFoundException e) {
0171: }
0172:
0173: try {
0174: workflowManager.deleteProcessDefinition("555555");
0175: fail("Expected a ProcessDefinitionNotFoundException");
0176: } catch (ProcessDefinitionNotFoundException e) {
0177: }
0178:
0179: try {
0180: workflowManager.getProcess("555555", locale);
0181: fail("Expected a ProcessInstanceNotFoundException");
0182: } catch (ProcessInstanceNotFoundException e) {
0183: }
0184:
0185: try {
0186: workflowManager.signal("555555", "boe", "boe", locale);
0187: fail("Expected a ProcessInstanceNotFoundException");
0188: } catch (ProcessInstanceNotFoundException e) {
0189: }
0190: }
0191:
0192: {
0193: String validWorkflow = "<process-definition name='test1'>"
0194: + " <swimlane name='initiator'/>"
0195: + " <start-state name='start'>"
0196: + " <task name='start-task' swimlane='initiator'/>"
0197: + " <transition name='trans1' to='s'/>"
0198: + " </start-state>" + " <state name='s'>"
0199: + " <transition name='to-end' to='end'/>"
0200: + " </state>" + " <end-state name='end'/>"
0201: + "</process-definition>";
0202:
0203: WfProcessDefinition workflowDefinition = workflowManager
0204: .deployProcessDefinition(new ByteArrayInputStream(
0205: validWorkflow.getBytes()), "text/xml",
0206: locale);
0207: WfProcessInstance workflow = workflowManager.startProcess(
0208: workflowDefinition.getId(), null, "trans1", locale);
0209:
0210: assertNotNull(workflow.getId());
0211: assertNotNull(workflow.getStart());
0212: assertNull(workflow.getEnd());
0213:
0214: assertEquals("/", workflow.getRootExecutionPath().getPath());
0215: assertEquals("s", workflow.getRootExecutionPath().getNode()
0216: .getName());
0217:
0218: workflowManager.signal(workflow.getId(), workflow
0219: .getRootExecutionPath().getPath(), null, locale);
0220: workflow = workflowManager.getProcess(workflow.getId(),
0221: locale);
0222:
0223: assertNotNull(workflow.getEnd());
0224: assertEquals("end", workflow.getRootExecutionPath()
0225: .getNode().getName());
0226:
0227: // Delete the workflow definition, which will also delete the associated workflow instances
0228: workflowManager.deleteProcessDefinition(workflowDefinition
0229: .getId());
0230: }
0231:
0232: {
0233: // A workflow with a task
0234:
0235: String validWorkflow = "<process-definition name='test2'>"
0236: + " <swimlane name='initiator'/>"
0237: + " <start-state name='start'>"
0238: + " <transition name='trans1' to='s'/>"
0239: + " </start-state>" + " <task-node name='s'>"
0240: + " <task name='task1'>"
0241: + " <assignment actor-id='"
0242: + repository.getUserId() + "'/>" + " </task>"
0243: + " <transition name='trans2' to='end'/>"
0244: + " </task-node>" + " <end-state name='end'/>"
0245: + "</process-definition>";
0246:
0247: WfProcessDefinition workflowDefinition = workflowManager
0248: .deployProcessDefinition(new ByteArrayInputStream(
0249: validWorkflow.getBytes()), "text/xml",
0250: locale);
0251: WfProcessInstance workflow = workflowManager.startProcess(
0252: workflowDefinition.getId(), null, "trans1", locale);
0253: assertEquals(1, workflowManager.getMyTasks(locale).size());
0254:
0255: WfProcessInstance workflow2 = workflowManager.startProcess(
0256: workflowDefinition.getId(), null, "trans1", locale);
0257: assertEquals(2, workflowManager.getMyTasks(locale).size());
0258:
0259: List<WfTask> tasks = workflowManager.getMyTasks(locale);
0260: WfTask task1 = tasks.get(0);
0261: WfTask task2 = tasks.get(1);
0262:
0263: workflowManager.updateTask(task1.getId(), null, locale);
0264: assertEquals(2, workflowManager.getMyTasks(locale).size());
0265:
0266: workflowManager.endTask(task1.getId(), null, null, locale);
0267: assertEquals(1, workflowManager.getMyTasks(locale).size());
0268:
0269: workflowManager.endTask(task2.getId(), null, "trans2",
0270: locale);
0271: assertEquals(0, workflowManager.getMyTasks(locale).size());
0272: }
0273:
0274: Map<String, byte[]> resourceBundles = new HashMap<String, byte[]>();
0275: resourceBundles.put("i18n/messages.xml",
0276: readResourceBytes("messages.xml"));
0277: resourceBundles.put("i18n/messages_nl.xml",
0278: readResourceBytes("messages_nl.xml"));
0279:
0280: {
0281: String workflow = "<process-definition name='test3'>"
0282: + " <swimlane name='initiator'/>"
0283: + " <start-state name='start'>"
0284: + " <task name='start-task' swimlane='initiator'/>"
0285: + " <transition name='trans1' to='s'/>"
0286: + " </start-state>" + " <task-node name='s'>"
0287: + " <task name='test-task'>"
0288: + " <assignment actor-id='"
0289: + repository.getUserId() + "'/>" + " </task>"
0290: + " <transition name='trans2' to='end'/>"
0291: + " </task-node>" + " <end-state name='end'/>"
0292: + "</process-definition>";
0293:
0294: // invalid metadata according to schema
0295: String invalidWorkflowMeta = "<workflowMeta xmlns='http://outerx.org/daisy/1.0#workflow'><an-invalid-tag/></workflowMeta>";
0296:
0297: try {
0298: workflowManager.deployProcessDefinition(
0299: buildWorkflowArchive(workflow,
0300: invalidWorkflowMeta, resourceBundles),
0301: "application/zip", locale);
0302: fail("Expected a WorkflowException because the workflow metadata is invalid.");
0303: } catch (WorkflowException e) {
0304: }
0305:
0306: // invalid meta: XML well-formedness error
0307: String anotherInvalidWorkflowMeta = "<workflow-met";
0308: try {
0309: workflowManager.deployProcessDefinition(
0310: buildWorkflowArchive(workflow,
0311: anotherInvalidWorkflowMeta,
0312: resourceBundles), "application/zip",
0313: locale);
0314: fail("Expected a WorkflowException because the workflow metadata is not well formed XML.");
0315: } catch (WorkflowException e) {
0316: }
0317:
0318: String workflowMeta = "<workflowMeta xmlns='http://outerx.org/daisy/1.0#workflowmeta'>"
0319: + " <label>My workflow</label>"
0320: + " <description>A workflow for test purposes.</description>"
0321: + "</workflowMeta>";
0322: WfProcessDefinition wfDef = workflowManager
0323: .deployProcessDefinition(buildWorkflowArchive(
0324: workflow, workflowMeta, resourceBundles),
0325: "application/zip", locale);
0326:
0327: assertEquals("My workflow", wfDef.getLabel().getText());
0328: assertEquals("A workflow for test purposes.", wfDef
0329: .getDescription().getText());
0330:
0331: String workflowMeta2 = "<workflowMeta xmlns='http://outerx.org/daisy/1.0#workflowmeta'>"
0332: + " <label>My workflow</label>"
0333: + " <description>A workflow for test purposes.</description>"
0334: + " <nodes>"
0335: + " <node path='s'>"
0336: + " <transition name='trans2'>"
0337: + " <label>Finish!</label>"
0338: + " </transition>"
0339: + " </node>"
0340: + " </nodes>" + "</workflowMeta>";
0341: WfProcessDefinition wfDef2 = workflowManager
0342: .deployProcessDefinition(buildWorkflowArchive(
0343: workflow, workflowMeta2, resourceBundles),
0344: "application/zip", locale);
0345: assertEquals("Finish!", wfDef2.getTask("test-task")
0346: .getNode().getLeavingTransitions().get(0)
0347: .getLabel().getText());
0348:
0349: String workflowMeta3 = "<workflowMeta xmlns='http://outerx.org/daisy/1.0#workflowmeta'>"
0350: + " <label>My workflow</label>"
0351: + " <description>A workflow for test purposes.</description>"
0352: + " <tasks>"
0353: + " <task name='test-task'>"
0354: + " <label>My test task</label>"
0355: + " </task>" + " </tasks>" + "</workflowMeta>";
0356: WfProcessDefinition wfDef3 = workflowManager
0357: .deployProcessDefinition(buildWorkflowArchive(
0358: workflow, workflowMeta3, resourceBundles),
0359: "application/zip", locale);
0360: assertEquals("My test task", wfDef3.getTask("test-task")
0361: .getLabel().getText());
0362: }
0363:
0364: {
0365: String workflow = "<process-definition name='test3'>"
0366: + " <swimlane name='initiator'/>"
0367: + " <start-state name='start'>"
0368: + " <task name='start-task' swimlane='initiator'/>"
0369: + " <transition name='trans1' to='s'/>"
0370: + " </start-state>"
0371: + " <task-node name='s'>"
0372: + " <event type='node-enter'>"
0373: + " <script>"
0374: + " executionContext.getContextInstance().createVariable(\"var-readonly\", \"hello\", token);"
0375: + " </script>" + " </event>"
0376: + " <task name='test-task'>"
0377: + " <assignment actor-id='"
0378: + repository.getUserId() + "'/>" + " </task>"
0379: + " <transition name='trans2' to='s2'/>"
0380: + " </task-node>" + " <task-node name='s2'>"
0381: + " <task name='another-test-task'>"
0382: + " <assignment actor-id='"
0383: + repository.getUserId() + "'/>" + " </task>"
0384: + " <transition name='trans3' to='end'/>"
0385: + " </task-node>" + " <end-state name='end'/>"
0386: + "</process-definition>";
0387:
0388: String workflowMeta = "<workflowMeta xmlns='http://outerx.org/daisy/1.0#workflowmeta'>"
0389: + " <label>My workflow</label>"
0390: + " <description>A workflow for test purposes.</description>"
0391: + " <variables>"
0392: + " <variable name='var2' type='string' scope='global'/>"
0393: + " <variable name='var-link' type='daisy-link' scope='global'/>"
0394: + " <variable name='var-long' type='long' scope='global'/>"
0395: + " <variable name='var-date' type='date' scope='global'/>"
0396: + " <variable name='var-datetime' type='datetime' scope='global'/>"
0397: + " <variable name='var-actor' type='actor' scope='global'/>"
0398: + " <variable name='var-actor2' type='actor' scope='global'/>"
0399: + " <variable name='var-boolean' type='boolean' scope='global'/>"
0400: + " </variables>"
0401: + " <tasks>"
0402: + " <task name='test-task'>"
0403: + " <label>My test task</label>"
0404: + " <variables>"
0405: + " <variable name='var1' type='string' scope='task'>"
0406: + " <label>Variable 1</label>"
0407: + " </variable>"
0408: + " <variable base='var2'/>"
0409: + " <variable base='var-link'/>"
0410: + " <variable base='var-long'/>"
0411: + " <variable base='var-date'/>"
0412: + " <variable base='var-datetime'/>"
0413: + " <variable base='var-actor'/>"
0414: + " <variable base='var-actor2'/>"
0415: + " <variable base='var-boolean'/>"
0416: + " </variables>"
0417: + " </task>"
0418: + " </tasks>" + "</workflowMeta>";
0419:
0420: WfProcessDefinition wfDef = workflowManager
0421: .deployProcessDefinition(buildWorkflowArchive(
0422: workflow, workflowMeta, resourceBundles),
0423: "application/zip", locale);
0424: WfProcessInstance wfInst = workflowManager.startProcess(
0425: wfDef.getId(), null, null, locale);
0426:
0427: // two instances should exist at this point
0428: assertEquals(2, wfInst.getTasks().size());
0429:
0430: WfTask task = wfInst.getTask("test-task");
0431: assertNotNull(task);
0432:
0433: assertEquals(TaskPriority.NORMAL, task.getPriority());
0434: assertNull(task.getDueDate());
0435:
0436: TaskUpdateData taskUpdateData = new TaskUpdateData();
0437: taskUpdateData.setPriority(TaskPriority.HIGHEST);
0438: task = workflowManager.updateTask(task.getId(),
0439: taskUpdateData, locale);
0440:
0441: assertEquals(TaskPriority.HIGHEST, task.getPriority());
0442: assertNull(task.getDueDate());
0443:
0444: Date dueDate = getDate(new Date(System.currentTimeMillis()
0445: + (1000 * 60 * 60)), true);
0446: taskUpdateData.setDueDate(dueDate);
0447: task = workflowManager.updateTask(task.getId(),
0448: taskUpdateData, locale);
0449:
0450: assertEquals(dueDate, task.getDueDate());
0451:
0452: // Basic variables test
0453: taskUpdateData.setVariable("var1", VariableScope.TASK,
0454: WfValueType.STRING, "boe!");
0455: task = workflowManager.updateTask(task.getId(),
0456: taskUpdateData, locale);
0457: assertEquals("boe!", task.getVariable("var1",
0458: VariableScope.TASK).getValue());
0459: assertNull(task.getVariable("var1", VariableScope.GLOBAL));
0460:
0461: // Setting variable in wrong scope should be ignored
0462: taskUpdateData.setVariable("var2", VariableScope.TASK,
0463: WfValueType.STRING, "boe2!");
0464: task = workflowManager.updateTask(task.getId(),
0465: taskUpdateData, locale);
0466: assertNull(task.getVariable("var2", VariableScope.TASK));
0467: assertNull(task.getVariable("var2", VariableScope.GLOBAL));
0468:
0469: taskUpdateData.setVariable("var2", VariableScope.GLOBAL,
0470: WfValueType.STRING, "boe2!");
0471: task = workflowManager.updateTask(task.getId(),
0472: taskUpdateData, locale);
0473: assertEquals("boe2!", task.getVariable("var2",
0474: VariableScope.GLOBAL).getValue());
0475: assertEquals(2, task.getVariables().size());
0476:
0477: taskUpdateData.deleteVariable("var2", VariableScope.GLOBAL);
0478: task = workflowManager.updateTask(task.getId(),
0479: taskUpdateData, locale);
0480: assertNull(task.getVariable("var2", VariableScope.GLOBAL));
0481: assertEquals(1, task.getVariables().size());
0482:
0483: assertEquals("Variable 1", wfDef.getTask("test-task")
0484: .getVariable("var1", VariableScope.TASK).getLabel()
0485: .getText());
0486:
0487: task = workflowManager.updateTask(task.getId(),
0488: new TaskUpdateData(), locale);
0489: // check variables etc. are not removed/reset when nothing is mentioned about them in the TaskUpdateData
0490: assertEquals(1, task.getVariables().size());
0491: assertEquals(TaskPriority.HIGHEST, task.getPriority());
0492: assertEquals(dueDate, task.getDueDate());
0493:
0494: List<Long> poolIds = new ArrayList<Long>();
0495: poolIds.add(1L);
0496: poolIds.add(2L);
0497: WfActorKey poolKey = new WfActorKey(poolIds);
0498:
0499: // try all variable data types
0500: taskUpdateData = new TaskUpdateData();
0501: Date date = getDate(new Date(), false);
0502: Date dateTime = getDate(new Date(), true);
0503: taskUpdateData.setVariable("var-link",
0504: VariableScope.GLOBAL, WfValueType.DAISY_LINK,
0505: new WfVersionKey("1-DSY", 1, 1, null));
0506: taskUpdateData.setVariable("var-long",
0507: VariableScope.GLOBAL, WfValueType.LONG,
0508: new Long(55));
0509: taskUpdateData.setVariable("var-date",
0510: VariableScope.GLOBAL, WfValueType.DATE, date);
0511: taskUpdateData.setVariable("var-datetime",
0512: VariableScope.GLOBAL, WfValueType.DATETIME,
0513: dateTime);
0514: taskUpdateData.setVariable("var-actor",
0515: VariableScope.GLOBAL, WfValueType.ACTOR,
0516: new WfActorKey(3));
0517: taskUpdateData.setVariable("var-actor2",
0518: VariableScope.GLOBAL, WfValueType.ACTOR, poolKey);
0519: taskUpdateData.setVariable("var-boolean",
0520: VariableScope.GLOBAL, WfValueType.BOOLEAN,
0521: Boolean.TRUE);
0522:
0523: task = workflowManager.updateTask(task.getId(),
0524: taskUpdateData, locale);
0525: assertEquals(new WfVersionKey("1-DSY", 1, 1, null), task
0526: .getVariable("var-link", VariableScope.GLOBAL)
0527: .getValue());
0528: assertEquals(new Long(55), task.getVariable("var-long",
0529: VariableScope.GLOBAL).getValue());
0530: assertEquals(date, task.getVariable("var-date",
0531: VariableScope.GLOBAL).getValue());
0532: assertEquals(dateTime, task.getVariable("var-datetime",
0533: VariableScope.GLOBAL).getValue());
0534: assertEquals(new WfActorKey(3), task.getVariable(
0535: "var-actor", VariableScope.GLOBAL).getValue());
0536: assertEquals(poolKey, task.getVariable("var-actor2",
0537: VariableScope.GLOBAL).getValue());
0538: assertEquals(Boolean.TRUE, task.getVariable("var-boolean",
0539: VariableScope.GLOBAL).getValue());
0540:
0541: String workflowMeta2 = "<workflowMeta xmlns='http://outerx.org/daisy/1.0#workflowmeta'>"
0542: + " <variables>"
0543: + " <variable name='var-required' type='string' scope='global' required='true'/>"
0544: + " <variable name='var-readonly' type='string' scope='global' readOnly='true'/>"
0545: + " </variables>"
0546: + " <tasks>"
0547: + " <task name='test-task'>"
0548: + " <variables>"
0549: + " <variable base='var-required'/>"
0550: + " <variable base='var-readonly'/>"
0551: + " </variables>"
0552: + " </task>"
0553: + " </tasks>" + "</workflowMeta>";
0554:
0555: WfProcessDefinition wfDef2 = workflowManager
0556: .deployProcessDefinition(buildWorkflowArchive(
0557: workflow, workflowMeta2, resourceBundles),
0558: "application/zip", locale);
0559: WfProcessInstance wfInst2 = workflowManager.startProcess(
0560: wfDef2.getId(), null, null, locale);
0561: WfTask task2 = wfInst2.getTask("test-task");
0562:
0563: taskUpdateData = new TaskUpdateData();
0564: taskUpdateData.setVariable("var-readonly",
0565: VariableScope.GLOBAL, WfValueType.STRING, "hi");
0566: // updating task should ignore the read only variable and not complain about the missing required variable
0567: task2 = workflowManager.updateTask(task2.getId(),
0568: taskUpdateData, locale);
0569: assertEquals("hello", task2.getVariable("var-readonly",
0570: VariableScope.GLOBAL).getValue());
0571:
0572: try {
0573: task2 = workflowManager.endTask(task2.getId(),
0574: taskUpdateData, null, locale);
0575: fail("Missing required variable should throw an exception.");
0576: } catch (WorkflowException e) {
0577: }
0578:
0579: taskUpdateData.setVariable("var-required",
0580: VariableScope.GLOBAL, WfValueType.STRING,
0581: "something");
0582: workflowManager.endTask(task2.getId(), taskUpdateData,
0583: null, locale);
0584:
0585: // Test process suspension, resumption and deletion
0586: WfProcessInstance suspendedProcess = workflowManager
0587: .suspendProcess(wfInst2.getId(), locale);
0588: assertTrue(suspendedProcess.isSuspended());
0589: suspendedProcess = workflowManager.getProcess(wfInst2
0590: .getId(), locale);
0591: assertTrue(suspendedProcess.isSuspended());
0592: suspendedProcess = workflowManager.resumeProcess(wfInst2
0593: .getId(), locale);
0594: assertFalse(suspendedProcess.isSuspended());
0595: workflowManager.deleteProcess(wfInst2.getId());
0596: try {
0597: workflowManager.getProcess(wfInst2.getId(), locale);
0598: fail("Expected a ProcessInstanceNotFoundException");
0599: } catch (ProcessInstanceNotFoundException e) { /* ignore */
0600: }
0601: ;
0602: }
0603:
0604: //
0605: // Some more variable functionality: selection lists, initial values, styling
0606: //
0607: {
0608: String workflow = "<process-definition name='test4'>"
0609: + " <swimlane name='initiator'/>"
0610: + " <start-state name='start'>"
0611: + " <task name='start-task' swimlane='initiator'/>"
0612: + " <transition name='trans' to='end'/>"
0613: + " </start-state>" + " <end-state name='end'/>"
0614: + "</process-definition>";
0615:
0616: String workflowMeta = "<workflowMeta xmlns='http://outerx.org/daisy/1.0#workflowmeta'"
0617: + " xmlns:wfmeta='http://outerx.org/daisy/1.0#workflowmeta'"
0618: + " xmlns:wf='http://outerx.org/daisy/1.0#workflow'>"
0619: + " <label>My workflow</label>"
0620: + " <description>A workflow for test purposes.</description>"
0621: + " <variables>"
0622: + " <variable name='var1' type='string' scope='global'>"
0623: + " <selectionList>"
0624: + " <listItem>"
0625: + " <wf:string>value1</wf:string>"
0626: + " <label>Label 1</label>"
0627: + " </listItem>"
0628: + " <listItem>"
0629: + " <wf:string>value2</wf:string>"
0630: + " </listItem>"
0631: + " </selectionList>"
0632: + " <initialValueScript>"
0633: + " return 'value1';"
0634: + " </initialValueScript>"
0635: + " <wfmeta:styling foo='bar' xmlns=''>foo <b>bar</b> foo!</wfmeta:styling>"
0636: + " </variable>"
0637: + " </variables>"
0638: + " <tasks>"
0639: + " <task name='start-task'>"
0640: + " <variables>"
0641: + " <variable base='var1'/>"
0642: + " </variables>"
0643: + " </task>"
0644: + " </tasks>" + "</workflowMeta>";
0645:
0646: WfProcessDefinition wfDef = workflowManager
0647: .deployProcessDefinition(buildWorkflowArchive(
0648: workflow, workflowMeta, resourceBundles),
0649: "application/zip", locale);
0650: WfTaskDefinition taskDef = wfDef.getTask("start-task");
0651: WfVariableDefinition variableDef = taskDef.getVariable(
0652: "var1", VariableScope.GLOBAL);
0653:
0654: assertNotNull(variableDef.getSelectionList());
0655: assertEquals(2, variableDef.getSelectionList().size());
0656: assertEquals("value1", variableDef.getSelectionList()
0657: .get(0).getValue());
0658: assertEquals("Label 1", variableDef.getSelectionList().get(
0659: 0).getLabel().getText());
0660: assertEquals("value2", variableDef.getSelectionList()
0661: .get(1).getValue());
0662:
0663: List<WfVariable> initialVariableValues = workflowManager
0664: .getInitialVariables(wfDef.getId(), null);
0665: assertEquals(1, initialVariableValues.size());
0666: assertEquals("value1", initialVariableValues.get(0)
0667: .getValue());
0668:
0669: System.out.println("Styling info is: ");
0670: System.out.println(variableDef.getStyling().toString());
0671: }
0672:
0673: //
0674: // A review workflow testcase
0675: //
0676: {
0677: // Create a reviewer user
0678: User reviewerUser = repository.getUserManager().createUser(
0679: "reviewer");
0680: reviewerUser.setPassword("reviewer");
0681: reviewerUser.addToRole(repository.getUserManager().getRole(
0682: "User", false));
0683: reviewerUser.save();
0684: Repository reviewerRepo = repositoryManager
0685: .getRepository(new Credentials("reviewer",
0686: "reviewer"));
0687: WorkflowManager reviewerWfManager = (WorkflowManager) reviewerRepo
0688: .getExtension("WorkflowManager");
0689:
0690: // Set ACL to something meaningful
0691: AccessManager accessManager = repository.getAccessManager();
0692: Acl acl = accessManager.getStagingAcl();
0693:
0694: AclObject aclObject = acl.createNewObject("true");
0695: AclEntry aclEntry = aclObject.createNewEntry(
0696: AclSubjectType.EVERYONE, -1);
0697: for (AclPermission permission : AclPermission.values()) {
0698: aclEntry.set(permission, AclActionType.GRANT);
0699: }
0700: aclObject.add(aclEntry);
0701: acl.add(aclObject);
0702: acl.save();
0703: accessManager.copyStagingToLive();
0704:
0705: // Create the document to review
0706: DocumentType docType = repository.getRepositorySchema()
0707: .createDocumentType("TestDocType");
0708: docType.save();
0709: Document document = repository.createDocument(
0710: "A document to review", docType.getName());
0711: document.setNewVersionState(VersionState.DRAFT);
0712: document.save();
0713:
0714: // Create the process definition
0715: String reviewWorkflow = readResource("review-process-definition.xml");
0716: String reviewMeta = readResource("review-process-meta.xml");
0717:
0718: WfProcessDefinition reviewDef = workflowManager
0719: .deployProcessDefinition(
0720: buildWorkflowArchive(reviewWorkflow,
0721: reviewMeta, resourceBundles),
0722: "application/zip", locale);
0723:
0724: // check resource bundles work
0725: assertEquals("Review workflow", reviewDef.getLabel()
0726: .getText());
0727:
0728: // check translated labels + resource bundle fallback
0729: WfProcessDefinition reviewDefNl = workflowManager
0730: .getProcessDefinition(reviewDef.getId(),
0731: new Locale("nl", "BE"));
0732: assertEquals("Verifieer-workflow", reviewDefNl.getLabel()
0733: .getText());
0734: assertEquals("Start document review", reviewDefNl.getTask(
0735: "startReviewTask").getLabel().getText());
0736:
0737: // Start the workflow
0738: TaskUpdateData startTaskData = new TaskUpdateData();
0739: WfVersionKey documentKey = WfVersionKey.get(document, "1");
0740: startTaskData.setVariable("document", VariableScope.GLOBAL,
0741: WfValueType.DAISY_LINK, documentKey);
0742: startTaskData.setVariable("reviewer", VariableScope.GLOBAL,
0743: WfValueType.ACTOR, new WfActorKey(reviewerUser
0744: .getId()));
0745: WfProcessInstance reviewInst = workflowManager
0746: .startProcess(reviewDef.getId(), startTaskData,
0747: "review", locale);
0748:
0749: // Reviewer does the reviewing
0750: List<WfTask> reviewerTasks = reviewerWfManager
0751: .getMyTasks(locale);
0752: System.out.println("reviewer tasks: "
0753: + reviewerTasks.size());
0754: assertEquals(1, reviewerTasks.size());
0755: WfTask reviewTask = reviewerTasks.get(0);
0756: assertEquals("reviewTask", reviewTask.getDefinition()
0757: .getName());
0758: assertEquals(documentKey, reviewTask
0759: .getVariable("document").getValue());
0760:
0761: TaskUpdateData reviewerData = new TaskUpdateData();
0762: reviewerData.setVariable("reviewComment",
0763: VariableScope.GLOBAL, WfValueType.STRING,
0764: "This needs some more work.");
0765: reviewerWfManager.endTask(reviewTask.getId(), reviewerData,
0766: "requestChanges", locale);
0767:
0768: // Submitter gets requestChanges task and asks new review
0769: List<WfTask> tasks = workflowManager.getMyTasks(locale);
0770: WfTask requestChangesTask = null;
0771: for (WfTask task : tasks) {
0772: System.out.println("found task "
0773: + task.getDefinition().getName());
0774: if (task.getDefinition().getName().equals(
0775: "requestChangesTask")) {
0776: requestChangesTask = task;
0777: break;
0778: }
0779: }
0780: assertNotNull("Did not find the request changes task",
0781: requestChangesTask);
0782: assertEquals("This needs some more work.",
0783: requestChangesTask.getVariable("reviewComment")
0784: .getValue());
0785:
0786: // Do some update on the document
0787: document.setName("A document to review -- updated");
0788: document.setNewVersionState(VersionState.DRAFT);
0789: document.save();
0790:
0791: WfVersionKey updatedVersionKey = WfVersionKey.get(document,
0792: String.valueOf(document.getLastVersionId()));
0793: assertEquals(VersionState.DRAFT, updatedVersionKey
0794: .getVersion(repository).getState());
0795:
0796: TaskUpdateData requestChangesData = new TaskUpdateData();
0797: requestChangesData.setVariable("fixComment",
0798: VariableScope.GLOBAL, WfValueType.STRING,
0799: "Did some improvements.");
0800: requestChangesData.setVariable("document",
0801: VariableScope.GLOBAL, WfValueType.DAISY_LINK,
0802: updatedVersionKey);
0803: workflowManager.endTask(requestChangesTask.getId(),
0804: requestChangesData, "newReview", locale);
0805:
0806: // Reviewer accepts
0807: reviewerWfManager.endTask(reviewerWfManager.getMyTasks(
0808: locale).get(0).getId(), null, "approve", locale);
0809: assertEquals(0, reviewerWfManager.getMyTasks(locale).size());
0810:
0811: // check document version was put to state 'publish'
0812: assertEquals(VersionState.PUBLISH, updatedVersionKey
0813: .getVersion(repository).getState());
0814:
0815: // Check process is ended
0816: reviewInst = reviewerWfManager.getProcess(reviewInst
0817: .getId(), locale);
0818: assertNotNull(reviewInst.getEnd());
0819:
0820: //
0821: // Do another review, now with a pool assigned as reviewer
0822: //
0823:
0824: // First create a pool
0825: WfPoolManager poolManager = workflowManager
0826: .getPoolManager();
0827: WfPool pool = poolManager.createPool("My pool");
0828: pool.save();
0829: poolManager.addUsersToPool(pool.getId(), longList(
0830: reviewerUser.getId(), 500, 501, 502));
0831:
0832: startTaskData = new TaskUpdateData();
0833: documentKey = WfVersionKey.get(document, "1");
0834: startTaskData.setVariable("document", VariableScope.GLOBAL,
0835: WfValueType.DAISY_LINK, documentKey);
0836: startTaskData.setVariable("reviewer", VariableScope.GLOBAL,
0837: WfValueType.ACTOR, new WfActorKey(longList(pool
0838: .getId())));
0839: reviewInst = workflowManager.startProcess(
0840: reviewDef.getId(), startTaskData, "review", locale);
0841:
0842: assertEquals(0, reviewerWfManager.getMyTasks(locale).size());
0843: assertEquals(1, reviewerWfManager.getPooledTasks(locale)
0844: .size());
0845: WfTask pooledTask = reviewerWfManager
0846: .getPooledTasks(locale).get(0);
0847: assertEquals(-1, pooledTask.getActorId());
0848:
0849: // Try same query ("my pooled tasks") using the generic query API
0850: QueryConditions queryConditions = new QueryConditions();
0851: List<QueryOrderByItem> orderByItems = new ArrayList<QueryOrderByItem>();
0852: queryConditions.addSpecialCondition("tasksInMyPool",
0853: new WfValueType[0], new Object[0]);
0854: queryConditions.addCondition("task.actor",
0855: WfValueType.USER, "is_null");
0856: queryConditions.addCondition("task.isOpen",
0857: WfValueType.BOOLEAN, "eq", Boolean.TRUE);
0858: assertEquals(1, reviewerWfManager.getTasks(queryConditions,
0859: orderByItems, -1, -1, Locale.US).size());
0860:
0861: try {
0862: dummyWfManager.requestPooledTask(pooledTask.getId(),
0863: locale);
0864: fail("Requesting a pooled task which does not belong to any of the user's pools should fail.");
0865: } catch (WfAuthorizationException e) {
0866: }
0867:
0868: WfTask myTask = reviewerWfManager.requestPooledTask(
0869: pooledTask.getId(), locale);
0870: assertEquals(reviewerUser.getId(), myTask.getActorId());
0871: assertEquals(1, reviewerWfManager.getMyTasks(locale).size());
0872: assertEquals(0, reviewerWfManager.getPooledTasks(locale)
0873: .size());
0874:
0875: try {
0876: reviewerWfManager.requestPooledTask(pooledTask.getId(),
0877: locale);
0878: fail("Requesting assignment of a non-pooled task should fail.");
0879: } catch (WorkflowException e) {
0880: }
0881: }
0882:
0883: //
0884: // Test the generic process and task query API
0885: //
0886: {
0887: String workflow = "<process-definition name='searchtest'>"
0888: + " <swimlane name='initiator'/>"
0889: + " <start-state name='start'>"
0890: + " <task name='start-task' swimlane='initiator'/>"
0891: + " <transition name='trans' to='end'/>"
0892: + " </start-state>" + " <end-state name='end'/>"
0893: + "</process-definition>";
0894:
0895: String workflowMeta = "<workflowMeta xmlns='http://outerx.org/daisy/1.0#workflowmeta'"
0896: + " xmlns:wfmeta='http://outerx.org/daisy/1.0#workflowmeta'"
0897: + " xmlns:wf='http://outerx.org/daisy/1.0#workflow'>"
0898: + " <label>My workflow</label>"
0899: + " <description>A workflow for test purposes.</description>"
0900: + " <variables>"
0901: + " <variable name='var1' type='string' scope='global'>"
0902: + " <selectionList>"
0903: + " <listItem>"
0904: + " <wf:string>value1</wf:string>"
0905: + " <label>Label 1</label>"
0906: + " </listItem>"
0907: + " <listItem>"
0908: + " <wf:string>value2</wf:string>"
0909: + " </listItem>"
0910: + " </selectionList>"
0911: + " <initialValueScript>"
0912: + " return 'value1';"
0913: + " </initialValueScript>"
0914: + " <wfmeta:styling foo='bar' xmlns=''>foo <b>bar</b> foo!</wfmeta:styling>"
0915: + " </variable>"
0916: + " <variable name='var2' type='long' scope='global'/>"
0917: + " <variable name='var3' type='string' scope='global'/>"
0918: + " <variable name='var4' type='boolean' scope='global'/>"
0919: + " <variable name='var5' type='daisy-link' scope='global'/>"
0920: + " <variable name='var6' type='daisy-link' scope='global'/>"
0921: + " <variable name='var7' type='date' scope='global'/>"
0922: + " </variables>"
0923: + " <tasks>"
0924: + " <task name='start-task'>"
0925: + " <variables>"
0926: + " <variable base='var1'/>"
0927: + " <variable base='var2'/>"
0928: + " <variable base='var3' type='string' scope='task'/>"
0929: + " <variable base='var4'/>"
0930: + " <variable base='var5'/>"
0931: + " <variable base='var6'/>"
0932: + " <variable base='var7'/>"
0933: + " </variables>"
0934: + " </task>"
0935: + " </tasks>" + "</workflowMeta>";
0936:
0937: WfProcessDefinition wfDef = workflowManager
0938: .deployProcessDefinition(buildWorkflowArchive(
0939: workflow, workflowMeta, resourceBundles),
0940: "application/zip", locale);
0941:
0942: Date testDate = getDate(new Date(), false);
0943: TaskUpdateData startTaskData = new TaskUpdateData();
0944: startTaskData.setVariable("var1", VariableScope.GLOBAL,
0945: WfValueType.STRING, "value1");
0946: startTaskData.setVariable("var2", VariableScope.GLOBAL,
0947: WfValueType.LONG, new Long(33));
0948: startTaskData.setVariable("var3", VariableScope.TASK,
0949: WfValueType.STRING, "testval");
0950: startTaskData.setVariable("var4", VariableScope.GLOBAL,
0951: WfValueType.BOOLEAN, Boolean.TRUE);
0952: startTaskData.setVariable("var5", VariableScope.GLOBAL,
0953: WfValueType.DAISY_LINK, new WfVersionKey("99-DSY",
0954: 1, 1, null));
0955: startTaskData.setVariable("var6", VariableScope.GLOBAL,
0956: WfValueType.DAISY_LINK, new WfVersionKey("99-DSY",
0957: 1, 1, "live"));
0958: startTaskData.setVariable("var7", VariableScope.GLOBAL,
0959: WfValueType.DATE, testDate);
0960: workflowManager.startProcess(wfDef.getId(), startTaskData,
0961: null, Locale.US);
0962:
0963: List<WfTask> tasks;
0964: List<WfProcessInstance> processes;
0965: QueryConditions queryConditions;
0966: List<QueryOrderByItem> orderByItems;
0967:
0968: // QueryConditions without any conditions should work
0969: queryConditions = new QueryConditions();
0970: orderByItems = Collections.emptyList();
0971: workflowManager.getTasks(queryConditions, orderByItems, -1,
0972: -1, Locale.US);
0973:
0974: // Test a like-condition
0975: queryConditions = new QueryConditions();
0976: queryConditions.addTaskVariableCondition("var3",
0977: WfValueType.STRING, "like", "%val%");
0978: tasks = workflowManager.getTasks(queryConditions,
0979: orderByItems, -1, -1, Locale.US);
0980: assertEquals(1, tasks.size());
0981:
0982: // Test any-combination
0983: queryConditions = new QueryConditions();
0984: queryConditions.setMeetAllCriteria(false);
0985: queryConditions.addTaskVariableCondition("var3",
0986: WfValueType.STRING, "like", "%val%");
0987: queryConditions.addTaskVariableCondition("var3",
0988: WfValueType.STRING, "like",
0989: "%somethingitdoesntcontain%");
0990: tasks = workflowManager.getTasks(queryConditions,
0991: orderByItems, -1, -1, Locale.US);
0992: assertEquals(1, tasks.size());
0993:
0994: // Test all-combination
0995: queryConditions = new QueryConditions();
0996: queryConditions.setMeetAllCriteria(true);
0997: queryConditions.addTaskVariableCondition("var3",
0998: WfValueType.STRING, "like", "%val%");
0999: queryConditions.addTaskVariableCondition("var3",
1000: WfValueType.STRING, "like",
1001: "%somethingitdoesntcontain%");
1002: tasks = workflowManager.getTasks(queryConditions,
1003: orderByItems, -1, -1, Locale.US);
1004: assertEquals(0, tasks.size());
1005:
1006: // Test is not null condition
1007: queryConditions = new QueryConditions();
1008: queryConditions.addTaskVariableCondition("var3",
1009: WfValueType.STRING, "is_not_null");
1010: tasks = workflowManager.getTasks(queryConditions,
1011: orderByItems, -1, -1, Locale.US);
1012: assertEquals(1, tasks.size());
1013:
1014: // test a between condition
1015: queryConditions = new QueryConditions();
1016: queryConditions.addProcessVariableCondition("var2",
1017: WfValueType.LONG, "between", 32l, 34l);
1018: tasks = workflowManager.getTasks(queryConditions,
1019: orderByItems, -1, -1, Locale.US);
1020: assertEquals(1, tasks.size());
1021:
1022: // test a between condition, searching for processes
1023: queryConditions = new QueryConditions();
1024: queryConditions.addProcessVariableCondition("var2",
1025: WfValueType.LONG, "between", 32l, 34l);
1026: processes = workflowManager.getProcesses(queryConditions,
1027: orderByItems, -1, -1, Locale.US);
1028: assertEquals(1, processes.size());
1029:
1030: // less than
1031: queryConditions = new QueryConditions();
1032: queryConditions.addProcessVariableCondition("var2",
1033: WfValueType.LONG, "lt", 34l);
1034: tasks = workflowManager.getTasks(queryConditions,
1035: orderByItems, -1, -1, Locale.US);
1036: assertEquals(1, tasks.size());
1037:
1038: // greater than
1039: queryConditions = new QueryConditions();
1040: queryConditions.addProcessVariableCondition("var2",
1041: WfValueType.LONG, "gt", 32l);
1042: tasks = workflowManager.getTasks(queryConditions,
1043: orderByItems, -1, -1, Locale.US);
1044: assertEquals(1, tasks.size());
1045:
1046: // boolean search
1047: queryConditions = new QueryConditions();
1048: queryConditions.addProcessVariableCondition("var4",
1049: WfValueType.BOOLEAN, "eq", Boolean.TRUE);
1050: tasks = workflowManager.getTasks(queryConditions,
1051: orderByItems, -1, -1, Locale.US);
1052: assertEquals(1, tasks.size());
1053:
1054: // version key search
1055: queryConditions = new QueryConditions();
1056: queryConditions.addProcessVariableCondition("var5",
1057: WfValueType.DAISY_LINK, "like", new WfVersionKey(
1058: "99-DSY", 1, 1, null));
1059: tasks = workflowManager.getTasks(queryConditions,
1060: orderByItems, -1, -1, Locale.US);
1061: assertEquals(1, tasks.size());
1062:
1063: queryConditions = new QueryConditions();
1064: queryConditions.addProcessVariableCondition("var6",
1065: WfValueType.DAISY_LINK, "like", new WfVersionKey(
1066: "99-DSY", 1, 1, "live"));
1067: tasks = workflowManager.getTasks(queryConditions,
1068: orderByItems, -1, -1, Locale.US);
1069: assertEquals(1, tasks.size());
1070:
1071: queryConditions = new QueryConditions();
1072: queryConditions.addProcessVariableCondition("var6",
1073: WfValueType.DAISY_LINK, "like", new WfVersionKey(
1074: "99-DSY", 1, 1, "last"));
1075: tasks = workflowManager.getTasks(queryConditions,
1076: orderByItems, -1, -1, Locale.US);
1077: assertEquals(0, tasks.size());
1078:
1079: queryConditions = new QueryConditions();
1080: queryConditions.addProcessVariableCondition("var6",
1081: WfValueType.DAISY_LINK, "like", new WfVersionKey(
1082: "99-DSY", 1, 1, null));
1083: tasks = workflowManager.getTasks(queryConditions,
1084: orderByItems, -1, -1, Locale.US);
1085: assertEquals(1, tasks.size());
1086:
1087: // date search
1088: queryConditions = new QueryConditions();
1089: queryConditions.addProcessVariableCondition("var7",
1090: WfValueType.DATE, "eq", testDate);
1091: tasks = workflowManager.getTasks(queryConditions,
1092: orderByItems, -1, -1, Locale.US);
1093: assertEquals(1, tasks.size());
1094:
1095: // relatedToDocument special condition
1096: queryConditions = new QueryConditions();
1097: queryConditions.addSpecialCondition("relatedToDocument",
1098: new WfValueType[] { WfValueType.DAISY_LINK },
1099: new Object[] { new WfVersionKey("99-DSY", 1, 1,
1100: null) });
1101: processes = workflowManager.getProcesses(queryConditions,
1102: orderByItems, -1, -1, Locale.US);
1103: assertEquals(1, processes.size());
1104:
1105: // Test some basic error checking
1106: queryConditions = new QueryConditions();
1107: try {
1108: queryConditions.addProcessVariableCondition("var7",
1109: WfValueType.DATE, "eq", "foo");
1110: fail("Giving an incorrect type of data should fail.");
1111: } catch (IllegalArgumentException e) {
1112: } catch (Exception e) {
1113: }
1114:
1115: queryConditions = new QueryConditions();
1116: queryConditions.addProcessVariableCondition("var7",
1117: WfValueType.DATE, "eq", new Date(), new Date());
1118: try {
1119: workflowManager.getTasks(queryConditions, orderByItems,
1120: -1, -1, Locale.US);
1121: fail("Giving an incorrect number of values should fail.");
1122: } catch (IllegalArgumentException e) {
1123: } catch (Exception e) {
1124: }
1125:
1126: queryConditions = new QueryConditions();
1127: queryConditions.addProcessVariableCondition("var7",
1128: WfValueType.DATE, "like", testDate);
1129: try {
1130: workflowManager.getTasks(queryConditions, orderByItems,
1131: -1, -1, Locale.US);
1132: fail("A like-search for a date should give an error");
1133: } catch (WorkflowException e) {
1134: }
1135:
1136: queryConditions = new QueryConditions();
1137: queryConditions.addTaskVariableCondition("var3",
1138: WfValueType.STRING, "like", "%val%");
1139: try {
1140: workflowManager.getProcesses(queryConditions,
1141: orderByItems, -1, -1, Locale.US);
1142: fail("Searching for processes using taks variables should fail.");
1143: } catch (WorkflowException e) {
1144: }
1145:
1146: // test selecting some stuff -- tasks
1147: queryConditions = new QueryConditions();
1148: queryConditions.addCondition("process.definitionName",
1149: WfValueType.STRING, "eq", "searchtest");
1150: List<QuerySelectItem> selectItems = new ArrayList<QuerySelectItem>();
1151: selectItems.add(new QuerySelectItem("task.id",
1152: QueryValueSource.PROPERTY));
1153: selectItems.add(new QuerySelectItem("var1",
1154: QueryValueSource.PROCESS_VARIABLE));
1155: selectItems.add(new QuerySelectItem("task.definitionLabel",
1156: QueryValueSource.PROPERTY));
1157: selectItems.add(new QuerySelectItem(
1158: "task.definitionDescription",
1159: QueryValueSource.PROPERTY));
1160: selectItems.add(new QuerySelectItem("task.create",
1161: QueryValueSource.PROPERTY));
1162: orderByItems = new ArrayList<QueryOrderByItem>();
1163: orderByItems.add(new QueryOrderByItem("task.id",
1164: QueryValueSource.PROPERTY, SortOrder.ASCENDING));
1165: SearchResultDocument.SearchResult result = workflowManager
1166: .searchTasks(selectItems, queryConditions,
1167: orderByItems, -1, -1, Locale.US)
1168: .getSearchResult();
1169: assertEquals(1, result.getRows().getRowArray().length);
1170: assertTrue(result.getRows().getRowArray(0).getValueArray(1)
1171: .isSetLabel());
1172:
1173: // test selecting some stuff -- processes
1174: queryConditions = new QueryConditions();
1175: queryConditions.addCondition("process.definitionName",
1176: WfValueType.STRING, "eq", "searchtest");
1177: selectItems = new ArrayList<QuerySelectItem>();
1178: selectItems.add(new QuerySelectItem("daisy_creator",
1179: QueryValueSource.PROCESS_VARIABLE));
1180: selectItems.add(new QuerySelectItem("daisy_owner",
1181: QueryValueSource.PROCESS_VARIABLE));
1182: selectItems.add(new QuerySelectItem("process.id",
1183: QueryValueSource.PROPERTY));
1184: selectItems.add(new QuerySelectItem("process.start",
1185: QueryValueSource.PROPERTY));
1186: selectItems.add(new QuerySelectItem("process.end",
1187: QueryValueSource.PROPERTY));
1188: selectItems.add(new QuerySelectItem("var1",
1189: QueryValueSource.PROCESS_VARIABLE));
1190: orderByItems = new ArrayList<QueryOrderByItem>();
1191: orderByItems.add(new QueryOrderByItem("process.start",
1192: QueryValueSource.PROPERTY, SortOrder.ASCENDING));
1193: result = workflowManager.searchProcesses(selectItems,
1194: queryConditions, orderByItems, -1, -1, Locale.US)
1195: .getSearchResult();
1196: assertEquals(1, result.getRows().getRowArray().length);
1197: assertEquals("3", ((XmlString) result.getRows()
1198: .getRowArray(0).getValueArray(0).getRaw())
1199: .getStringValue());
1200: assertEquals("testuser", ((XmlString) result.getRows()
1201: .getRowArray(0).getValueArray(0).getLabel())
1202: .getStringValue());
1203: assertEquals("3", ((XmlString) result.getRows()
1204: .getRowArray(0).getValueArray(1).getRaw())
1205: .getStringValue());
1206: assertEquals("testuser", ((XmlString) result.getRows()
1207: .getRowArray(0).getValueArray(1).getLabel())
1208: .getStringValue());
1209: }
1210:
1211: // Some task-vs-global variable tests
1212: {
1213: String workflow = "<process-definition name='searchtest'>"
1214: + " <swimlane name='initiator'/>"
1215: + " <start-state name='start'>"
1216: + " <task name='start-task' swimlane='initiator'/>"
1217: + " <transition name='trans' to='end'/>"
1218: + " </start-state>" + " <end-state name='end'/>"
1219: + "</process-definition>";
1220:
1221: String workflowMeta = "<workflowMeta xmlns='http://outerx.org/daisy/1.0#workflowmeta'"
1222: + " xmlns:wfmeta='http://outerx.org/daisy/1.0#workflowmeta'"
1223: + " xmlns:wf='http://outerx.org/daisy/1.0#workflow'>"
1224: + " <variables>"
1225: + " <variable name='var' type='date' scope='global'/>"
1226: + " </variables>"
1227: + " <tasks>"
1228: + " <task name='start-task'>"
1229: + " <variables>"
1230: + " <variable base='var' type='long'/>"
1231: + " </variables>"
1232: + " </task>"
1233: + " </tasks>" + "</workflowMeta>";
1234:
1235: try {
1236: workflowManager.deployProcessDefinition(
1237: buildWorkflowArchive(workflow, workflowMeta,
1238: resourceBundles), "application/zip",
1239: locale);
1240: fail("Overriding a global variable with a different type should fail.");
1241:
1242: } catch (WorkflowException e) {
1243: }
1244:
1245: workflowMeta = "<workflowMeta xmlns='http://outerx.org/daisy/1.0#workflowmeta'"
1246: + " xmlns:wfmeta='http://outerx.org/daisy/1.0#workflowmeta'"
1247: + " xmlns:wf='http://outerx.org/daisy/1.0#workflow'>"
1248: + " <tasks>"
1249: + " <task name='start-task'>"
1250: + " <variables>"
1251: + " <variable name='var' type='long' scope='global'/>"
1252: + " </variables>"
1253: + " </task>"
1254: + " </tasks>" + "</workflowMeta>";
1255:
1256: try {
1257: workflowManager.deployProcessDefinition(
1258: buildWorkflowArchive(workflow, workflowMeta,
1259: resourceBundles), "application/zip",
1260: locale);
1261: fail("Defining a global variable not-globally should fail.");
1262: } catch (WorkflowException e) {
1263: }
1264:
1265: workflowMeta = "<workflowMeta xmlns='http://outerx.org/daisy/1.0#workflowmeta'"
1266: + " xmlns:wfmeta='http://outerx.org/daisy/1.0#workflowmeta'"
1267: + " xmlns:wf='http://outerx.org/daisy/1.0#workflow'>"
1268: + " <variables>"
1269: + " <variable name='var' type='long' scope='global'/>"
1270: + " </variables>"
1271: + " <tasks>"
1272: + " <task name='start-task'>"
1273: + " <variables>"
1274: + " <variable base='var'>"
1275: + " <selectionList>"
1276: + " <listItem>"
1277: + " <wf:string>value1</wf:string>"
1278: + " </listItem>"
1279: + " </selectionList>"
1280: + " </variable>"
1281: + " </variables>"
1282: + " </task>" + " </tasks>" + "</workflowMeta>";
1283:
1284: try {
1285: workflowManager.deployProcessDefinition(
1286: buildWorkflowArchive(workflow, workflowMeta,
1287: resourceBundles), "application/zip",
1288: locale);
1289: fail("Changing the selection list of a global variable locally should fail.");
1290: } catch (WorkflowException e) {
1291: }
1292: }
1293:
1294: //
1295: // Some authorization tests
1296: //
1297: {
1298: // Create a user
1299: User authTestUser = repository.getUserManager().createUser(
1300: "auth-test");
1301: authTestUser.setPassword("auth-test");
1302: authTestUser.addToRole(repository.getUserManager().getRole(
1303: "User", false));
1304: authTestUser.save();
1305: Repository authTestRepo = repositoryManager
1306: .getRepository(new Credentials("auth-test",
1307: "auth-test"));
1308: WorkflowManager authTestWfManager = (WorkflowManager) authTestRepo
1309: .getExtension("WorkflowManager");
1310:
1311: WfPool pool = workflowManager.getPoolManager().createPool(
1312: "AuthTestPool");
1313: pool.save();
1314:
1315: String workflow = "<process-definition name='testaccess'>"
1316: + " <swimlane name='initiator'/>"
1317: + " <start-state name='start'>"
1318: + " <task name='start-task' swimlane='initiator'/>"
1319: + " <transition name='trans1' to='s'/>"
1320: + " </start-state>" + " <task-node name='s'>"
1321: + " <task name='test-task'>"
1322: + " <assignment pooled-actors='"
1323: + pool.getId() + "'/>" + " </task>"
1324: + " <transition name='trans2' to='end'/>"
1325: + " </task-node>" + " <end-state name='end'/>"
1326: + "</process-definition>";
1327:
1328: String workflowMeta = "<workflowMeta xmlns='http://outerx.org/daisy/1.0#workflowmeta'>"
1329: + " <variables>"
1330: + " <variable name='daisy_document' type='daisy-link' scope='global'/>"
1331: + " </variables>"
1332: + " <tasks>"
1333: + " <task name='test-task'>"
1334: + " <variables>"
1335: + " <variable base='daisy_document'/>"
1336: + " </variables>"
1337: + " </task>"
1338: + " </tasks>" + "</workflowMeta>";
1339:
1340: WfProcessDefinition processDef = workflowManager
1341: .deployProcessDefinition(buildWorkflowArchive(
1342: workflow, workflowMeta, resourceBundles),
1343: "application/zip", locale);
1344:
1345: WfProcessInstance processInstance = workflowManager
1346: .startProcess(processDef.getId(),
1347: new TaskUpdateData(), "trans1", Locale.US);
1348:
1349: // normal user should not be able to access a process with which has nothing to do
1350: try {
1351: authTestWfManager.getProcess(processInstance.getId(),
1352: Locale.US);
1353: fail("User should not be able to access process instance.");
1354: } catch (WfAuthorizationException e) {
1355: }
1356:
1357: workflowManager.getPoolManager().addUsersToPool(
1358: pool.getId(), longList(authTestUser.getId()));
1359: // now this should succeed
1360: authTestWfManager.getProcess(processInstance.getId(),
1361: Locale.US);
1362: // take away pool membership again
1363: workflowManager.getPoolManager().removeUsersFromPool(
1364: pool.getId(), longList(authTestUser.getId()));
1365:
1366: // Associate process with a document
1367: Document document = repository.createDocument(
1368: "A test document", "TestDocType");
1369: document.save();
1370:
1371: TaskUpdateData taskUpdateData = new TaskUpdateData();
1372: taskUpdateData.setVariable("daisy_document",
1373: VariableScope.GLOBAL, WfValueType.DAISY_LINK,
1374: WfVersionKey.get(document, null));
1375: String taskId = processInstance.getTask("test-task")
1376: .getId();
1377: workflowManager.updateTask(taskId, taskUpdateData,
1378: Locale.US);
1379:
1380: // now should succeed again because process instance is associated with a document the user can read
1381: authTestWfManager.getProcess(processInstance.getId(),
1382: Locale.US);
1383:
1384: // update document so user can't read it anymore
1385: document.setPrivate(true);
1386: document.save();
1387:
1388: try {
1389: authTestWfManager.getProcess(processInstance.getId(),
1390: Locale.US);
1391: fail("User should not be able to access process instance.");
1392: } catch (WfAuthorizationException e) {
1393: }
1394:
1395: // add user back to the pool and test filtering of task lists
1396: workflowManager.getPoolManager().addUsersToPool(
1397: pool.getId(), longList(authTestUser.getId()));
1398: assertEquals(0, authTestWfManager.getPooledTasks(Locale.US)
1399: .size());
1400:
1401: // test direct task access
1402: try {
1403: authTestWfManager.getTask(taskId, Locale.US);
1404: fail("User should not be able to access task instance.");
1405: } catch (WfAuthorizationException e) {
1406: }
1407:
1408: // test direct task access
1409: try {
1410: authTestWfManager.requestPooledTask(taskId, Locale.US);
1411: fail("User should not be able to request pooled task.");
1412: } catch (WfAuthorizationException e) {
1413: }
1414:
1415: // make doc non-private, should make task accessible to the user
1416: document.setPrivate(false);
1417: document.save();
1418:
1419: // test direct task access
1420: authTestWfManager.getTask(taskId, Locale.US);
1421:
1422: // test pool-list access
1423: assertEquals(1, authTestWfManager.getPooledTasks(Locale.US)
1424: .size());
1425:
1426: // test requesting pooled task
1427: authTestWfManager.requestPooledTask(taskId, Locale.US);
1428: authTestWfManager.getTask(taskId, Locale.US);
1429:
1430: // Once the user is assigned to the task, he should be able to access task and process even if he
1431: // can't read the associated document
1432: document.setPrivate(true);
1433: document.save();
1434: authTestWfManager.getTask(taskId, Locale.US);
1435: authTestWfManager.getProcess(processInstance.getId(),
1436: Locale.US);
1437: }
1438:
1439: //
1440: // Some timer tests
1441: //
1442: {
1443: String workflow = "<process-definition name='test-timers'>"
1444: + " <swimlane name='initiator'/>"
1445: + " <start-state name='start'>"
1446: + " <task name='start-task' swimlane='initiator'/>"
1447: + " <transition name='trans1' to='s'/>"
1448: + " </start-state>"
1449: + " <state name='s'>"
1450: + " <event type='node-enter'>"
1451: + " <create-timer name='my-timer' duedate='1000 days'>"
1452: + " </create-timer>" + " </event>"
1453: + " <transition name='trans2' to='end'/>"
1454: + " </state>" + " <end-state name='end'/>"
1455: + "</process-definition>";
1456:
1457: WfProcessDefinition processDef = workflowManager
1458: .deployProcessDefinition(new ByteArrayInputStream(
1459: workflow.getBytes()), "text/xml", locale);
1460:
1461: // start two processes, hence two timers
1462: workflowManager.startProcess(processDef.getId(),
1463: new TaskUpdateData(), "trans1", Locale.US);
1464: workflowManager.startProcess(processDef.getId(),
1465: new TaskUpdateData(), "trans1", Locale.US);
1466:
1467: // test getTimer and getXml
1468: workflowManager.getTimer("1", Locale.US).getXml();
1469:
1470: // test querying
1471: QueryConditions conditions = new QueryConditions();
1472: conditions.addCondition("timer.suspended",
1473: WfValueType.BOOLEAN, "eq", false);
1474: conditions.addCondition("timer.name", WfValueType.STRING,
1475: "eq", "my-timer");
1476:
1477: List<QueryOrderByItem> orderByItems = new ArrayList<QueryOrderByItem>();
1478: orderByItems.add(new QueryOrderByItem("timer.id",
1479: QueryValueSource.PROPERTY, SortOrder.DESCENDING));
1480: List<WfTimer> timers = workflowManager.getTimers(
1481: conditions, orderByItems, -1, -1, Locale.US);
1482: assertEquals(2, timers.size());
1483:
1484: List<QuerySelectItem> querySelectItems = new ArrayList<QuerySelectItem>();
1485: querySelectItems.add(new QuerySelectItem("timer.id",
1486: QueryValueSource.PROPERTY));
1487: querySelectItems.add(new QuerySelectItem("timer.name",
1488: QueryValueSource.PROPERTY));
1489: querySelectItems.add(new QuerySelectItem("timer.dueDate",
1490: QueryValueSource.PROPERTY));
1491: querySelectItems.add(new QuerySelectItem("process.id",
1492: QueryValueSource.PROPERTY));
1493: querySelectItems.add(new QuerySelectItem("timer.suspended",
1494: QueryValueSource.PROPERTY));
1495: querySelectItems.add(new QuerySelectItem("timer.failed",
1496: QueryValueSource.PROPERTY));
1497: SearchResultDocument result = workflowManager.searchTimers(
1498: querySelectItems, conditions, orderByItems, -1, -1,
1499: Locale.US);
1500: assertEquals(2, result.getSearchResult().getRows()
1501: .getRowArray().length);
1502: }
1503:
1504: //
1505: // Test un-assign and re-assign
1506: //
1507: {
1508: WfPoolManager poolManager = workflowManager
1509: .getPoolManager();
1510: WfPool pool = poolManager
1511: .createPool("Assing reassign test pool");
1512: pool.save();
1513: poolManager.addUsersToPool(pool.getId(), longList(dummyUser
1514: .getId()));
1515:
1516: String workflow = "<process-definition name='testTaskAssignment'>"
1517: + " <swimlane name='initiator'/>"
1518: + " <swimlane name='lane2'>"
1519: + " <assignment pooled-actors='"
1520: + pool.getId()
1521: + "'/>"
1522: + " </swimlane>"
1523: + " <start-state name='start'>"
1524: + " <task name='start-task' swimlane='initiator'/>"
1525: + " <transition name='trans1' to='s'/>"
1526: + " </start-state>"
1527: + " <task-node name='s'>"
1528: + " <task name='test-task'>"
1529: + " <assignment pooled-actors='"
1530: + pool.getId()
1531: + "'/>"
1532: + " </task>"
1533: + " <transition name='trans2' to='s2'/>"
1534: + " </task-node>"
1535: + " <task-node name='s2'>"
1536: + " <task name='test-task2'>"
1537: + " <assignment actor-id='"
1538: + dummyUser.getId()
1539: + "'/>"
1540: + " </task>"
1541: + " <transition name='trans3' to='s3'/>"
1542: + " </task-node>"
1543: + " <task-node name='s3'>"
1544: + " <task name='test-task3' swimlane='lane2'>"
1545: + " </task>"
1546: + " <transition name='trans4' to='s4'/>"
1547: + " </task-node>"
1548: + " <task-node name='s4'>"
1549: + " <task name='test-task4' swimlane='lane2'>"
1550: + " </task>"
1551: + " <transition name='trans4' to='end'/>"
1552: + " </task-node>"
1553: + " <end-state name='end'/>"
1554: + "</process-definition>";
1555:
1556: WfProcessDefinition processDef = workflowManager
1557: .deployProcessDefinition(new ByteArrayInputStream(
1558: workflow.getBytes()), "text/xml", locale);
1559:
1560: TaskUpdateData taskUpdateData = new TaskUpdateData();
1561: WfProcessInstance process = workflowManager.startProcess(
1562: processDef.getId(), taskUpdateData, null, locale);
1563:
1564: // dummy user requests task
1565: WfTask task = process.getTask("test-task");
1566: dummyWfManager.requestPooledTask(task.getId(), locale);
1567:
1568: // dummy user unassigns himself from the task
1569: task = dummyWfManager.unassignTask(task.getId(), locale);
1570: assertEquals(-1, task.getActorId());
1571:
1572: // testuser requests tasks, dummy user tries to unassign it but should not be allowed to do that
1573: workflowManager.requestPooledTask(task.getId(), locale);
1574: try {
1575: dummyWfManager.unassignTask(task.getId(), locale);
1576: fail("An ordinary user shouldn't be able to unassign the task of someone else.");
1577: } catch (WorkflowException e) {
1578: }
1579:
1580: // re-assign task to dummy user
1581: task = workflowManager.assignTask(task.getId(),
1582: new WfActorKey(dummyUser.getId()), false, locale);
1583: assertEquals(dummyUser.getId(), task.getActorId());
1584:
1585: // once more unassign it
1586: dummyWfManager.unassignTask(task.getId(), locale);
1587:
1588: // transition to next task
1589: task = workflowManager.assignTask(task.getId(),
1590: new WfActorKey(repository.getUserId()), false,
1591: locale);
1592: workflowManager.endTask(task.getId(), new TaskUpdateData(),
1593: null, locale);
1594:
1595: // test un-assigning when there are no pools to fall back to
1596: process = workflowManager.getProcess(process.getId(),
1597: locale);
1598: WfTask task2 = process.getTask("test-task2");
1599: try {
1600: dummyWfManager.unassignTask(task2.getId(), locale);
1601: fail("Unassignment should fail since there are no pools to fall back too.");
1602: } catch (WorkflowException e) {
1603: }
1604:
1605: // re-assign task2 to a pool, let the dummy request it and unassing himself from it, now this should work
1606: // since there is a pool to fall back too.
1607: task2 = workflowManager.assignTask(task2.getId(),
1608: new WfActorKey(longList(pool.getId())), false,
1609: locale);
1610: dummyWfManager.requestPooledTask(task2.getId(), locale);
1611: dummyWfManager.unassignTask(task2.getId(), locale);
1612:
1613: // move to next task
1614: task2 = workflowManager.endTask(task2.getId(),
1615: new TaskUpdateData(), null, locale);
1616:
1617: // Re-assigning task3 with overwrite of swimlane should make that task4, assigned to the same swimlane,
1618: // also becomes assigned to the same user.
1619: process = workflowManager.getProcess(process.getId(),
1620: locale);
1621: WfTask task3 = process.getTask("test-task3");
1622: workflowManager.assignTask(task3.getId(), new WfActorKey(
1623: dummyUser.getId()), true, locale);
1624: dummyWfManager.endTask(task3.getId(), new TaskUpdateData(),
1625: null, locale);
1626:
1627: process = workflowManager.getProcess(process.getId(),
1628: locale);
1629: WfTask task4 = process.getTask("test-task4");
1630: assertEquals(dummyUser.getId(), task4.getActorId());
1631: }
1632: }
1633:
1634: private List<Long> longList(long... ids) {
1635: List<Long> list = new ArrayList<Long>(ids.length);
1636: for (long id : ids) {
1637: list.add(id);
1638: }
1639: return list;
1640: }
1641:
1642: private Date getDate(Date date, boolean keepTime) {
1643: Calendar calendar = new GregorianCalendar();
1644: calendar.setTime(date);
1645: if (!keepTime) {
1646: calendar.set(Calendar.HOUR_OF_DAY, 0);
1647: calendar.set(Calendar.MINUTE, 0);
1648: calendar.set(Calendar.SECOND, 0);
1649: }
1650: calendar.set(Calendar.MILLISECOND, 0);
1651: return calendar.getTime();
1652: }
1653:
1654: private InputStream buildWorkflowArchive(String processDefinition,
1655: String processMeta, Map<String, byte[]> bundles)
1656: throws IOException {
1657: Map<String, byte[]> entries = new HashMap<String, byte[]>();
1658: entries.put("processdefinition.xml", processDefinition
1659: .getBytes("UTF-8"));
1660: entries.put("daisy-process-meta.xml", processMeta
1661: .getBytes("UTF-8"));
1662:
1663: if (bundles != null) {
1664: for (Map.Entry<String, byte[]> bundle : bundles.entrySet()) {
1665: entries.put(bundle.getKey(), bundle.getValue());
1666: }
1667: }
1668:
1669: byte[] zipData = buildZip(entries);
1670: return new ByteArrayInputStream(zipData);
1671: }
1672:
1673: private byte[] buildZip(Map<String, byte[]> byteArrays)
1674: throws IOException {
1675: ByteArrayOutputStream bos = new ByteArrayOutputStream();
1676: ZipOutputStream zos = new ZipOutputStream(bos);
1677:
1678: for (Map.Entry<String, byte[]> entry : byteArrays.entrySet()) {
1679: zos.putNextEntry(new ZipEntry(entry.getKey()));
1680: zos.write(entry.getValue());
1681: zos.closeEntry();
1682: }
1683:
1684: zos.close();
1685:
1686: return bos.toByteArray();
1687: }
1688:
1689: String readResource(String name) throws Exception {
1690: InputStream is = getClass().getClassLoader()
1691: .getResourceAsStream(
1692: "org/outerj/daisy/repository/test/resources/"
1693: + name);
1694: Reader reader = new InputStreamReader(is, "UTF-8");
1695: BufferedReader bufferedReader = new BufferedReader(reader);
1696:
1697: StringBuilder buffer = new StringBuilder();
1698: int c = bufferedReader.read();
1699: while (c != -1) {
1700: buffer.append((char) c);
1701: c = bufferedReader.read();
1702: }
1703:
1704: return buffer.toString();
1705: }
1706:
1707: byte[] readResourceBytes(String name) throws Exception {
1708: InputStream is = getClass().getClassLoader()
1709: .getResourceAsStream(
1710: "org/outerj/daisy/repository/test/resources/"
1711: + name);
1712: ByteArrayOutputStream bos = new ByteArrayOutputStream();
1713:
1714: byte[] buffer = new byte[8192];
1715: int read;
1716: while ((read = is.read(buffer)) != -1) {
1717: bos.write(buffer, 0, read);
1718: }
1719:
1720: return bos.toByteArray();
1721: }
1722: }
|