From 46d8689bed8ba0900daec186189a2f9044eefccd Mon Sep 17 00:00:00 2001 From: Laramie Crocker Date: Wed, 16 Mar 2011 23:38:31 +0000 Subject: [PATCH] CSPACE-3560 Added imports service; moved Tools.java from module common to common-api; added other utility classes to common-api --- .../xmlreplay/PayloadLogger.java | 2 +- .../xmlreplay/ServiceResult.java | 73 +++- .../xmlreplay/TreeWalkResults.java | 3 +- .../xmlreplay/XmlCompareJdom.java | 9 +- .../IntegrationTests/xmlreplay/XmlReplay.java | 176 ++++++-- .../xmlreplay/XmlReplayEval.java | 21 +- .../xmlreplay/XmlReplayTest.java | 2 +- .../xmlreplay/XmlReplayTransport.java | 110 +++-- .../test/XmlReplayDevTest.java | 87 +++- .../test-data/xmlreplay/dev-master.xml | 16 +- .../objectexit/object-exit-display.xml | 51 +++ .../test-data/xmlreplay/objectexit/oe1.xml | 1 - .../test-data/xmlreplay/objectexit/oe24.xml | 0 .../xmlreplay/objectexit/oeObject.xml | 9 + .../xmlreplay/objectexit/oePerson.xml | 0 .../objectexit/oePersonDisplayOnly.xml | 11 + .../objectexit/oePersonauthority.xml | 12 + .../xmlreplay/objectexit/res/oe2.res.xml | 2 + .../objectexit/res/oePersonGET.res.xml | 2 + .../res/oePersonauthorityGET.res.xml | 0 services/common-api/pom.xml | 1 + .../services/common/api/FileTools.java | 124 ++++++ .../services/common/api/RefName.java | 33 +- .../services/common/api}/Tools.java | 35 +- .../services/common/api/ZipTools.java | 156 +++++++ services/common/pom.xml | 5 + .../services/common/FileUtils.java | 32 +- .../services/common/IFragmentHandler.java | 56 +++ .../services/common/ReflectionMapper.java | 2 + .../services/common/ResourceBase.java | 43 +- .../services/common/XmlSaxFragmenter.java | 333 ++++++++++++++ .../services/common/init/AddIndices.java | 2 +- .../services/common/storage/JDBCTools.java | 2 +- .../nuxeo/client/java/DocHandlerBase.java | 2 +- .../test-data/XmlSaxFragmenter-sample.xml | 14 + services/imports/.project | 17 + services/imports/3rdparty/.project | 17 + .../.settings/org.maven.ide.eclipse.prefs | 9 + services/imports/3rdparty/build.xml | 127 ++++++ .../nuxeo-platform-cs-imports/.classpath | 8 + .../nuxeo-platform-cs-imports/.project | 17 + .../.settings/org.maven.ide.eclipse.prefs | 9 + .../nuxeo-platform-cs-imports/build.xml | 143 ++++++ .../nuxeo-platform-cs-imports/pom.xml | 38 ++ .../src/main/resources/META-INF/MANIFEST.MF | 22 + .../resources/OSGI-INF/core-types-contrib.xml | 15 + .../OSGI-INF/deployment-fragment.xml | 408 ++++++++++++++++++ .../resources/OSGI-INF/ecm-types-contrib.xml | 29 ++ .../resources/OSGI-INF/layouts-contrib.xml | 212 +++++++++ .../main/resources/schemas/imports_common.xsd | 18 + services/imports/3rdparty/pom.xml | 24 ++ services/imports/build.xml | 124 ++++++ services/imports/jaxb/.classpath | 31 ++ services/imports/jaxb/.project | 19 + .../.settings/org.maven.ide.eclipse.prefs | 9 + services/imports/jaxb/pom.xml | 47 ++ .../services/ImportsJAXBSchema.java | 16 + .../services/ImportsListItemJAXBSchema.java | 9 + .../src/main/resources/imports_common.xsd | 56 +++ services/imports/pom.xml | 23 + services/imports/service/.classpath | 313 ++++++++++++++ services/imports/service/.classpath~ | 315 ++++++++++++++ services/imports/service/.project | 28 ++ services/imports/service/.project~ | 30 ++ .../.settings/org.maven.ide.eclipse.prefs | 9 + services/imports/service/pom.xml | 125 ++++++ services/imports/service/profiles.xml | 4 + .../services/imports/ImportsResource.java | 227 ++++++++++ .../services/imports/ImportsResource.java~ | 59 +++ .../services/imports/TemplateExpander.java | 165 +++++++ .../services/imports/nuxeo/ImportCommand.java | 56 +++ .../nuxeo/ImportsDocumentModelHandler.java | 32 ++ .../nuxeo/LoggedXMLDirectoryReader.java | 134 ++++++ .../authority-request-naturalhistory.xml | 27 ++ .../main/resources/templates/authority.xml | 51 +++ .../src/main/resources/templates/person.xml | 51 +++ .../templates/personauthorities-part.xml | 7 + .../personauthorities-workspace-document.xml | 65 +++ .../resources/templates/service-document.xml | 45 ++ .../templates/workspace-document.xml | 65 +++ .../services/test/ImportsServiceTest.java | 65 +++ .../service/src/test/resources/log4j.xml | 45 ++ .../resources/requests/authority-request.xml | 20 + .../requests/collectionobject-request.xml | 282 ++++++++++++ .../person/nuxeo/PersonValidatorHandler.java | 2 +- services/pom.xml | 1 + 86 files changed, 4981 insertions(+), 116 deletions(-) create mode 100755 services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/object-exit-display.xml create mode 100755 services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oe24.xml create mode 100755 services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oeObject.xml create mode 100755 services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oePerson.xml create mode 100755 services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oePersonDisplayOnly.xml create mode 100755 services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oePersonauthority.xml create mode 100755 services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oePersonGET.res.xml create mode 100755 services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oePersonauthorityGET.res.xml create mode 100755 services/common-api/src/main/java/org/collectionspace/services/common/api/FileTools.java rename services/{common/src/main/java/org/collectionspace/services/common => common-api/src/main/java/org/collectionspace/services/common/api}/Tools.java (78%) create mode 100755 services/common-api/src/main/java/org/collectionspace/services/common/api/ZipTools.java create mode 100755 services/common/src/main/java/org/collectionspace/services/common/IFragmentHandler.java create mode 100755 services/common/src/main/java/org/collectionspace/services/common/XmlSaxFragmenter.java create mode 100755 services/common/src/test/resources/test-data/XmlSaxFragmenter-sample.xml create mode 100755 services/imports/.project create mode 100755 services/imports/3rdparty/.project create mode 100644 services/imports/3rdparty/.settings/org.maven.ide.eclipse.prefs create mode 100755 services/imports/3rdparty/build.xml create mode 100644 services/imports/3rdparty/nuxeo-platform-cs-imports/.classpath create mode 100755 services/imports/3rdparty/nuxeo-platform-cs-imports/.project create mode 100644 services/imports/3rdparty/nuxeo-platform-cs-imports/.settings/org.maven.ide.eclipse.prefs create mode 100755 services/imports/3rdparty/nuxeo-platform-cs-imports/build.xml create mode 100755 services/imports/3rdparty/nuxeo-platform-cs-imports/pom.xml create mode 100755 services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/META-INF/MANIFEST.MF create mode 100755 services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/OSGI-INF/core-types-contrib.xml create mode 100644 services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/OSGI-INF/deployment-fragment.xml create mode 100755 services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/OSGI-INF/ecm-types-contrib.xml create mode 100755 services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/OSGI-INF/layouts-contrib.xml create mode 100755 services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/schemas/imports_common.xsd create mode 100755 services/imports/3rdparty/pom.xml create mode 100755 services/imports/build.xml create mode 100644 services/imports/jaxb/.classpath create mode 100755 services/imports/jaxb/.project create mode 100644 services/imports/jaxb/.settings/org.maven.ide.eclipse.prefs create mode 100755 services/imports/jaxb/pom.xml create mode 100755 services/imports/jaxb/src/main/java/org/collectionspace/services/ImportsJAXBSchema.java create mode 100755 services/imports/jaxb/src/main/java/org/collectionspace/services/ImportsListItemJAXBSchema.java create mode 100755 services/imports/jaxb/src/main/resources/imports_common.xsd create mode 100755 services/imports/pom.xml create mode 100755 services/imports/service/.classpath create mode 100755 services/imports/service/.classpath~ create mode 100755 services/imports/service/.project create mode 100755 services/imports/service/.project~ create mode 100644 services/imports/service/.settings/org.maven.ide.eclipse.prefs create mode 100755 services/imports/service/pom.xml create mode 100644 services/imports/service/profiles.xml create mode 100755 services/imports/service/src/main/java/org/collectionspace/services/imports/ImportsResource.java create mode 100755 services/imports/service/src/main/java/org/collectionspace/services/imports/ImportsResource.java~ create mode 100755 services/imports/service/src/main/java/org/collectionspace/services/imports/TemplateExpander.java create mode 100755 services/imports/service/src/main/java/org/collectionspace/services/imports/nuxeo/ImportCommand.java create mode 100755 services/imports/service/src/main/java/org/collectionspace/services/imports/nuxeo/ImportsDocumentModelHandler.java create mode 100755 services/imports/service/src/main/java/org/collectionspace/services/imports/nuxeo/LoggedXMLDirectoryReader.java create mode 100755 services/imports/service/src/main/resources/templates/authority-request-naturalhistory.xml create mode 100755 services/imports/service/src/main/resources/templates/authority.xml create mode 100755 services/imports/service/src/main/resources/templates/person.xml create mode 100755 services/imports/service/src/main/resources/templates/personauthorities-part.xml create mode 100755 services/imports/service/src/main/resources/templates/personauthorities-workspace-document.xml create mode 100755 services/imports/service/src/main/resources/templates/service-document.xml create mode 100755 services/imports/service/src/main/resources/templates/workspace-document.xml create mode 100755 services/imports/service/src/test/java/org/collectionspace/services/test/ImportsServiceTest.java create mode 100644 services/imports/service/src/test/resources/log4j.xml create mode 100755 services/imports/service/src/test/resources/requests/authority-request.xml create mode 100755 services/imports/service/src/test/resources/requests/collectionobject-request.xml diff --git a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/PayloadLogger.java b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/PayloadLogger.java index 8913f51f0..905abb1a6 100755 --- a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/PayloadLogger.java +++ b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/PayloadLogger.java @@ -23,7 +23,7 @@ package org.collectionspace.services.IntegrationTests.xmlreplay; -import org.collectionspace.services.common.Tools; +import org.collectionspace.services.common.api.Tools; import java.io.*; import java.util.ArrayList; diff --git a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/ServiceResult.java b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/ServiceResult.java index fd2ce06e7..71b1bf5e1 100755 --- a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/ServiceResult.java +++ b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/ServiceResult.java @@ -24,7 +24,7 @@ package org.collectionspace.services.IntegrationTests.xmlreplay; import org.apache.commons.httpclient.Header; -import org.collectionspace.services.common.Tools; +import org.collectionspace.services.common.api.Tools; import java.util.ArrayList; import java.util.HashMap; @@ -44,7 +44,8 @@ public class ServiceResult { public String location = ""; public String CSID = ""; public String subresourceCSID = ""; - public String requestPayload = ""; + public String requestPayload = ""; //just like requestPayloadRaw, but may have multipart boundary and headers. + public Map requestPayloadsRaw = new HashMap(); public String result = ""; public int responseCode = 0; public String responseMessage = ""; @@ -121,16 +122,22 @@ public class ServiceResult { } break; case TEXT: + if (value.countFor(TreeWalkResults.TreeWalkEntry.STATUS.TEXT_DIFFERENT)>0) { + failureReason = " : DOM TEXT_DIFFERENT; "; + return false; + } + break; + case TREE: if (!value.treesMatch()) { failureReason = " : DOM TREE MISMATCH; "; return false; } + break; + case TREE_TEXT: if (value.countFor(TreeWalkResults.TreeWalkEntry.STATUS.TEXT_DIFFERENT)>0) { failureReason = " : DOM TEXT_DIFFERENT; "; return false; } - break; - case TREE: if (!value.treesMatch()) { failureReason = " : DOM TREE MISMATCH; "; return false; @@ -143,7 +150,20 @@ public class ServiceResult { return true; } + private boolean overrideExpectedResult = false; + + /** Call this method to create a ServiceResult mock object, for when you are doing autoDelete, and you come + * across a GET : GETs don't have a DELETE url, so they don't need to be autoDeleted, so an empty ServiceResult object + * signifies this. + */ + public void overrideGotExpectedResult(){ + overrideExpectedResult = true; + } + public boolean gotExpectedResult(){ + if (overrideExpectedResult){ + return true; + } if (Tools.notEmpty(failureReason)){ return false; } @@ -170,12 +190,16 @@ public class ServiceResult { //public static final String[] DUMP_OPTIONS = {"minimal", "detailed", "full"}; public static enum DUMP_OPTIONS {minimal, detailed, full}; - public static enum PAYLOAD_STRICTNESS {ZERO, ADDOK, TREE, TEXT, STRICT}; + public static enum PAYLOAD_STRICTNESS {ZERO, ADDOK, TREE, TEXT, TREE_TEXT, STRICT}; public String toString(){ return detail(true); } + + private static final String LINE = "\r\n=================================="; + private static final String CRLF = "\r\n"; + public String detail(boolean includePayloads){ String res = "{" + ( gotExpectedResult() ? "SUCCESS" : "FAILURE" ) @@ -193,12 +217,13 @@ public class ServiceResult { + ( Tools.notEmpty(location) ? "; location.CSID:"+location : "" ) + ( Tools.notEmpty(error) ? "; ERROR:"+error : "" ) + "; gotExpected:"+gotExpectedResult() - + ( includePayloads && Tools.notEmpty(requestPayload) ? "; requestPayload:\r\n"+requestPayload+"\r\n" : "" ) - + ( includePayloads && Tools.notEmpty(result) ? "; result:"+result : "" ) + ( partsSummary(true)) - +"}"; + +"}" + + ( includePayloads && Tools.notBlank(requestPayload) ? LINE+"requestPayload:"+LINE+CRLF+requestPayload+LINE : "" ) + + ( includePayloads && Tools.notBlank(result) ? LINE+"result:"+LINE+CRLF+result : "" ); return res; } + public String minimal(){ return "{" + ( gotExpectedResult() ? "SUCCESS" : "FAILURE" ) @@ -226,4 +251,36 @@ public class ServiceResult { return toString(); } } + + /** This method may be called from a test case, using a syntax like ${testID3.resValue("persons_common", "//refName")} */ + public String got(String partName, String xpath) throws Exception { + try { + PayloadLogger.HttpTraffic traffic = PayloadLogger.readPayloads(this.result, this.boundary, this.contentLength); + PayloadLogger.Part partFromServer = traffic.getPart(partName); + String source = partFromServer.getContent(); + org.jdom.Element element = (org.jdom.Element) XmlCompareJdom.selectSingleNode(source, xpath); + String sr = element != null ? element.getText() : ""; + return sr; + } catch (Exception e){ + return "ERROR reading response value: "+e; + } + } + + /** This method may be called from a test case, using a syntax like ${oe9.reqValue("personauthorities_common","//shortIdentifier")} */ + public String sent(String partName, String xpath) throws Exception { + try { + if (Tools.isEmpty(partName)){ + partName = "default"; + } + String source = this.requestPayloadsRaw.get(partName); + if (source == null){ + return "ERROR:null:requestPayloadsRaw["+partName+"]"; + } + org.jdom.Element element = (org.jdom.Element) XmlCompareJdom.selectSingleNode(source, xpath); //e.g. "//shortIdentifier"); + String sr = element != null ? element.getText() : ""; + return sr; + } catch (Exception e){ + return "ERROR reading request value: "+e; + } + } } diff --git a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/TreeWalkResults.java b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/TreeWalkResults.java index db4706fc5..0d24a169f 100755 --- a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/TreeWalkResults.java +++ b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/TreeWalkResults.java @@ -23,7 +23,7 @@ package org.collectionspace.services.IntegrationTests.xmlreplay; -import org.collectionspace.services.common.Tools; +import org.collectionspace.services.common.api.Tools; import java.util.ArrayList; @@ -50,6 +50,7 @@ public class TreeWalkResults extends ArrayList { +(Tools.notEmpty(lpath) ? ", L.path:"+lpath : "") +(Tools.notEmpty(rpath) ? ", R.path:"+rpath : "") +(Tools.notEmpty(message) ? ", message:"+message : "") + +(Tools.notEmpty(errmessage) ? ", errmessage:"+errmessage : "") +((status != STATUS.MATCHED) && Tools.notEmpty(ltextTrimmed) ? ",\r\n L.trimmed:"+ltextTrimmed : "") +((status != STATUS.MATCHED) && Tools.notEmpty(rtextTrimmed) ? ",\r\n R.trimmed:"+rtextTrimmed : "") +"}"; diff --git a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlCompareJdom.java b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlCompareJdom.java index 7d2672bca..837b605f3 100755 --- a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlCompareJdom.java +++ b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlCompareJdom.java @@ -22,7 +22,7 @@ */ package org.collectionspace.services.IntegrationTests.xmlreplay; -import org.collectionspace.services.common.Tools; +import org.collectionspace.services.common.api.Tools; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; @@ -105,7 +105,12 @@ private static final String DEFAULT_SAX_DRIVER_CLASS = "org.apache.xerces.parser return xpath.selectSingleNode(element); } - + public static Object selectSingleNode(String docSource, String xpathExpression) throws Exception { + Document doc = getDocumentFromContent(docSource); + Element element = doc.getRootElement(); + XPath xpath = new JDOMXPath(xpathExpression); + return xpath.selectSingleNode(element); + } public static boolean treeWalk(Document left, Document right, TreeWalkResults list) throws Exception { diff --git a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplay.java b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplay.java index 2b87806cb..89807bf87 100755 --- a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplay.java +++ b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplay.java @@ -6,7 +6,7 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.jexl2.JexlContext; import org.apache.commons.jexl2.JexlEngine; import org.apache.commons.jexl2.MapContext; -import org.collectionspace.services.common.Tools; +import org.collectionspace.services.common.api.Tools; import org.dom4j.*; import org.dom4j.io.SAXReader; @@ -147,7 +147,7 @@ public class XmlReplay { return list; } - /** Use this if you wish to named tests within a testGroup, otherwise call runTestGroup(). */ + /** Use this if you wish to run named tests within a testGroup, otherwise call runTestGroup(). */ public List runTests(String testGroupID, String testID) throws Exception { List result = runXmlReplayFile(this.basedir, this.controlFileName, @@ -198,8 +198,17 @@ public class XmlReplay { List results = new ArrayList(); for (ServiceResult pr : serviceResultsMap.values()){ try { - ServiceResult deleteResult = XmlReplayTransport.doDELETE(pr.deleteURL, pr.auth, pr.testID, "[autodelete:"+logName+"]"); - results.add(deleteResult); + if (Tools.notEmpty(pr.deleteURL)){ + ServiceResult deleteResult = XmlReplayTransport.doDELETE(pr.deleteURL, pr.auth, pr.testID, "[autodelete:"+logName+"]"); + results.add(deleteResult); + } else { + ServiceResult errorResult = new ServiceResult(); + errorResult.fullURL = pr.fullURL; + errorResult.testGroupID = pr.testGroupID; + errorResult.fromTestID = pr.fromTestID; + errorResult.overrideGotExpectedResult(); + results.add(errorResult); + } } catch (Throwable t){ String s = (pr!=null) ? "ERROR while cleaning up ServiceResult map: "+pr+" for "+pr.deleteURL+" :: "+t : "ERROR while cleaning up ServiceResult map (null ServiceResult): "+t; @@ -272,47 +281,86 @@ public class XmlReplay { private static class PartsStruct { public List partsList = new ArrayList(); public List filesList = new ArrayList(); + public List fromTests = new ArrayList(); + public List> varsList = new ArrayList>(); boolean bDoingSinglePartPayload = false; String singlePartPayloadFilename = ""; String overrideTestID = ""; public static PartsStruct readParts(Node testNode, final String testID, String xmlReplayBaseDir){ - PartsStruct result = new PartsStruct(); - result.singlePartPayloadFilename = testNode.valueOf("filename"); + PartsStruct resultPartsStruct = new PartsStruct(); + resultPartsStruct.singlePartPayloadFilename = testNode.valueOf("filename"); String singlePartPayloadFilename = testNode.valueOf("filename"); if (Tools.notEmpty(singlePartPayloadFilename)){ - result.bDoingSinglePartPayload = true; - result.singlePartPayloadFilename = xmlReplayBaseDir + '/' + singlePartPayloadFilename; + resultPartsStruct.bDoingSinglePartPayload = true; + resultPartsStruct.singlePartPayloadFilename = xmlReplayBaseDir + '/' + singlePartPayloadFilename; + List varNodes = testNode.selectNodes("vars/var"); + readVars(testNode, varNodes, resultPartsStruct); } else { - result.bDoingSinglePartPayload = false; + resultPartsStruct.bDoingSinglePartPayload = false; List parts = testNode.selectNodes("parts/part"); if (parts == null || parts.size()==0){ //path is just /testGroup/test/part/ - String commonPartName = testNode.valueOf("part/label"); - String testfile = testNode.valueOf("part/filename"); - String fullTestFilename = xmlReplayBaseDir + '/' + testfile; - if ( Tools.isEmpty(testID) ){ - result.overrideTestID = testfile; //It is legal to have a missing ID attribute, and rely on a unique filename. - } - result.partsList.add(commonPartName); - result.filesList.add(fullTestFilename); + Node part = testNode.selectSingleNode("part"); + readPart(testNode, part, xmlReplayBaseDir, testID, resultPartsStruct); //side-effect: adds objects to result. } else { // path is /testGroup/test/parts/part/ for (Node part : parts){ - String commonPartName = part.valueOf("label"); - String filename = part.valueOf("filename"); - String fullTestFilename = xmlReplayBaseDir + '/' + filename; - if ( Tools.isEmpty(testID) ){ //if testID is empty, we'll use the *first* filename as ID. - result.overrideTestID = filename; //It is legal to have a missing ID attribute, and rely on a unique filename. - } - result.partsList.add(commonPartName); - result.filesList.add(fullTestFilename); + readPart(testNode, part, xmlReplayBaseDir, testID, resultPartsStruct); //side-effect: adds objects to result. } } } - return result; + return resultPartsStruct; + } + private static void readPart(Node testNode, Node part, String xmlReplayBaseDir, String testID, PartsStruct resultPartsStruct){ + String commonPartName = part.valueOf("label"); + String filename = part.valueOf("filename"); + String fullTestFilename = xmlReplayBaseDir + '/' + filename; + if ( Tools.isEmpty(testID) ){ //if testID is empty, we'll use the *first* filename as ID. + resultPartsStruct.overrideTestID = filename; //It is legal to have a missing ID attribute, and rely on a unique filename. + } + String fromTest = part.valueOf("fromTest"); + if (fromTest == null){ + fromTest = ""; + } + + //These next foun members (partsList,filesList,varsList, and fromTests), + // should be added in lock-step, since they are assumed to exist by index (0,1,2,3, etc.) + resultPartsStruct.partsList.add(commonPartName); + resultPartsStruct.filesList.add(fullTestFilename); + resultPartsStruct.fromTests.add(fromTest); + + List varNodes = part.selectNodes("var"); + readVars(testNode, varNodes, resultPartsStruct); + /* Map vars = new HashMap(); + resultPartsStruct.varsList.add(vars); + + List varNodes = part.selectNodes("var"); + //System.out.println("### vars: "+vars.size()+" ########"); + for (Node var: varNodes){ + String ID = var.valueOf("@ID"); + String value = var.getText(); + //System.out.println("ID: "+ID+" value: "+value); + vars.put(ID, value); //vars is already part of resultPartsStruct.varsList + } + //System.out.println("### end-vars ########"); + */ + } + private static void readVars(Node testNode, List varNodes, PartsStruct resultPartsStruct){ + Map vars = new HashMap(); + resultPartsStruct.varsList.add(vars); + //System.out.println("### vars: "+vars.size()+" ########"); + for (Node var: varNodes){ + String ID = var.valueOf("@ID"); + String value = var.getText(); + //System.out.println("ID: "+ID+" value: "+value); + vars.put(ID, value); //vars is already part of resultPartsStruct.varsList + } + //System.out.println("### end-vars ########"); } } + + private static String fixupFullURL(String fullURL, String protoHostPort, String uri){ if ( ! uri.startsWith(protoHostPort)){ fullURL = Tools.glue(protoHostPort, "/", uri); @@ -364,7 +412,8 @@ public class XmlReplay { String OK = ""; byte[] b = FileUtils.readFileToByteArray(new File(expectedResponseParts.singlePartPayloadFilename)); String expectedPartContent = new String(b); - expectedPartContent = evalStruct.eval(expectedPartContent, serviceResultsMap, evalStruct.jexl, evalStruct.jc); + Map vars = expectedResponseParts.varsList.get(0); //just one part, so just one varsList. Must be there, even if empty. + expectedPartContent = evalStruct.eval(expectedPartContent, serviceResultsMap, vars, evalStruct.jexl, evalStruct.jc); String label = "NOLABEL"; String leftID = "{from expected part, label:"+label+" filename: "+expectedResponseParts.singlePartPayloadFilename+"}"; String rightID = "{from server, label:"+label @@ -399,10 +448,18 @@ public class XmlReplay { for (int i=0; i\r\n"+expectedPartContent); + Map vars = expectedResponseParts.varsList.get(i); + String fromTest = expectedResponseParts.fromTests.get(i); + String expectedPartContent; + if ( ! Tools.isEmpty(fromTest)){ + ServiceResult resultFromTest = serviceResultsMap.get(fromTest); + expectedPartContent = resultFromTest.requestPayloadsRaw.get(label); //TODO: debug this!!!!!!! + } else { + byte[] b = FileUtils.readFileToByteArray(new File(fileName)); + expectedPartContent = new String(b); + expectedPartContent = evalStruct.eval(expectedPartContent, serviceResultsMap, vars, evalStruct.jexl, evalStruct.jc); + } + //System.out.println("expected: "+label+ " content ==>\r\n"+expectedPartContent); PayloadLogger.Part partFromServer = traffic.getPart(label); String partFromServerContent = ""; if (partFromServer != null){ @@ -430,7 +487,7 @@ public class XmlReplay { //} } } catch (Exception e){ - String err = "ERROR in XmlReplay.validateResponse() : "+e; + String err = "ERROR in XmlReplay.validateResponse() : "+e; //System.out.println(err); return err ; } @@ -504,6 +561,7 @@ public class XmlReplay { evalStruct.jexl = jexl; for (Node testgroup : testgroupNodes) { + JexlContext jc = new MapContext(); //Get a new JexlContext for each test group. evalStruct.jc = jc; @@ -518,7 +576,15 @@ public class XmlReplay { int testElementIndex = -1; for (Node testNode : tests) { + long startTime = System.currentTimeMillis(); try { + /*try { + //"sleeping 2"); + Thread.currentThread().sleep(2); + } catch (InterruptedException ie){ + System.out.println("ERROR sleeping: "+ie); + } + */ testElementIndex++; String testID = testNode.valueOf("@ID"); String testIDLabel = Tools.notEmpty(testID) ? (testGroupID+'.'+testID) : (testGroupID+'.'+testElementIndex); @@ -537,7 +603,7 @@ public class XmlReplay { } if (uri.indexOf("$")>-1){ - uri = evalStruct.eval(uri, serviceResultsMap, jexl, jc); + uri = evalStruct.eval(uri, serviceResultsMap, null, jexl, jc); } fullURL = fixupFullURL(fullURL, protoHostPort, uri); @@ -572,14 +638,23 @@ public class XmlReplay { uri = fromTestID(uri, testNode, serviceResultsMap); } if (parts.bDoingSinglePartPayload){ - serviceResult = XmlReplayTransport.doPOST_PUTFromXML(parts.singlePartPayloadFilename, protoHostPort, uri, method, XmlReplayTransport.APPLICATION_XML, evalStruct, authForTest, testIDLabel); + Map vars = null; + if (parts.varsList.size()>0){ + vars = parts.varsList.get(0); + } + serviceResult = XmlReplayTransport.doPOST_PUTFromXML(parts.singlePartPayloadFilename, vars, protoHostPort, uri, method, XmlReplayTransport.APPLICATION_XML, evalStruct, authForTest, testIDLabel); } else { - serviceResult = XmlReplayTransport.doPOST_PUTFromXML_Multipart(parts.filesList, parts.partsList, protoHostPort, uri, method, evalStruct, authForTest, testIDLabel); + boolean POX = true; + if (POX){ + serviceResult = XmlReplayTransport.doPOST_PUTFromXML_POX (parts.filesList, parts.partsList, parts.varsList, protoHostPort, uri, method, evalStruct, authForTest, testIDLabel); + } else { + serviceResult = XmlReplayTransport.doPOST_PUTFromXML_Multipart(parts.filesList, parts.partsList, parts.varsList, protoHostPort, uri, method, evalStruct, authForTest, testIDLabel); + } } results.add(serviceResult); - if (isPOST){ + //if (isPOST){ serviceResultsMap.put(testID, serviceResult); //PUTs do not return a Location, so don't add PUTs to serviceResultsMap. - } + //} fullURL = fixupFullURL(fullURL, protoHostPort, uri); } else if (method.equalsIgnoreCase("DELETE")){ String fromTestID = testNode.valueOf("fromTestID"); @@ -610,11 +685,13 @@ public class XmlReplay { fullURL = fromTestID(fullURL, testNode, serviceResultsMap); serviceResult = XmlReplayTransport.doGET(fullURL, authForTest, testIDLabel); results.add(serviceResult); + serviceResultsMap.put(testID, serviceResult); } else if (method.equalsIgnoreCase("LIST")){ fullURL = fixupFullURL(fullURL, protoHostPort, uri); String listQueryParams = ""; //TODO: empty for now, later may pick up from XML control file. serviceResult = XmlReplayTransport.doLIST(fullURL, listQueryParams, authForTest, testIDLabel); results.add(serviceResult); + serviceResultsMap.put(testID, serviceResult); } else { throw new Exception("HTTP method not supported by XmlReplay: "+method); } @@ -634,20 +711,36 @@ public class XmlReplay { String level = expectedLevel.valueOf("@level"); serviceResult.payloadStrictness = level; } - + //===================================================== + // ALL VALIDATION FOR ALL REQUESTS IS DONE HERE: + //===================================================== String vError = validateResponse(serviceResult, serviceResultsMap, expectedResponseParts, evalStruct); if (Tools.notEmpty(vError)){ serviceResult.error = vError; serviceResult.failureReason = " : VALIDATION ERROR; "; } - String serviceResultRow = serviceResult.dump(dump.dumpServiceResult); + String serviceResultRow = serviceResult.dump(dump.dumpServiceResult)+"; time:"+(startTime-System.currentTimeMillis()); String leader = (dump.dumpServiceResult == ServiceResult.DUMP_OPTIONS.detailed) ? "XmlReplay:"+testIDLabel+": ": ""; + if ( (dump.dumpServiceResult == ServiceResult.DUMP_OPTIONS.detailed) + || (dump.dumpServiceResult == ServiceResult.DUMP_OPTIONS.full)){ + System.out.println("\r\n#---------------------#"); + } System.out.println(leader+serviceResultRow+"\r\n"); - if (dump.payloads) System.out.println(serviceResult.result); + if (dump.payloads && Tools.notBlank(serviceResult.requestPayload)) { + System.out.println("\r\n========== request payload ==============="); + System.out.println(serviceResult.requestPayload); + System.out.println("==========================================\r\n"); + } + if (dump.payloads && Tools.notBlank(serviceResult.result)) { + System.out.println("\r\n========== response payload =============="); + System.out.println(serviceResult.result); + System.out.println("==========================================\r\n"); + } } catch (Throwable t) { String msg = "ERROR: XmlReplay experienced an error in a test node: "+testNode+" Throwable: "+t; System.out.println(msg); + System.out.println(Tools.getStackTrace(t)); ServiceResult serviceResult = new ServiceResult(); serviceResult.error = msg; serviceResult.failureReason = " : SYSTEM ERROR; "; @@ -690,6 +783,9 @@ public class XmlReplay { if (Tools.notEmpty(fromProps)){ return fromProps; } + if (line==null){ + return ""; + } result = line.getOptionValue(option); if (result == null){ result = ""; diff --git a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayEval.java b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayEval.java index 5723f5b27..a9ece6858 100755 --- a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayEval.java +++ b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayEval.java @@ -52,13 +52,26 @@ public class XmlReplayEval { * uri = eval(uri, serviceResultsMap, jexl, jc);
* RESULT: "/cspace-services/orgauthorities/43a2739c-4f40-49c8-a6d5/items/" */ - public static String eval(String inputJexlExpression, Map serviceResultsMap, JexlEngine jexl, JexlContext jc) { + public static String eval(String inputJexlExpression, Map serviceResultsMap, Map vars, JexlEngine jexl, JexlContext jc) { //System.out.println("\r\n---- REPLACE.init-uri: "+inputJexlExpression); String result; try { - for (ServiceResult postResult : serviceResultsMap.values()) { - jc.set(postResult.testID, postResult); - //System.out.println("eval :: "+postResult.testID+"==>"+postResult); + //System.out.println("eval :: serviceResultsMap "+serviceResultsMap.size()); + for (ServiceResult serviceResult : serviceResultsMap.values()) { + jc.set(serviceResult.testID, serviceResult); + //System.out.println("eval :: "+serviceResult.testID+"==>"+serviceResult.minimal()); + } + if (vars!=null){ + for (Map.Entry entry: vars.entrySet()) { + String value = entry.getValue(); + String key = entry.getKey(); + try { + value = parse(value, jexl, jc); + } catch (Exception e){ + value = "ERROR: "+e; + } + jc.set(key, value); + } } result = parse(inputJexlExpression, jexl, jc); } catch (Throwable t) { diff --git a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayTest.java b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayTest.java index c480b7dc5..e9b4ca645 100755 --- a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayTest.java +++ b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayTest.java @@ -23,7 +23,7 @@ package org.collectionspace.services.IntegrationTests.xmlreplay; -import org.collectionspace.services.common.Tools; +import org.collectionspace.services.common.api.Tools; import org.testng.Assert; import java.io.File; diff --git a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayTransport.java b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayTransport.java index 885af176b..bd31d6629 100755 --- a/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayTransport.java +++ b/services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayTransport.java @@ -36,10 +36,11 @@ import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; -import org.collectionspace.services.common.Tools; +import org.collectionspace.services.common.api.Tools; /** * @author Laramie Crocker @@ -51,16 +52,20 @@ public class XmlReplayTransport { private static String CRLF = "\r\n"; public static ServiceResult doGET(String urlString, String authForTest, String fromTestID) throws Exception { + ServiceResult pr = new ServiceResult(); + pr.fromTestID = fromTestID; + pr.method = "GET"; + //HACK for speed testing. + //pr.CSID = "2"; + //pr.overrideGotExpectedResult(); + //if (true) return pr; + //END-HACK HttpClient client = new HttpClient(); GetMethod getMethod = new GetMethod(urlString); getMethod.addRequestHeader("Accept", "multipart/mixed"); getMethod.addRequestHeader("Accept", "application/xml"); getMethod.setRequestHeader("Authorization", "Basic " + authForTest); //"dGVzdDp0ZXN0"); getMethod.setRequestHeader("X-XmlReplay-fromTestID", fromTestID); - ServiceResult pr = new ServiceResult(); - - pr.fromTestID = fromTestID; - pr.method = "GET"; try { int statusCode1 = client.executeMethod(getMethod); pr.responseCode = statusCode1; @@ -129,29 +134,30 @@ public class XmlReplayTransport { /** Use this overload for multipart messages. */ public static ServiceResult doPOST_PUTFromXML_Multipart(List filesList, - List partsList, - String protoHostPort, - String uri, - String method, - XmlReplayEval evalStruct, - String authForTest, - String fromTestID) - throws Exception { + List partsList, + List> varsList, + String protoHostPort, + String uri, + String method, + XmlReplayEval evalStruct, + String authForTest, + String fromTestID) + throws Exception { if ( filesList==null||filesList.size()==0 ||partsList==null||partsList.size()==0 ||(partsList.size() != filesList.size())){ throw new Exception("filesList and partsList must not be empty and must have the same number of items each."); } String content = DD + BOUNDARY; - + Map contentRaw = new HashMap(); for (int i=0; i filesList, + List partsList, + List> varsList, + String protoHostPort, + String uri, + String method, + XmlReplayEval evalStruct, + String authForTest, + String fromTestID) + throws Exception { + if ( filesList==null||filesList.size()==0 + ||partsList==null||partsList.size()==0 + ||(partsList.size() != filesList.size())){ + throw new Exception("filesList and partsList must not be empty and must have the same number of items each."); + } + StringBuffer content = new StringBuffer("\r\n"); + //content.append(CRLF).append("").append(CRLF); + Map contentRaw = new HashMap(); + for (int i=0; i"); + String urlString = protoHostPort+uri; + String POX_BOUNDARY = "";//empty for POX. + return doPOST_PUT(urlString, content.toString(), contentRaw, POX_BOUNDARY, method,APPLICATION_XML, authForTest, fromTestID); //method is POST or PUT. + } + + /** Use this overload for NON-multipart messages, that is, regular POSTs. */ - public static ServiceResult doPOST_PUTFromXML(String fileName, - String protoHostPort, - String uri, - String method, - String contentType, - XmlReplayEval evalStruct, - String authForTest, - String fromTestID) + public static ServiceResult doPOST_PUTFromXML(String fileName, + Map vars, + String protoHostPort, + String uri, + String method, + String contentType, + XmlReplayEval evalStruct, + String authForTest, + String fromTestID) throws Exception { byte[] b = FileUtils.readFileToByteArray(new File(fileName)); String xmlString = new String(b); - xmlString = evalStruct.eval(xmlString, evalStruct.serviceResultsMap, evalStruct.jexl, evalStruct.jc); + xmlString = evalStruct.eval(xmlString, evalStruct.serviceResultsMap, vars, evalStruct.jexl, evalStruct.jc); String urlString = protoHostPort+uri; - return doPOST_PUT(urlString, xmlString, BOUNDARY, method, contentType, authForTest, fromTestID); //method is POST or PUT. + Map contentRaw = new HashMap(); + contentRaw.put("default", xmlString); + return doPOST_PUT(urlString, xmlString, contentRaw, BOUNDARY, method, contentType, authForTest, fromTestID); //method is POST or PUT. } - public static ServiceResult doPOST_PUT(String urlString, String content, String boundary, String method, String contentType, + public static ServiceResult doPOST_PUT(String urlString, String content, Map contentRaw, + String boundary, String method, String contentType, String authForTest, String fromTestID) throws Exception { ServiceResult result = new ServiceResult(); result.method = method; + //HACK for speed testing. Result: XmlReplay takes 9ms to process one test + // right up to the point of actually firing an HTTP request. + // or ~ 120 records per second. + //result.CSID = "2"; + //result.overrideGotExpectedResult(); + //if (true) return result; + //END-HACK try { URL url = new URL(urlString); HttpURLConnection conn; @@ -210,6 +263,7 @@ public class XmlReplayTransport { try { result.requestPayload = content; + result.requestPayloadsRaw = contentRaw; result.responseCode = conn.getResponseCode(); //System.out.println("responseCode: "+result.responseCode); if (400 <= result.responseCode && result.responseCode <= 499){ diff --git a/services/IntegrationTests/src/test/java/org/collectionspace/services/IntegrationTests/test/XmlReplayDevTest.java b/services/IntegrationTests/src/test/java/org/collectionspace/services/IntegrationTests/test/XmlReplayDevTest.java index b4fae5c87..0389953ba 100755 --- a/services/IntegrationTests/src/test/java/org/collectionspace/services/IntegrationTests/test/XmlReplayDevTest.java +++ b/services/IntegrationTests/src/test/java/org/collectionspace/services/IntegrationTests/test/XmlReplayDevTest.java @@ -3,11 +3,19 @@ package org.collectionspace.services.IntegrationTests.test; import org.collectionspace.services.IntegrationTests.xmlreplay.ServiceResult; import org.collectionspace.services.IntegrationTests.xmlreplay.XmlReplay; import org.collectionspace.services.IntegrationTests.xmlreplay.XmlReplayTest; +import org.collectionspace.services.common.api.Tools; + import org.testng.annotations.Test; +import java.util.ArrayList; import java.util.List; /** + Maven surefire doesn't let you pass stuff on the command line + unless you define -DforkMode=never inn the command-line args. + So be sure to use a command-line like: + mvn -e test -DxmlReplayMaster=dev-master.xml -DforkMode=never -Dtest=XmlReplayDevTest + * * User: laramie * $LastChangedRevision: $ * $LastChangedDate: $ @@ -16,22 +24,77 @@ public class XmlReplayDevTest extends XmlReplayTest { @Test public void runMaster() throws Exception { - XmlReplay replay = createXmlReplayUsingIntegrationTestsModule(".."); - List> list = replay.runMaster(XmlReplay.DEFAULT_DEV_MASTER_CONTROL); - logTestForGroup(list, "XmlReplayMasterTest"); - /* - Maven surefire doesn't let you pass stuff on the command line - unless you define it in command args in the pom.xml file. - So this doesn't work, because -D defines don't get passed through - when maven execs surefire. + if (true) return; + //This was a hack test. String masterFile = System.getProperty("xmlReplayMaster"); if (Tools.notEmpty(masterFile)){ System.out.println("Using masterFile specified in System property: "+masterFile); - XmlReplay replay = createXmlReplayUsingIntegrationTestsModule(".."); - List> list = replay.runMaster(masterFile); - logTestForGroup(list, "XmlReplayMasterTest"); - } */ + } else { + masterFile = XmlReplay.DEFAULT_DEV_MASTER_CONTROL; + System.out.println("Using default masterFile: "+masterFile); + } + //XmlReplay replay = createXmlReplayUsingIntegrationTestsModule(".."); + //List> list = replay.runMaster(masterFile); + //logTestForGroup(list, "XmlReplayMasterTest"); + int MAXWORKERS = 20; + long start = System.currentTimeMillis(); + for (int t=0; t workers = new ArrayList(); + private List stats = new ArrayList(); + private volatile boolean quitNow = false; + protected void finished(Worker worker, Long time){ + synchronized(workers){ + workers.remove(worker); + stats.add(time); + if (workers.size()==0){ + quitNow = true; + } + System.out.println("Workers left: "+workers.size()); + workers.notifyAll(); + } + + } + + public static class Worker extends Thread{ + public Worker(String masterFile, String ID, XmlReplayDevTest dtest){ + super(ID); + this.masterFile = masterFile; + this.dtest = dtest; + } + private String masterFile; + private XmlReplayDevTest dtest; + + public void run(){ + try { + long start = System.currentTimeMillis(); + System.out.println("RUNNING Master in Worker: "+this.getName()); + XmlReplay replay = createXmlReplayUsingIntegrationTestsModule(".."); + List> list = replay.runMaster(masterFile); + logTestForGroup(list, "XmlReplayMasterTest"); + long stop = System.currentTimeMillis(); + dtest.finished(this, stop-start); + } catch (Exception e){ + System.out.println("ERROR in Worker: "+e); + return; + } + + } } } diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dev-master.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dev-master.xml index 0d8bcfeb3..0343334d4 100644 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dev-master.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/dev-master.xml @@ -8,10 +8,11 @@ below about not leaving any active testGroups enabled in this file when you check it in. --> + http://localhost:8180 - + YWRtaW5AY29sbGVjdGlvbnNwYWNlLm9yZzpBZG1pbmlzdHJhdG9y @@ -40,11 +41,22 @@ + + + --> + + + - diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/object-exit-display.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/object-exit-display.xml new file mode 100755 index 000000000..efa447bc9 --- /dev/null +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/object-exit-display.xml @@ -0,0 +1,51 @@ + + + + + YWRtaW5AY29sbGVjdGlvbnNwYWNlLm9yZzpBZG1pbmlzdHJhdG9y + YWRtaW5AY29sbGVjdGlvbnNwYWNlLm9yZzpBZG1pbmlzdHJhdG9y + + + + + + + POST + /cspace-services/personauthorities/ + objectexit/oePersonauthority.xml + + + POST + /cspace-services/personauthorities/${oePersonauthority.CSID}/items/ + objectexit/oePersonDisplayOnly.xml + + Finbar the DisplayName + + + + GET + /cspace-services/personauthorities/${oePersonauthority.CSID}/items/${oePerson.CSID} + + + + + + + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oe1.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oe1.xml index 35bf0cd42..329ca8e42 100644 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oe1.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oe1.xml @@ -1,4 +1,3 @@ - diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oe24.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oe24.xml new file mode 100755 index 000000000..e69de29bb diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oeObject.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oeObject.xml new file mode 100755 index 000000000..17acce70a --- /dev/null +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oeObject.xml @@ -0,0 +1,9 @@ + + + ${depositor} + ${currentOwner} + exitDate-1290026474563 + ${exitNumber} + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oePerson.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oePerson.xml new file mode 100755 index 000000000..e69de29bb diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oePersonDisplayOnly.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oePersonDisplayOnly.xml new file mode 100755 index 000000000..c2c16c90f --- /dev/null +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oePersonDisplayOnly.xml @@ -0,0 +1,11 @@ + + + + + ${displayName} + false + + + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oePersonauthority.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oePersonauthority.xml new file mode 100755 index 000000000..b66c80abc --- /dev/null +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/oePersonauthority.xml @@ -0,0 +1,12 @@ + + + + Default Person Authority + defaultPersonAuthority + PersonAuthority + + + + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe2.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe2.res.xml index 4413627b7..24166dc6a 100755 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe2.res.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oe2.res.xml @@ -1,4 +1,5 @@ + urn:cspace:org.collectionspace.demo:orgauthority:name(TestOrgAuth):organization:name(Northern Climes Museum)'Northern Climes Museum' + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oePersonGET.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oePersonGET.res.xml new file mode 100755 index 000000000..f0308d73a --- /dev/null +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oePersonGET.res.xml @@ -0,0 +1,2 @@ +removed from svn + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oePersonauthorityGET.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/objectexit/res/oePersonauthorityGET.res.xml new file mode 100755 index 000000000..e69de29bb diff --git a/services/common-api/pom.xml b/services/common-api/pom.xml index 0e8c736cf..567ec6bb9 100755 --- a/services/common-api/pom.xml +++ b/services/common-api/pom.xml @@ -10,6 +10,7 @@ org.collectionspace.services org.collectionspace.services.common-api services.common-api + 1.5.1 jar diff --git a/services/common-api/src/main/java/org/collectionspace/services/common/api/FileTools.java b/services/common-api/src/main/java/org/collectionspace/services/common/api/FileTools.java new file mode 100755 index 000000000..dc74370ce --- /dev/null +++ b/services/common-api/src/main/java/org/collectionspace/services/common/api/FileTools.java @@ -0,0 +1,124 @@ +/** + * This document is a part of the source code and related artifacts + * for CollectionSpace, an open source collections management system + * for museums and related institutions: + + * http://www.collectionspace.org + * http://wiki.collectionspace.org + + * Copyright 2009 University of California at Berkeley + + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + + * You may obtain a copy of the ECL 2.0 License at + + * https://source.collectionspace.org/collection-space/LICENSE.txt + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.collectionspace.services.common.api; + +// This class is designed to avoid dependencies, so it does not include logging, or apache commons. +// There is another cspace utility class, called +// org.collectionspace.services.common.FileUtils +// albeit with different functions, which does have dependencies. + +import java.io.*; +import java.util.UUID; +import java.util.regex.Pattern; +import java.util.regex.Matcher; + + +/** + * @author Laramie Crocker + * $LastChangedRevision: $ + * $LastChangedDate: $ + */ +public class FileTools { + + public static void forceParentDirectories(String filename) throws IOException { + File theFile = new File(filename); + String parent = theFile.getParent(); + if (parent != null){ + File p = new File(parent); + p.mkdirs(); + System.out.println("Making directory: "+p.getCanonicalPath()); + } + } + + public static boolean copyFile(String sourceFileName, String destFileName, boolean forceParentDirs) throws IOException { + if (sourceFileName == null || destFileName == null) + return false; + if (sourceFileName.equals(destFileName)) + return false; + if (forceParentDirs) + forceParentDirectories(destFileName); + try{ + java.io.FileInputStream in = new java.io.FileInputStream(sourceFileName); + java.io.FileOutputStream out = new java.io.FileOutputStream(destFileName); + try { + byte[] buf = new byte[31000]; + int read = in.read(buf); + while (read > -1){ + out.write(buf, 0, read); + read = in.read(buf); + } + } finally { + in.close(); + out.close(); + } + } catch (Exception e) { + System.out.println(e.toString()); + return false; + } + return true; + } + + public static String readFile(String dir, String relPath){ + try { + File theFile = new File(dir, relPath); + FileInputStream fis = new FileInputStream(theFile); + byte[] theData = new byte[(int) theFile.length()]; + // need to check the number of bytes read here + int howmany = fis.read(theData); + if (howmany != theData.length){ + System.out.println("ERROR: Couldn't read all of stream! filesize: "+theData.length+" read: "+howmany); + } + fis.close(); + return new String(theData); + } catch (Exception e) { // can't find the file + System.out.println("ERROR: "+e); + return null; + } + } + + public static File saveFile(String dir, String relativeName, String content, boolean forceParentDirs) + throws IOException { + File result = null; + PrintWriter writer; + try{ + if (forceParentDirs) forceParentDirectories(dir+'/'+relativeName); + result = new File(dir,relativeName); + writer = new PrintWriter(new FileOutputStream(result)); + }catch (Exception e){ + System.out.println("Can't write to file in FileTools.saveFile: " + relativeName + " :: " + e); + return null; + } + writer.write(content); + writer.close(); + return result; + } + + public static File createTmpDir(String filePrefix){ + String tmpDir = System.getProperty("java.io.tmpdir"); + File result = new File(tmpDir, filePrefix + UUID.randomUUID().toString()); + return result; + } + + +} diff --git a/services/common-api/src/main/java/org/collectionspace/services/common/api/RefName.java b/services/common-api/src/main/java/org/collectionspace/services/common/api/RefName.java index 823095e2d..e0a15f6e3 100755 --- a/services/common-api/src/main/java/org/collectionspace/services/common/api/RefName.java +++ b/services/common-api/src/main/java/org/collectionspace/services/common/api/RefName.java @@ -4,10 +4,39 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; /** + * Usage for this class, if you have a URN and would like to get at its fields, is to call one of these methods: + * + * RefName.AuthorityItem item = RefName.AuthorityItem.parse(RefName.AUTHORITY_ITEM_EXAMPLE); + * or + * RefName.Authority authority = RefName.Authority.parse(RefName.AUTHORITY_EXAMPLE); + * + * From the object returned, you may set/get any of the public fields. + * + * If you want to format a string urn, then you need to construct either a RefName.AuthorityItem or RefName.Authority. + * You can parse a URN to do so, as shown above, or you can construct one with a constructor, setting its fields afterwards. + * A better way is to use one of the build*() methods on this class: + * + * RefName.Authority authority2 = RefName.buildAuthority(tenantName, serviceName, authorityShortIdentifier, authorityDisplayName); + * + * RefName.AuthorityItem item2 = RefName.buildAuthorityItem(authority2, + * RefName.EX_itemShortIdentifier, + * RefName.EX_itemDisplayName); + * + * Note that authority2 is an object, not a String, and is passed in to RefName.buildAuthorityItem(). + * + * Then simply call toString() on the object: + * + * String authorityURN = authority2.toString(); + * + * String itemURN = item2.toString(); + * + * These test cases are kept up-to-date in + * + * org.collectionspace.services.common.api.test.RefNameTest + * * User: laramie - * $LastChangedRevision: $ - * $LastChangedDate: $ */ + public class RefName { public static final String HACK_VOCABULARIES = "Vocabularies"; //TODO: get rid of these. public static final String HACK_ORGANIZATIONS = "Organizations"; //TODO: get rid of these. diff --git a/services/common/src/main/java/org/collectionspace/services/common/Tools.java b/services/common-api/src/main/java/org/collectionspace/services/common/api/Tools.java similarity index 78% rename from services/common/src/main/java/org/collectionspace/services/common/Tools.java rename to services/common-api/src/main/java/org/collectionspace/services/common/api/Tools.java index cea3c2042..0df8fba6d 100755 --- a/services/common/src/main/java/org/collectionspace/services/common/Tools.java +++ b/services/common-api/src/main/java/org/collectionspace/services/common/api/Tools.java @@ -21,7 +21,7 @@ * limitations under the License. */ -package org.collectionspace.services.common; +package org.collectionspace.services.common.api; import java.io.File; import java.util.regex.Pattern; @@ -47,15 +47,33 @@ public class Tools { return first+separator+second; } + /** Remove all whitespace from a String. */ + public static String squeeze(String s) { + return s.replaceAll("\\s+", ""); + } + + /** Milliseconds from start time as defined by the Date class. */ + public static Long now(){ + return new Long((new java.util.Date()).getTime()); + } + /** Handles null strings as empty. */ public static boolean isEmpty(String str){ return !notEmpty(str); } /** Handles null strings as empty. */ - public static boolean notEmpty(String str){ + public static boolean notEmpty(String str){ + if (str==null) return false; + if (str.length()==0) return false; + return true; + } + public static boolean notBlank(String str){ if (str==null) return false; if (str.length()==0) return false; + if (str.trim().length()==0){ + return false; + } return true; } @@ -133,7 +151,18 @@ public class Tools { return result; } - + /** Takes an Exception object and formats a message that provides more debug information + * suitable for developers for printing to System.out or for logging. Not suitable for + * presentation of error messages to clients. + */ + public static String errorToString(Throwable e, boolean stackTraceOnException){ + if (e==null){ + return ""; + } + String s = e.toString() + "\r\n -- message: " + e.getMessage(); + s = s + "\r\n -- Stack Trace: \r\n -- " + getStackTrace(e); + return s; + } } diff --git a/services/common-api/src/main/java/org/collectionspace/services/common/api/ZipTools.java b/services/common-api/src/main/java/org/collectionspace/services/common/api/ZipTools.java new file mode 100755 index 000000000..f0aaa4be7 --- /dev/null +++ b/services/common-api/src/main/java/org/collectionspace/services/common/api/ZipTools.java @@ -0,0 +1,156 @@ +/** + * This document is a part of the source code and related artifacts + * for CollectionSpace, an open source collections management system + * for museums and related institutions: + + * http://www.collectionspace.org + * http://wiki.collectionspace.org + + * Copyright 2009 University of California at Berkeley + + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + + * You may obtain a copy of the ECL 2.0 License at + + * https://source.collectionspace.org/collection-space/LICENSE.txt + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.collectionspace.services.common.api; + +import java.io.*; +import java.util.*; +import java.util.zip.*; + +/** + * User: laramie + * $LastChangedRevision: $ + * $LastChangedDate: $ + */ +public class ZipTools { + + public static final void copyInputStream(InputStream in, OutputStream out) throws IOException { + try { + byte[] buffer = new byte[1024]; + int len; + while ((len = in.read(buffer)) >= 0) { + out.write(buffer, 0, len); + } + } finally { + in.close(); + out.close(); + } + } + + public static void forceParentDirectories(String filename) throws Exception { + File theFile = new File(filename); + String parent = theFile.getParent(); + if (parent != null) { + File p = new File(parent); + p.mkdirs(); + System.out.println("Making directory: " + p.getCanonicalPath()); + } + } + + /** + * It is HIGHLY recommended to use a baseOutputDir, such as "./", or + * a local directory you know, such as "/tmp/foo", to prevent + * files from being unzipped in your root directory. + */ + public static final void unzip(String zipfileName, String baseOutputDir) { + Enumeration entries; + ZipFile zipFile; + try { + zipFile = new ZipFile(zipfileName); + entries = zipFile.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = (ZipEntry) entries.nextElement(); + String entryName = entry.getName(); + String theName = baseOutputDir + '/' + entryName; + if (entry.isDirectory()) { + // Assume directories are stored parents first then children. + System.out.println("Extracting directory: " + entry.getName()); + // This is not robust, just for demonstration purposes. + (new File(theName)).mkdirs(); + continue; + } + //(new File(theName)).mkdirs(); + forceParentDirectories(theName); + System.out.println("Extracting file: " + theName); + copyInputStream(zipFile.getInputStream(entry), new BufferedOutputStream(new FileOutputStream(theName))); + } + zipFile.close(); + } catch (Exception ioe) { + System.err.println("Unhandled exception:"); + ioe.printStackTrace(); + return; + } + } + + public static void zipDiveDirectory(int stripLeadingPathChars, String directory, String zipFilename) throws Exception { + ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFilename)); + zipDir(stripLeadingPathChars, directory, zos); + zos.close(); + } + + public static void zipDir(int stripLeadingPathChars, String dir2zip, ZipOutputStream zos) throws Exception { + File fzipDir = new File(dir2zip); + if (!fzipDir.exists()) { + System.out.println("dir doesn't exist: " + dir2zip); + return; + } + String[] dirList = fzipDir.list(); //get a listing of the directory content + byte[] readBuffer = new byte[2156]; + int bytesIn = 0; + //loop through dirList, and zip the files + for (int i = 0; i < dirList.length; i++) { + File f = new File(fzipDir, dirList[i]); + if (f.isDirectory()) { + //if the File object is a directory, call this function again to add its content recursively + zipDir(stripLeadingPathChars, f.getPath(), zos); //DIVE! + continue; + } + //if we reached here, the File object f was not a directory + String fpath = f.getPath(); + String nameInArchive = fpath.substring(stripLeadingPathChars, fpath.length()); + addToZip(zos, fpath, nameInArchive); + } + } + + public static void addToZip(ZipOutputStream zos, String filename, String nameInArchive) throws Exception { + File file = new File(filename); + if (!file.exists()) { + System.err.println("File does not exist, skipping: " + filename); + return; + } + BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); + int bytesRead; + byte[] buffer = new byte[1024]; + CRC32 crc = new CRC32(); + crc.reset(); + while ((bytesRead = bis.read(buffer)) != -1) { + crc.update(buffer, 0, bytesRead); + } + bis.close(); + // Reset to beginning of input stream + bis = new BufferedInputStream(new FileInputStream(file)); + String nameInArchiveFixed = nameInArchive.replace("\\", "/"); + ZipEntry entry = new ZipEntry(nameInArchiveFixed); + entry.setMethod(ZipEntry.STORED); + entry.setCompressedSize(file.length()); + entry.setSize(file.length()); + entry.setCrc(crc.getValue()); + zos.putNextEntry(entry); + while ((bytesRead = bis.read(buffer)) != -1) { + zos.write(buffer, 0, bytesRead); + } + bis.close(); + } + +} + diff --git a/services/common/pom.xml b/services/common/pom.xml index 64ee1f388..e88c15485 100644 --- a/services/common/pom.xml +++ b/services/common/pom.xml @@ -15,6 +15,11 @@ + + org.collectionspace.services + org.collectionspace.services.common-api + 1.5.1 + org.collectionspace.services org.collectionspace.services.3rdparty.nuxeo.quote-api diff --git a/services/common/src/main/java/org/collectionspace/services/common/FileUtils.java b/services/common/src/main/java/org/collectionspace/services/common/FileUtils.java index eb4c6e0a2..6c85676af 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/FileUtils.java +++ b/services/common/src/main/java/org/collectionspace/services/common/FileUtils.java @@ -1,17 +1,42 @@ +/** + * This document is a part of the source code and related artifacts + * for CollectionSpace, an open source collections management system + * for museums and related institutions: + + * http://www.collectionspace.org + * http://wiki.collectionspace.org + + * Copyright 2009 University of California at Berkeley + + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + + * You may obtain a copy of the ECL 2.0 License at + + * https://source.collectionspace.org/collection-space/LICENSE.txt + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.collectionspace.services.common; //import java.io.*; import javax.servlet.http.HttpServletRequest; +import java.io.*; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.UUID; //import java.io.IOException; -import java.io.File; -import java.io.InputStream; -import java.io.FileOutputStream; + +import java.util.UUID; +import java.util.regex.Pattern; +import java.util.regex.Matcher; //import javax.servlet.ServletException; //import javax.servlet.http.HttpServlet; @@ -119,4 +144,5 @@ public class FileUtils { return result; } + } diff --git a/services/common/src/main/java/org/collectionspace/services/common/IFragmentHandler.java b/services/common/src/main/java/org/collectionspace/services/common/IFragmentHandler.java new file mode 100755 index 000000000..5a31f4919 --- /dev/null +++ b/services/common/src/main/java/org/collectionspace/services/common/IFragmentHandler.java @@ -0,0 +1,56 @@ +/** + * This document is a part of the source code and related artifacts + * for CollectionSpace, an open source collections management system + * for museums and related institutions: + + * http://www.collectionspace.org + * http://wiki.collectionspace.org + + * Copyright 2011 University of California at Berkeley + + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + + * You may obtain a copy of the ECL 2.0 License at + + * https://source.collectionspace.org/collection-space/LICENSE.txt + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.collectionspace.services.common; + +import org.dom4j.Document; +import org.dom4j.Element; + +/** Define this interface to listen for events from the driving class: + * org.collectionspace.services.common.XmlSaxFragmenter , so that + * the XmlSaxFragmenter class may be passed a large file or InputSource (stream) + * and it will be parsed with SAX, but you will get fragments from it that you can + * parse with DOM. + * + * You will be passed a Document context, which is a Dom4j document that represents the + * skeleton of the document you started with, but without any fragments, so the Document + * will just be context information of how the XmlSaxFragmenter found this fragment. + * + * You will receive onFragmentReady() events whenever a fragment is parsed completely. + * the fragment parameter will be just the inner XML String of fragmentParent, and will + * not be represented in the DOM of the Document context. + * + * @author Laramie Crocker + */ +public interface IFragmentHandler { + /** @param fragmentIndex is the zero-based index of the current fragment; you will first get this event + * on fragmentIndex==0, which is a fragmentCount of 1. */ + public void onFragmentReady(Document context, + Element fragmentParent, + String currentPath, + int fragmentIndex, + String fragment); + + /** @param fragmentCount is the count of fragments processed - a value of 1 means 1 fragment was found. */ + public void onEndDocument(Document context, int fragmentCount); +} diff --git a/services/common/src/main/java/org/collectionspace/services/common/ReflectionMapper.java b/services/common/src/main/java/org/collectionspace/services/common/ReflectionMapper.java index 50eb637c2..99f3e59dd 100755 --- a/services/common/src/main/java/org/collectionspace/services/common/ReflectionMapper.java +++ b/services/common/src/main/java/org/collectionspace/services/common/ReflectionMapper.java @@ -17,6 +17,8 @@ */ package org.collectionspace.services.common; +import org.collectionspace.services.common.api.Tools; + import java.lang.reflect.Constructor; import java.lang.reflect.Method; diff --git a/services/common/src/main/java/org/collectionspace/services/common/ResourceBase.java b/services/common/src/main/java/org/collectionspace/services/common/ResourceBase.java index def456339..ee5a4ecf7 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/ResourceBase.java +++ b/services/common/src/main/java/org/collectionspace/services/common/ResourceBase.java @@ -1,3 +1,27 @@ +/** + * This document is a part of the source code and related artifacts + * for CollectionSpace, an open source collections management system + * for museums and related institutions: + + * http://www.collectionspace.org + * http://wiki.collectionspace.org + + * Copyright 2010 University of California at Berkeley + + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + + * You may obtain a copy of the ECL 2.0 License at + + * https://source.collectionspace.org/collection-space/LICENSE.txt + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.collectionspace.services.common; import org.collectionspace.services.client.PoxPayloadIn; @@ -40,7 +64,18 @@ extends AbstractMultiPartCollectionSpaceResourceImpl { public static final String LIST = "list"; //FIXME retrieve client type from configuration - final static ClientType CLIENT_TYPE = ServiceMain.getInstance().getClientType(); + static ClientType CLIENT_TYPE; + static { + try { + // I put this in a try-catch static block instead of file-level static var initializer so that static methods of + // *Resource classes may be called statically from test cases. + // Without this catch, you can't even access static methods of a *Resource class for testing. + CLIENT_TYPE = ServiceMain.getInstance().getClientType(); + //System.out.println("Static initializer in ResourceBase. CLIENT_TYPE:"+CLIENT_TYPE); + } catch (Throwable t){ + System.out.println("Static initializer failed in ResourceBase because not running from deployment. OK to use Resource classes statically for tests."); + } + } protected void ensureCSID(String csid, String crudType) throws WebApplicationException { if (logger.isDebugEnabled()) { @@ -64,9 +99,9 @@ extends AbstractMultiPartCollectionSpaceResourceImpl { protected WebApplicationException bigReThrow(Exception e, String serviceMsg, String csid) throws WebApplicationException { Response response; - if (logger.isDebugEnabled()) { - logger.debug(getClass().getName(), e); - } + //if (logger.isDebugEnabled()) { + logger.error(getClass().getName(), e); + //} if (e instanceof UnauthorizedException) { response = Response.status(Response.Status.UNAUTHORIZED) .entity(serviceMsg + e.getMessage()).type("text/plain") diff --git a/services/common/src/main/java/org/collectionspace/services/common/XmlSaxFragmenter.java b/services/common/src/main/java/org/collectionspace/services/common/XmlSaxFragmenter.java new file mode 100755 index 000000000..c53be9fe8 --- /dev/null +++ b/services/common/src/main/java/org/collectionspace/services/common/XmlSaxFragmenter.java @@ -0,0 +1,333 @@ +/** + * This document is a part of the source code and related artifacts + * for CollectionSpace, an open source collections management system + * for museums and related institutions: + + * http://www.collectionspace.org + * http://wiki.collectionspace.org + + * Copyright 2011 University of California at Berkeley + + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + + * You may obtain a copy of the ECL 2.0 License at + + * https://source.collectionspace.org/collection-space/LICENSE.txt + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.collectionspace.services.common; + +import org.collectionspace.services.common.api.Tools; +import org.dom4j.Document; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import org.dom4j.io.HTMLWriter; +import org.dom4j.io.OutputFormat; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; +import org.xml.sax.ext.Locator2; +import java.io.StringWriter; + +/** Use XmlSaxFragmenter to parse a large file or InputSource (stream) + * with SAX, and pass in an instance of IFragmentHandler to parse() so that you can + * get fragments back that you can parse with DOM or other processing. + * + * You would typically instantiate and run this class like so: + * + * IFragmentHandler callback = new MyFragmentHandlerImpl(); //define the interface somewhere. + * XmlSaxFragmenter.parse("C:\\tmp\\imports.xml", "/document/schema", callback); + * + * Then, given an XML document like this: + * <document repository="default" id="123"> + * <schema name="collectionobjects_naturalhistory"> + * <nh-int/> + * <nh-note/> + * </schema> + * <schema name="collectionobjects_common"> + * <remNumber> + * <numberValue/> + * <numberType/> + * </remNumber> + * </schema> + * </document> + * + * you'll get two onFragmentReady() events: the first will pass String fragment = + * <schema name="collectionobjects_naturalhistory"> <nh-int/> + * <nh-note/> + * plus some context information, and the second will pass String fragment = + * <remNumber> + * <numberValue/> + * <numberType/> + * </remNumber> + * + * @author Laramie Crocker + */ +public class XmlSaxFragmenter implements ContentHandler, ErrorHandler { + + //=============== ContentHandler ==================================================== + + public void setDocumentLocator(Locator locator) { + if (xmlDeclarationDone){ + return; + } + if (locator instanceof Locator2){ + Locator2 l2 = ((Locator2) locator); + String enc = l2.getEncoding(); + String ver = l2.getXMLVersion(); + append("\r\n"); + xmlDeclarationDone = true; + } else { + //System.err.println("Locator2 not found."); + append("\r\n"); + xmlDeclarationDone = true; + } + //more info available from Locator if needed: locator.getPublicId(), locator.getSystemId(); + } + + public void startDocument() throws SAXException { + document = DocumentHelper.createDocument(); + } + + public void endDocument() throws SAXException { + if (fragmentHandler!=null) { + fragmentHandler.onEndDocument(document, fragmentIndex + 1); + } + } + + public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { + String attsString = attsToStr(atts); + append("<" + name(qName, localName) + attsString + ">"); + if (inFragment){ + inFragmentDepth++; + return; + } + if (currentElement == null){ + currentElement = document.addElement(qName); + } else { + Element element = DocumentHelper.createElement(qName); + currentElement.add(element); + previousElement = currentElement; + currentElement = element; + } + addAttributes(currentElement, atts); + String currentPath = currentElement.getPath(); + if (currentPath.equals(chopPath)){ + buffer = new StringBuffer(); + inFragment = true; + if (includeParent){ + append("<" + name(qName, localName) + attsString + ">"); + } + } + } + + public void endElement(String uri, String localName, String qName) throws SAXException { + if (inFragment && (inFragmentDepth>0)){ + append("'); + } else if (inFragment && inFragmentDepth == 0 && includeParent){ + append("'); + } + if (inFragment && (inFragmentDepth==0)){ + if (fragmentHandler!=null) { + fragmentIndex++; + fragmentHandler.onFragmentReady(document, + currentElement, + currentElement.getPath(), + fragmentIndex, + buffer.toString()); + } + inFragment = false; + currentElement = previousElement; + } + if (inFragment){ + inFragmentDepth--; + } + } + + public void characters(char ch[], int start, int length) throws SAXException { + String chars = new String(ch, start, length); + append(chars); + } + + public void startPrefixMapping(String prefix, String uri) throws SAXException { + } + public void endPrefixMapping(String prefix) throws SAXException { + } + public void ignorableWhitespace(char ch[], int start, int length) throws SAXException { + } + public void processingInstruction(String target, String data) throws SAXException { + } + public void skippedEntity(String name) throws SAXException { + } + + //=============== ErrorHandler ==================================================== + + public void error(SAXParseException exception){ + System.err.println("ERROR:"+exception); + } + public void fatalError(SAXParseException exception){ + System.err.println("FATAL_ERROR:"+exception); + } + public void warning(SAXParseException exception){ + System.err.println("WARNING:"+exception); + } + + //================ Helper Methods =================================================== + + private Document document; + private Element currentElement; + private Element previousElement; + private StringBuffer buffer = new StringBuffer(); + + private boolean xmlDeclarationDone = false; + private boolean inFragment = false; + private int inFragmentDepth = 0; + private int fragmentIndex = -1; //zero-based. Used for informational purposes only, to report to the IFragmentHandler. + + private String chopPath = ""; + public String getChopPath() { + return chopPath; + } + /** You should not set the chopPath directly; instead you must set it in the call to parse(). */ + protected void setChopPath(String chopPath) { + this.chopPath = chopPath; + } + + private boolean includeParent = false; + public boolean isIncludeParent() { + return includeParent; + } + public void setIncludeParent(boolean includeParent) { + this.includeParent = includeParent; + } + + + private IFragmentHandler fragmentHandler; + public IFragmentHandler getFragmentHandler() { + return fragmentHandler; + } + /** You should not set the FragmentHandler directly; instead you must set it in the call to parse(). */ + protected void setFragmentHandler(IFragmentHandler fragmentHandler) { + this.fragmentHandler = fragmentHandler; + } + + protected void append(String str){ + buffer.append(str); + } + + protected String name(String qn, String ln){ + if (Tools.isEmpty(qn)){ + return ln; + } + if (qn.equals(ln)){ + return ln; + } + return qn; + } + + //NOTE: we don't deal with this here because we don't need to + // actually understand the namespace uri: + // a.getURI(i) + protected String attsToStr(Attributes a){ + StringBuffer b = new StringBuffer(); + String qn, ln; + int attsLen = a.getLength(); + for (int i=0; i"; + } + return prettyHTML; + } + + /** This method takes a filename of a local file only; InputSource is not implemented yet. + * + * @param theFileName the filename of a local file, which should be valid XML. + * @param chopPath the path from the root of the document to the parent element + * of the fragment you want. + * @param handler An instance of IFragmentHandler that you define to get the onFragmentReady event + * which will give you the fragment and some context information. + * @param includeParent If you set this to true, you will get the element described by chopPath included in the fragment, otherwise, + * it will not appear in the fragment; in either case, the element will be available in the Document context and the + * Element fragmentParent in the callback IFragmentHandler.onFragmentReady(). + */ + public static void parse(String theFileName, + String chopPath, + IFragmentHandler handler, + boolean includeParent){ + try{ + XMLReader parser = setupParser(chopPath, handler, includeParent); + parser.parse(theFileName); + } catch(Exception e) { + e.printStackTrace(); + } + } + + public static void parse(InputSource inputSource, + String chopPath, + IFragmentHandler handler, + boolean includeParent){ + try{ + XMLReader parser = setupParser(chopPath, handler, includeParent); + parser.parse(inputSource); + } catch(Exception e) { + e.printStackTrace(); + } + } + + protected static XMLReader setupParser(String chopPath, + IFragmentHandler handler, + boolean includeParent) throws Exception { + XMLReader parser = XMLReaderFactory.createXMLReader(); + XmlSaxFragmenter fragmenter = new XmlSaxFragmenter(); + fragmenter.setChopPath(chopPath); + fragmenter.setFragmentHandler(handler); + fragmenter.setIncludeParent(includeParent); + parser.setContentHandler(fragmenter); + parser.setErrorHandler(fragmenter); + parser.setFeature("http://xml.org/sax/features/namespace-prefixes", true); + return parser; + } + +} diff --git a/services/common/src/main/java/org/collectionspace/services/common/init/AddIndices.java b/services/common/src/main/java/org/collectionspace/services/common/init/AddIndices.java index 617f20fc7..85416b162 100755 --- a/services/common/src/main/java/org/collectionspace/services/common/init/AddIndices.java +++ b/services/common/src/main/java/org/collectionspace/services/common/init/AddIndices.java @@ -23,7 +23,7 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.List; -import org.collectionspace.services.common.Tools; +import org.collectionspace.services.common.api.Tools; import org.collectionspace.services.common.service.ServiceBindingType; import org.collectionspace.services.common.service.InitHandler.Params.Field; import org.collectionspace.services.common.service.InitHandler.Params.Property; diff --git a/services/common/src/main/java/org/collectionspace/services/common/storage/JDBCTools.java b/services/common/src/main/java/org/collectionspace/services/common/storage/JDBCTools.java index 2b9e9230d..4348ac9de 100755 --- a/services/common/src/main/java/org/collectionspace/services/common/storage/JDBCTools.java +++ b/services/common/src/main/java/org/collectionspace/services/common/storage/JDBCTools.java @@ -18,7 +18,7 @@ package org.collectionspace.services.common.storage; import org.collectionspace.services.common.ServiceMain; -import org.collectionspace.services.common.Tools; +import org.collectionspace.services.common.api.Tools; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocHandlerBase.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocHandlerBase.java index ecc21560b..98ed10ff0 100755 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocHandlerBase.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocHandlerBase.java @@ -30,7 +30,7 @@ import java.util.Iterator; import java.util.List; import org.collectionspace.services.common.ReflectionMapper; -import org.collectionspace.services.common.Tools; +import org.collectionspace.services.common.api.Tools; import org.collectionspace.services.common.service.ListResultField; import org.collectionspace.services.common.service.DocHandlerParams; import org.collectionspace.services.common.service.ServiceBindingType; diff --git a/services/common/src/test/resources/test-data/XmlSaxFragmenter-sample.xml b/services/common/src/test/resources/test-data/XmlSaxFragmenter-sample.xml new file mode 100755 index 000000000..c652b7211 --- /dev/null +++ b/services/common/src/test/resources/test-data/XmlSaxFragmenter-sample.xml @@ -0,0 +1,14 @@ + + + + + In test-data + + + + + + + Male + + diff --git a/services/imports/.project b/services/imports/.project new file mode 100755 index 000000000..38e39f917 --- /dev/null +++ b/services/imports/.project @@ -0,0 +1,17 @@ + + + org.collectionspace.services.imports + + + + + + org.maven.ide.eclipse.maven2Builder + + + + + + org.maven.ide.eclipse.maven2Nature + + diff --git a/services/imports/3rdparty/.project b/services/imports/3rdparty/.project new file mode 100755 index 000000000..7c6ede9cf --- /dev/null +++ b/services/imports/3rdparty/.project @@ -0,0 +1,17 @@ + + + org.collectionspace.services.imports.3rdparty + + + + + + org.maven.ide.eclipse.maven2Builder + + + + + + org.maven.ide.eclipse.maven2Nature + + diff --git a/services/imports/3rdparty/.settings/org.maven.ide.eclipse.prefs b/services/imports/3rdparty/.settings/org.maven.ide.eclipse.prefs new file mode 100644 index 000000000..e2ce08c02 --- /dev/null +++ b/services/imports/3rdparty/.settings/org.maven.ide.eclipse.prefs @@ -0,0 +1,9 @@ +#Fri Aug 27 16:35:21 PDT 2010 +activeProfiles= +eclipse.preferences.version=1 +fullBuildGoals=process-test-resources +includeModules=false +resolveWorkspaceProjects=true +resourceFilterGoals=process-resources resources\:testResources +skipCompilerPlugin=true +version=1 diff --git a/services/imports/3rdparty/build.xml b/services/imports/3rdparty/build.xml new file mode 100755 index 000000000..4ba4cfc58 --- /dev/null +++ b/services/imports/3rdparty/build.xml @@ -0,0 +1,127 @@ + + + + imports service 3rdparty + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/services/imports/3rdparty/nuxeo-platform-cs-imports/.classpath b/services/imports/3rdparty/nuxeo-platform-cs-imports/.classpath new file mode 100644 index 000000000..6fd3b8551 --- /dev/null +++ b/services/imports/3rdparty/nuxeo-platform-cs-imports/.classpath @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/services/imports/3rdparty/nuxeo-platform-cs-imports/.project b/services/imports/3rdparty/nuxeo-platform-cs-imports/.project new file mode 100755 index 000000000..d2c371ceb --- /dev/null +++ b/services/imports/3rdparty/nuxeo-platform-cs-imports/.project @@ -0,0 +1,17 @@ + + org.collectionspace.services.imports.3rdparty.nuxeo + Imports Nuxeo Document Type. NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + + + org.eclipse.jdt.core.javabuilder + + + org.maven.ide.eclipse.maven2Builder + + + + org.eclipse.jdt.core.javanature + org.maven.ide.eclipse.maven2Nature + + \ No newline at end of file diff --git a/services/imports/3rdparty/nuxeo-platform-cs-imports/.settings/org.maven.ide.eclipse.prefs b/services/imports/3rdparty/nuxeo-platform-cs-imports/.settings/org.maven.ide.eclipse.prefs new file mode 100644 index 000000000..e2ce08c02 --- /dev/null +++ b/services/imports/3rdparty/nuxeo-platform-cs-imports/.settings/org.maven.ide.eclipse.prefs @@ -0,0 +1,9 @@ +#Fri Aug 27 16:35:21 PDT 2010 +activeProfiles= +eclipse.preferences.version=1 +fullBuildGoals=process-test-resources +includeModules=false +resolveWorkspaceProjects=true +resourceFilterGoals=process-resources resources\:testResources +skipCompilerPlugin=true +version=1 diff --git a/services/imports/3rdparty/nuxeo-platform-cs-imports/build.xml b/services/imports/3rdparty/nuxeo-platform-cs-imports/build.xml new file mode 100755 index 000000000..6c38f00f1 --- /dev/null +++ b/services/imports/3rdparty/nuxeo-platform-cs-imports/build.xml @@ -0,0 +1,143 @@ + + + + imports nuxeo document type + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/services/imports/3rdparty/nuxeo-platform-cs-imports/pom.xml b/services/imports/3rdparty/nuxeo-platform-cs-imports/pom.xml new file mode 100755 index 000000000..c490c3765 --- /dev/null +++ b/services/imports/3rdparty/nuxeo-platform-cs-imports/pom.xml @@ -0,0 +1,38 @@ + + + + org.collectionspace.services + org.collectionspace.services.imports.3rdparty + 1.5-SNAPSHOT + + + 4.0.0 + org.collectionspace.services + org.collectionspace.services.imports.3rdparty.nuxeo + services.imports.3rdparty.nuxeo + jar + + Imports Nuxeo Document Type + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + src/main/resources/META-INF/MANIFEST.MF + + ${eclipseVersion} + 2 + + + + + + + + diff --git a/services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/META-INF/MANIFEST.MF b/services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/META-INF/MANIFEST.MF new file mode 100755 index 000000000..3185c7c03 --- /dev/null +++ b/services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1,22 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 1 +Bundle-Name: NuxeoCS +Bundle-SymbolicName: org.collectionspace.imports;singleton:=true +Bundle-Version: 1.0.0 +Bundle-Localization: plugin +Bundle-Vendor: Nuxeo +Require-Bundle: org.nuxeo.runtime, + org.nuxeo.ecm.core.api, + org.nuxeo.ecm.core, + org.nuxeo.ecm.core.api, + org.nuxeo.ecm.platform.types.api, + org.nuxeo.ecm.platform.versioning.api, + org.nuxeo.ecm.platform.ui, + org.nuxeo.ecm.platform.forms.layout.client, + org.nuxeo.ecm.platform.ws, + org.collectionspace.collectionspace_core +Provide-Package: org.collectionspace.imports +Nuxeo-Component: OSGI-INF/core-types-contrib.xml, + OSGI-INF/ecm-types-contrib.xml, + OSGI-INF/layouts-contrib.xml + diff --git a/services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/OSGI-INF/core-types-contrib.xml b/services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/OSGI-INF/core-types-contrib.xml new file mode 100755 index 000000000..a84fb449b --- /dev/null +++ b/services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/OSGI-INF/core-types-contrib.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/OSGI-INF/deployment-fragment.xml b/services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/OSGI-INF/deployment-fragment.xml new file mode 100644 index 000000000..88b94ffd1 --- /dev/null +++ b/services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/OSGI-INF/deployment-fragment.xml @@ -0,0 +1,408 @@ + + + + + + ${bundle.fileName} + + + + + nuxeo.war + /nuxeo + + + + + + + + + + + + Seam Context Filter + /ws/FileManageWS + + + + Seam Context Filter + /DocumentManagerWS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #{currentServerLocation.name}/#{currentTabAction.label} + + + + Create new document in #{currentDocument.name} + + + + Create new document in #{currentDocument.name} + + + + breadcrumb=command.user_dashboard + + + + breadcrumb=command.manageMembers + + + + breadcrumb=command.manageMembers + + + + breadcrumb=title.vocabularies + + + + breadcrumb=command.advancedSearch + + + + + + en + en_GB + en_US + fr + de + es + it + ar + ru + ja + vn + + + messages + + + + config/addWorkspace.jpdl.xml + + + + + + generic_error_page + /generic_error_page.xhtml + + + + + generic_message_page + /generic_message_page.xhtml + + + + + home + /nxstartup.xhtml + + + + + user_login + /login.xhtml + + + + + user_logout + /logout.xhtml + + + + + view_servers + /view_servers.xhtml + + + + + + + view_domains + /view_domains.xhtml + + + + + select_document_type + /select_document_type.xhtml + + + + + create_document + /create_document.xhtml + + + + + edit_document + /edit_document.xhtml + + + + + view_documents + /view_documents.xhtml + + + + + create_file + /create_file.xhtml + + + + + create_workspace_wizard + /createWorkspaceWizard.xhtml + + + + + send_email + /document_email.xhtml + + + + + + view_workspaces + /view_workspaces.xhtml + + + + + + create_domain + /create_domain.xhtml + + + + + + edit_domain + /edit_domain.xhtml + + + + + + create_workspace + /create_workspace.xhtml + + + + + + edit_workspace + /edit_workspace.xhtml + + + + + + + members_management + /members_management.xhtml + + + + + view_users + /view_users.xhtml + + + + + view_many_users + /view_many_users.xhtml + + + + + edit_user + /edit_user.xhtml + + + + + edit_user_password + /edit_user_password.xhtml + + + + + view_user + /view_user.xhtml + + + + + create_user + /create_user.xhtml + + + + + view_groups + /view_groups.xhtml + + + + + view_group + /view_group.xhtml + + + + + edit_group + /edit_group.xhtml + + + + + create_group + /create_group.xhtml + + + + + view_vocabularies + /view_vocabularies.xhtml + + + + + view_vocabulary + /view_vocabulary.xhtml + + + + + + + search_form + /search/search_form.xhtml + + + + + search_results_nxql + /search/search_results_nxql.xhtml + + + + + search_results_advanced + + /search/search_results_advanced.xhtml + + + + + + search_results_simple + /search/search_results_simple.xhtml + + + + + + + clipboard + /incl/clipboard.xhtml + + + + + user_dashboard + /user_dashboard.xhtml + + + + + select_workspace_template + /select_workspace_template.xhtml + + + + + pdf_generation_error + /pdf_generation_error.xhtml + + + + + mass_edit + /massedit_documents.xhtml + + + + + mass_edit_confirm + /massedit_documents_preview.xhtml + + + + + + diff --git a/services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/OSGI-INF/ecm-types-contrib.xml b/services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/OSGI-INF/ecm-types-contrib.xml new file mode 100755 index 000000000..5d8d7cc7e --- /dev/null +++ b/services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/OSGI-INF/ecm-types-contrib.xml @@ -0,0 +1,29 @@ + + + + + + + view_documents + + + heading + collectionspace_core + imports + + + + + + Imports + + + + + + Imports + + + + + diff --git a/services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/OSGI-INF/layouts-contrib.xml b/services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/OSGI-INF/layouts-contrib.xml new file mode 100755 index 000000000..1c8ca6dec --- /dev/null +++ b/services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/OSGI-INF/layouts-contrib.xml @@ -0,0 +1,212 @@ + + + + + + + + + + + + + + + importsNumber + borrower + borrowersContact + lendersAuthorizer + lendersAuthorizationDate + lendersContact + + + + + + + importsDate + loanReturnDate + loanRenewalApplicationDate + specialConditionsOfLoan + importsNote + loanPurpose + + + + + + + true + + importsNumber + + + dataInputText + + + + + + + + true + + borrower + + + dataInputText + + + + + + + + true + + borrowersContact + + + dataInputText + + + + + + + + true + + lendersAuthorizer + + + dataInputText + + + + + + + + true + + lendersAuthorizationDate + + + dataInputText + + + + + + + + true + + lendersContact + + + dataInputText + + + + + + + + true + + importsDate + + + dataInputText + + + + + + + + true + + loanReturnDate + + + dataInputText + + + + + + + + true + + loanRenewalApplicationDate + + + dataInputText + + + + + + + + true + + specialConditionsOfLoan + + + dataInputText + + + + + + + + true + + importsNote + + + dataInputText + + + + + + + + true + + loanPurpose + + + dataInputText + + + + + + diff --git a/services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/schemas/imports_common.xsd b/services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/schemas/imports_common.xsd new file mode 100755 index 000000000..c6299df02 --- /dev/null +++ b/services/imports/3rdparty/nuxeo-platform-cs-imports/src/main/resources/schemas/imports_common.xsd @@ -0,0 +1,18 @@ + + + + + + + + + + + + + diff --git a/services/imports/3rdparty/pom.xml b/services/imports/3rdparty/pom.xml new file mode 100755 index 000000000..c526853c0 --- /dev/null +++ b/services/imports/3rdparty/pom.xml @@ -0,0 +1,24 @@ + + + + org.collectionspace.services.imports + org.collectionspace.services + 1.5-SNAPSHOT + + + 4.0.0 + org.collectionspace.services + org.collectionspace.services.imports.3rdparty + services.imports.3rdparty + pom + + + 3rd party build for imports service + + + + nuxeo-platform-cs-imports + + diff --git a/services/imports/build.xml b/services/imports/build.xml new file mode 100755 index 000000000..6307d113e --- /dev/null +++ b/services/imports/build.xml @@ -0,0 +1,124 @@ + + + + imports service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/services/imports/jaxb/.classpath b/services/imports/jaxb/.classpath new file mode 100644 index 000000000..981c9add6 --- /dev/null +++ b/services/imports/jaxb/.classpath @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/services/imports/jaxb/.project b/services/imports/jaxb/.project new file mode 100755 index 000000000..9c5e7b8c3 --- /dev/null +++ b/services/imports/jaxb/.project @@ -0,0 +1,19 @@ + + org.collectionspace.services.imports.jaxb + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + org.collectionspace.services.jaxb + + + + org.eclipse.jdt.core.javabuilder + + + org.maven.ide.eclipse.maven2Builder + + + + org.eclipse.jdt.core.javanature + org.maven.ide.eclipse.maven2Nature + + \ No newline at end of file diff --git a/services/imports/jaxb/.settings/org.maven.ide.eclipse.prefs b/services/imports/jaxb/.settings/org.maven.ide.eclipse.prefs new file mode 100644 index 000000000..c9f07df5d --- /dev/null +++ b/services/imports/jaxb/.settings/org.maven.ide.eclipse.prefs @@ -0,0 +1,9 @@ +#Wed Jan 19 22:49:45 PST 2011 +activeProfiles= +eclipse.preferences.version=1 +fullBuildGoals=process-test-resources +includeModules=false +resolveWorkspaceProjects=true +resourceFilterGoals=process-resources resources\:testResources +skipCompilerPlugin=true +version=1 diff --git a/services/imports/jaxb/pom.xml b/services/imports/jaxb/pom.xml new file mode 100755 index 000000000..fed62754e --- /dev/null +++ b/services/imports/jaxb/pom.xml @@ -0,0 +1,47 @@ + + + + org.collectionspace.services.imports + org.collectionspace.services + 1.5-SNAPSHOT + + + 4.0.0 + org.collectionspace.services + org.collectionspace.services.imports.jaxb + services.imports.jaxb + + + + com.sun.xml.bind + jaxb-impl + + + org.jvnet.jaxb2-commons + property-listener-injector + + + org.jvnet.jaxb2_commons + runtime + + + org.collectionspace.services + org.collectionspace.services.jaxb + ${project.version} + + + + + collectionspace-services-imports-jaxb + install + + + org.jvnet.jaxb2.maven2 + maven-jaxb2-plugin + + + + + diff --git a/services/imports/jaxb/src/main/java/org/collectionspace/services/ImportsJAXBSchema.java b/services/imports/jaxb/src/main/java/org/collectionspace/services/ImportsJAXBSchema.java new file mode 100755 index 000000000..c4b7c411e --- /dev/null +++ b/services/imports/jaxb/src/main/java/org/collectionspace/services/ImportsJAXBSchema.java @@ -0,0 +1,16 @@ +/** + * + */ +package org.collectionspace.services; + +public interface ImportsJAXBSchema { + final static String OBJECT_EXIT_CURRENT_OWNER = "currentOwner"; + final static String OBJECT_EXIT_DEPOSITOR = "depositor"; + final static String OBJECT_EXIT_DATE = "exitDate"; + final static String OBJECT_EXIT_METHODS = "exitMethods"; + final static String OBJECT_EXIT_METHOD = "exitMethod"; + final static String OBJECT_EXIT_NOTE = "exitNote"; + final static String OBJECT_EXIT_NUMBER = "exitNumber"; + final static String OBJECT_EXIT_REASON = "exitReason"; + final static String OBJECT_EXIT_PACKING_NOTE = "packingNote"; +} diff --git a/services/imports/jaxb/src/main/java/org/collectionspace/services/ImportsListItemJAXBSchema.java b/services/imports/jaxb/src/main/java/org/collectionspace/services/ImportsListItemJAXBSchema.java new file mode 100755 index 000000000..ccea4ffed --- /dev/null +++ b/services/imports/jaxb/src/main/java/org/collectionspace/services/ImportsListItemJAXBSchema.java @@ -0,0 +1,9 @@ +package org.collectionspace.services; + +public interface ImportsListItemJAXBSchema { + final static String OBJECT_EXIT_CURRENT_OWNER = "currentOwner"; + final static String OBJECT_EXIT_NUMBER = "exitNumber"; + + final static String CSID = "csid"; + final static String URI = "url"; +} diff --git a/services/imports/jaxb/src/main/resources/imports_common.xsd b/services/imports/jaxb/src/main/resources/imports_common.xsd new file mode 100755 index 000000000..c9008afff --- /dev/null +++ b/services/imports/jaxb/src/main/resources/imports_common.xsd @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/services/imports/pom.xml b/services/imports/pom.xml new file mode 100755 index 000000000..4e218a554 --- /dev/null +++ b/services/imports/pom.xml @@ -0,0 +1,23 @@ + + + + + org.collectionspace.services + org.collectionspace.services.main + 1.5-SNAPSHOT + + + 4.0.0 + org.collectionspace.services + org.collectionspace.services.imports + services.imports + pom + + + jaxb + service + 3rdparty + + + + diff --git a/services/imports/service/.classpath b/services/imports/service/.classpath new file mode 100755 index 000000000..6e90c0fd1 --- /dev/null +++ b/services/imports/service/.classpath @@ -0,0 +1,313 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/services/imports/service/.classpath~ b/services/imports/service/.classpath~ new file mode 100755 index 000000000..209157b7c --- /dev/null +++ b/services/imports/service/.classpath~ @@ -0,0 +1,315 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/services/imports/service/.project b/services/imports/service/.project new file mode 100755 index 000000000..a5e0530df --- /dev/null +++ b/services/imports/service/.project @@ -0,0 +1,28 @@ + + org.collectionspace.services.imports.service + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + org.collectionspace.services.3rdparty.nuxeo.quote-api + org.collectionspace.services.collectionobject.jaxb + org.collectionspace.services.common + org.collectionspace.services.contact.client + org.collectionspace.services.contact.jaxb + org.collectionspace.services.hyperjaxb + org.collectionspace.services.jaxb + org.collectionspace.services.imports.jaxb + org.collectionspace.services.person.client + org.collectionspace.services.person.jaxb + + + + org.eclipse.jdt.core.javabuilder + + + org.maven.ide.eclipse.maven2Builder + + + + org.eclipse.jdt.core.javanature + org.maven.ide.eclipse.maven2Nature + + \ No newline at end of file diff --git a/services/imports/service/.project~ b/services/imports/service/.project~ new file mode 100755 index 000000000..5bf91cf09 --- /dev/null +++ b/services/imports/service/.project~ @@ -0,0 +1,30 @@ + + org.collectionspace.services.imports.service + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + org.collectionspace.services.3rdparty.nuxeo.quote-api + org.collectionspace.services.client + org.collectionspace.services.collectionobject.jaxb + org.collectionspace.services.common + org.collectionspace.services.contact.client + org.collectionspace.services.contact.jaxb + org.collectionspace.services.hyperjaxb + org.collectionspace.services.jaxb + org.collectionspace.services.imports.client + org.collectionspace.services.imports.jaxb + org.collectionspace.services.person.client + org.collectionspace.services.person.jaxb + + + + org.eclipse.jdt.core.javabuilder + + + org.maven.ide.eclipse.maven2Builder + + + + org.eclipse.jdt.core.javanature + org.maven.ide.eclipse.maven2Nature + + \ No newline at end of file diff --git a/services/imports/service/.settings/org.maven.ide.eclipse.prefs b/services/imports/service/.settings/org.maven.ide.eclipse.prefs new file mode 100644 index 000000000..e2ce08c02 --- /dev/null +++ b/services/imports/service/.settings/org.maven.ide.eclipse.prefs @@ -0,0 +1,9 @@ +#Fri Aug 27 16:35:21 PDT 2010 +activeProfiles= +eclipse.preferences.version=1 +fullBuildGoals=process-test-resources +includeModules=false +resolveWorkspaceProjects=true +resourceFilterGoals=process-resources resources\:testResources +skipCompilerPlugin=true +version=1 diff --git a/services/imports/service/pom.xml b/services/imports/service/pom.xml new file mode 100755 index 000000000..018d04d83 --- /dev/null +++ b/services/imports/service/pom.xml @@ -0,0 +1,125 @@ + + + + + org.collectionspace.services + org.collectionspace.services.imports + 1.5-SNAPSHOT + + + 4.0.0 + org.collectionspace.services + org.collectionspace.services.imports.service + services.imports.service + jar + + + + + + + + org.collectionspace.services + org.collectionspace.services.common + ${project.version} + + + org.collectionspace.services + org.collectionspace.services.imports.jaxb + ${project.version} + + + org.collectionspace.services + org.collectionspace.services.collectionobject.jaxb + ${project.version} + + + + junit + junit + 4.1 + test + + + org.testng + testng + 5.6 + + + + + + javax.security + jaas + 1.0.01 + provided + + + + dom4j + dom4j + 1.6.1 + provided + + + + + + org.jboss.resteasy + resteasy-jaxrs + + + tjws + webserver + + + + + org.jboss.resteasy + resteasy-jaxb-provider + + + org.jboss.resteasy + resteasy-multipart-provider + + + + + org.nuxeo.ecm.platform + nuxeo-shell-core + ${nuxeo.platform.version} + + + org.nuxeo.ecm.core + nuxeo-core-api + ${nuxeo.core.version} + + + jboss-remoting + jboss + + + + + + org.restlet + org.restlet + 1.0.7 + + + com.noelios.restlet + com.noelios.restlet.ext.httpclient + 1.0.7 + + + com.noelios.restlet + com.noelios.restlet + 1.0.7 + + + + + collectionspace-services-imports + + + diff --git a/services/imports/service/profiles.xml b/services/imports/service/profiles.xml new file mode 100644 index 000000000..347b9df22 --- /dev/null +++ b/services/imports/service/profiles.xml @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/services/imports/service/src/main/java/org/collectionspace/services/imports/ImportsResource.java b/services/imports/service/src/main/java/org/collectionspace/services/imports/ImportsResource.java new file mode 100755 index 000000000..ce6c85815 --- /dev/null +++ b/services/imports/service/src/main/java/org/collectionspace/services/imports/ImportsResource.java @@ -0,0 +1,227 @@ +/** + * This document is a part of the source code and related artifacts + * for CollectionSpace, an open source collections management system + * for museums and related institutions: + + * http://www.collectionspace.org + * http://wiki.collectionspace.org + + * Copyright 2011 University of California at Berkeley + + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + + * You may obtain a copy of the ECL 2.0 License at + + * https://source.collectionspace.org/collection-space/LICENSE.txt + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.collectionspace.services.imports; + +import org.collectionspace.services.common.FileUtils; +import org.collectionspace.services.common.ResourceBase; +import org.collectionspace.services.common.ServiceMessages; +import org.collectionspace.services.common.api.FileTools; +import org.collectionspace.services.common.api.Tools; +import org.collectionspace.services.common.api.ZipTools; + +// The modified Nuxeo ImportCommand from nuxeo's shell: +import org.collectionspace.services.imports.nuxeo.ImportCommand; +import org.jboss.resteasy.plugins.providers.multipart.InputPart; +import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput; +import org.xml.sax.InputSource; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.util.List; +import java.util.Map; + +/** + * @author Laramie Crocker + */ +@Path(ImportsResource.SERVICE_PATH) +@Produces({"application/xml"}) +@Consumes({"application/xml"}) +public class ImportsResource extends ResourceBase { + + public static final String SERVICE_PATH = "imports"; + public static final String SERVICE_NAME = "imports"; + + @Override + public String getServiceName(){ + return SERVICE_NAME; + } + + @Override + protected String getVersionString() { + final String lastChangeRevision = "$LastChangedRevision: 2108 $"; + return lastChangeRevision; + } + + @Override + //public Class getCommonPartClass() { + public Class getCommonPartClass() { + try { + return Class.forName("org.collectionspace.services.imports.ImportsCommon");//.class; + } catch (ClassNotFoundException e){ + return null; + } + } + + + /* KRUFT: + + 1) here is how you can deal with poxpayloads: + //PoxPayloadIn input = new PoxPayloadIn(xmlPayload); + //ServiceContext ctx = createServiceContext(input); + 2) here are some notes: + //First, save the import request to a local file. + // It may be huge. To accept a stream, send it as an upload request; see acceptUpload() + 3) useful for debugging: + System.out.println("\r\n\r\n\r\n=====================\r\n RUNNING create with xmlPayload: \r\n"+xmlPayload); + */ + + + public static final String TEMPLATE_DIR = "/src/trunk/services/imports/service/src/main/resources/templates"; + + /** you can test this with something like: + * curl -X POST http://localhost:8180/cspace-services/imports -i -u "Admin@collectionspace.org:Administrator" -H "Content-Type: application/xml" -T in.xml + * -T /src/trunk/services/imports/service/src/main/resources/templates/authority-request.xml + */ + @POST + @Consumes("application/xml") + @Produces("application/xml") + public javax.ws.rs.core.Response create(String xmlPayload) { + String result; + javax.ws.rs.core.Response.ResponseBuilder rb; + try { + InputSource inputSource = payloadToInputSource(xmlPayload); + result = createFromInputSource(inputSource); + rb = javax.ws.rs.core.Response.ok(); + } catch (Exception e) { + result = Tools.errorToString(e, true); + rb = javax.ws.rs.core.Response.status(javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + } + rb.entity(result); + return rb.build(); + } + + public static String createFromInputSource(InputSource inputSource) throws Exception { + // We must expand the request and wrap it with all kinds of Nuxeo baggage, which expandXmlPayloadToDir knows how to do. + String outputDir = FileTools.createTmpDir("imports-").getCanonicalPath(); + expandXmlPayloadToDir(inputSource, TEMPLATE_DIR, outputDir); + + // Next, call the nuxeo import service, pointing it to our local directory that has the expanded request. + ImportCommand importCommand = new ImportCommand(); + String destWorkspaces = "/default-domain/workspaces"; + String report = importCommand.run(outputDir, destWorkspaces); + String result = "SUCCESS"+report+""; + return result; + } + + /** @param xmlPayload A request file has a specific format, you can look at: + * trunk/services/imports/service/src/test/resources/requests/authority-request.xml + */ + public static InputSource payloadToInputSource(String xmlPayload) throws Exception { + String requestDir = FileTools.createTmpDir("imports-request-").getCanonicalPath(); + File requestFile = FileTools.saveFile(requestDir, "request.xml", xmlPayload, true); + if (requestFile == null){ + throw new FileNotFoundException("Could not create file in requestDir: "+requestDir); + } + String requestFilename = requestFile.getCanonicalPath(); + InputSource inputSource = new InputSource(requestFilename); + System.out.println("############## REQUEST_FILENAME: "+requestFilename); + return inputSource; + } + + /** This method may be called statically from outside this class; there is a test call in + * org.collectionspace.services.test.ImportsServiceTest + * + * @param inputSource A wrapper around a request file, either a local file or a stream; + * the file has a specific format, you can look at: + * trunk/services/imports/service/src/test/resources/requests/authority-request.xml + * @param templateDir The local directory where templates are to be found at runtime. + * @param outputDir The local directory where expanded files and directories are found, ready to be passed to the Nuxeo importer. + */ + public static void expandXmlPayloadToDir(InputSource inputSource, String templateDir, String outputDir) throws Exception { + System.out.println("############## TEMPLATE_DIR: "+templateDir); + System.out.println("############## OUTPUT_DIR:"+outputDir); + TemplateExpander.expandInputSource(templateDir, outputDir, inputSource, "/imports/import"); + } + + /** you can test like this: + * curl -F "file=@out.zip;type=application/zip" --basic -u "Admin@collectionspace.org:Administrator" http://localhost:8280/cspace-services/imports + */ + @POST + @Consumes("multipart/form-data") + @Produces("application/xml") + public javax.ws.rs.core.Response acceptUpload(@Context HttpServletRequest req, + MultipartFormDataInput partFormData) { + javax.ws.rs.core.Response response = null; + StringBuffer resultBuf = new StringBuffer(); + try { + InputStream fileStream = null; + String preamble = partFormData.getPreamble(); + System.out.println("Preamble type is:" + preamble); + Map> partsMap = partFormData.getFormDataMap(); + List fileParts = partsMap.get("file"); + for (InputPart part : fileParts){ + String mediaType = part.getMediaType().toString(); + System.out.println("Media type is:" + mediaType); + if (mediaType.equalsIgnoreCase("text/xml")){ + InputSource inputSource = new InputSource(part.getBody(InputStream.class, null)); + String result = createFromInputSource(inputSource); + resultBuf.append(result); + continue; + } + if (mediaType.equalsIgnoreCase("application/zip")){ + fileStream = part.getBody(InputStream.class, null); + + File zipfile = FileUtils.createTmpFile(fileStream, getServiceName() + "_"); + String zipfileName = zipfile.getCanonicalPath(); + System.out.println("Imports zip file saved to:" + zipfileName); + + String baseOutputDir = FileTools.createTmpDir("imports-").getCanonicalPath(); + File indir = new File(baseOutputDir+"/in"); + indir.mkdir(); + ZipTools.unzip(zipfileName, indir.getCanonicalPath()); + String result = "\r\nZipfile " + zipfileName + "extracted to: " + indir.getCanonicalPath()+""; + System.out.println(result); + + long start = System.currentTimeMillis(); + //TODO: now call import service... + resultBuf.append(result); + continue; + } + } + javax.ws.rs.core.Response.ResponseBuilder rb = javax.ws.rs.core.Response.ok(); + rb.entity(resultBuf.toString()); + response = rb.build(); + } catch (Exception e) { + throw bigReThrow(e, ServiceMessages.CREATE_FAILED); + } + return response; + } + + String page = "
" + + "Choose a file to import:
"; + @GET + @Produces("text/html") + public String getInputForm(@QueryParam("form") String form) { + return page; + } +} diff --git a/services/imports/service/src/main/java/org/collectionspace/services/imports/ImportsResource.java~ b/services/imports/service/src/main/java/org/collectionspace/services/imports/ImportsResource.java~ new file mode 100755 index 000000000..fc83ed44e --- /dev/null +++ b/services/imports/service/src/main/java/org/collectionspace/services/imports/ImportsResource.java~ @@ -0,0 +1,59 @@ +/** + * This document is a part of the source code and related artifacts + * for CollectionSpace, an open source collections management system + * for museums and related institutions: + + * http://www.collectionspace.org + * http://wiki.collectionspace.org + + * Copyright 2009 University of California at Berkeley + + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + + * You may obtain a copy of the ECL 2.0 License at + + * https://source.collectionspace.org/collection-space/LICENSE.txt + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.collectionspace.services.imports; + +import org.collectionspace.services.client.ImportsClient; +import org.collectionspace.services.common.ResourceBase; + +import javax.ws.rs.Consumes; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; + +@Path(ImportsClient.SERVICE_PATH) +@Produces({"application/xml"}) +@Consumes({"application/xml"}) +public class ImportsResource extends ResourceBase { + + @Override + public String getServiceName(){ + return ImportsClient.SERVICE_NAME; + } + + @Override + protected String getVersionString() { + final String lastChangeRevision = "$LastChangedRevision: 2108 $"; + return lastChangeRevision; + } + + @Override + //public Class getCommonPartClass() { + public Class getCommonPartClass() { + try { + return Class.forName("org.collectionspace.services.imports.ImportsCommon");//.class; + } catch (ClassNotFoundException e){ + return null; + } + } + +} diff --git a/services/imports/service/src/main/java/org/collectionspace/services/imports/TemplateExpander.java b/services/imports/service/src/main/java/org/collectionspace/services/imports/TemplateExpander.java new file mode 100755 index 000000000..f98d7ce09 --- /dev/null +++ b/services/imports/service/src/main/java/org/collectionspace/services/imports/TemplateExpander.java @@ -0,0 +1,165 @@ +/** + * This document is a part of the source code and related artifacts + * for CollectionSpace, an open source collections management system + * for museums and related institutions: + + * http://www.collectionspace.org + * http://wiki.collectionspace.org + + * Copyright 2011 University of California at Berkeley + + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + + * You may obtain a copy of the ECL 2.0 License at + + * https://source.collectionspace.org/collection-space/LICENSE.txt + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.collectionspace.services.imports; + +import java.io.*; +import java.util.UUID; + +import org.collectionspace.services.common.IFragmentHandler; +import org.collectionspace.services.common.XmlSaxFragmenter; +import org.collectionspace.services.common.api.FileTools; +import org.collectionspace.services.common.api.Tools; +import org.dom4j.Document; +import org.dom4j.Element; +import org.hibernate.sql.Template; +import org.testng.annotations.Test; +import org.xml.sax.InputSource; + +/** This class expands templates specifically for the imports service. + * + * To see capability to create workspaces, see svn revision 4346 on branch + * https://source.collectionspace.org/collection-space/src/services/branches/CSPACE-3178/services + * This capability was removed, as it was necessary for testing only. + * + * @author Laramie Crocker + */ +public class TemplateExpander { + + protected static String var(String theVar){ + return "\\$\\{"+theVar+"\\}"; + } + + /** + * @param source the template, which contains variables wrapped in a dollar sign and curly braces, e.g. source="my template with ID ${docID} yada yada." + * @param theVar a variable name, without the dollar sign or curly braces or internal quotes, e.g. searchAndReplaceVar(source, "docID", "1234-5678") + * @param replace the value the variable will be replaced with. + * @return the expanded template. + */ + public static String searchAndReplaceVar(String source, String theVar, String replace){ + return Tools.searchAndReplace(source, var(theVar), replace); + } + + public static String doOneService(String outDir, String partTmpl, String wrapperTmpl, + String SERVICE_TYPE, String SERVICE_NAME, String CSID) throws Exception { + String docID; + if (Tools.notBlank(CSID)){ + docID = CSID; + } else { + docID = UUID.randomUUID().toString(); + } + String part = Tools.searchAndReplace(partTmpl, var("docID"), docID); + + wrapperTmpl = Tools.searchAndReplace(wrapperTmpl, var("Schema"), part); + wrapperTmpl = Tools.searchAndReplace(wrapperTmpl, var("docID"), docID); + wrapperTmpl = Tools.searchAndReplace(wrapperTmpl, var("ServiceType"), SERVICE_TYPE); + wrapperTmpl = Tools.searchAndReplace(wrapperTmpl, var("ServiceName"), SERVICE_NAME); + //TODO: set timestamp via creating a ${created} variable. + + String serviceDir = outDir+'/'+docID; + FileTools.saveFile(serviceDir, "document.xml", wrapperTmpl, true/*true=create parent dirs*/); + return docID; + } + + + /** Once you have called createWorkspace() to create a home for documents of a service, you can call this method to add documents for that service. + * + * Internally, this method also gets called by the XmlSaxFragmenter callback via the public inner class FragmentHandlerImpl. + * + * @param partTmpl A template file that contains the schema part for the service, and which has macros such as ${docID} to be expanded. + * @param SERVICE_NAME The name of the service, such as "Personauthorities" + * @param SERVICE_TYPE The Nuxeo document type, such as "Personauthority" + * @param TEMPLATE_DIR The local filesystem location of all the standard templates that wrap up workspace documents; + * once expanded, these spit out Nuxeo import format. + * @param CSID An optional parameter which forces the document CSID, otherwise the CSID is set to a random UUID. + * @throws Exception + */ + public static void createDocInWorkspace(String partTmpl, + String SERVICE_NAME, + String SERVICE_TYPE, + String TEMPLATE_DIR, + String OUTPUT_DIR, + String CSID) throws Exception { + String wrapperTmpl = FileTools.readFile(TEMPLATE_DIR,"service-document.xml"); + String outputDir = OUTPUT_DIR+'/'+SERVICE_NAME; + doOneService(outputDir, partTmpl, wrapperTmpl, SERVICE_TYPE, SERVICE_NAME, CSID); + } + + public static void expand(String TEMPLATE_DIR, String outputDir, String requestFilename, String chopPath){ + FragmentHandlerImpl callback = new FragmentHandlerImpl(TEMPLATE_DIR, outputDir); + XmlSaxFragmenter.parse(requestFilename, chopPath, callback, false); + } + + public static void expandInputSource(String TEMPLATE_DIR, String outputDir, InputSource requestSource, String chopPath){ + FragmentHandlerImpl callback = new FragmentHandlerImpl(TEMPLATE_DIR, outputDir); + XmlSaxFragmenter.parse(requestSource, chopPath, callback, false); + } + + /** This inner class is the callback target for calls to XmlSaxFragmenter, for example: + * FragmentHandlerImpl callback = new FragmentHandlerImpl(); + * XmlSaxFragmenter.parse(filename, "/imports/import", callback, false); + * It will be called for every /imports/import in the file: + * <import ID="1" service="Personauthorities" type="Personauthority"> + */ + public static class FragmentHandlerImpl implements IFragmentHandler { + //============IFragmentHandler=========================================================== + public void onFragmentReady(Document context, Element fragmentParent, String currentPath, int fragmentIndex, String fragment){ + try { + dump(context, currentPath, fragmentIndex, fragment); + String serviceName = checkAttribute(fragmentParent, "service", SERVICE_NAME); + String serviceType = checkAttribute(fragmentParent, "type", SERVICE_TYPE); + String CSID = fragmentParent.attributeValue("CSID"); + TemplateExpander.createDocInWorkspace(fragment, serviceName, serviceType, TEMPLATE_DIR, OUPUT_DIR, CSID); + } catch (Exception e){ + System.err.println("ERROR calling expandXmlPayloadToDir"+e); + e.printStackTrace(); + } + } + public void onEndDocument(Document document, int fragmentCount){ + System.out.println("====TemplateExpander DONE============\r\n"+ XmlSaxFragmenter.prettyPrint(document)+"================"); + } + //============helper methods============================================================== + public FragmentHandlerImpl(String templateDir, String outputDir){ + TEMPLATE_DIR = templateDir; + OUPUT_DIR = outputDir; + } + public String SERVICE_NAME = ""; //You can provide a default. + public String SERVICE_TYPE = ""; //You can provide a default. + public String TEMPLATE_DIR = ""; //You MUST provide a default via constructor. + public String OUPUT_DIR = ""; //You MUST provide a default via constructor. + private String checkAttribute(Element fragmentParent, String attName, String defaultVal){ + String val = fragmentParent.attributeValue(attName); + if (Tools.notEmpty(val)){ + return val; + } + return defaultVal; + } + private void dump(Document context, String currentPath, int fragmentIndex, String fragment){ + System.out.println("====Path============\r\n"+currentPath+'['+fragmentIndex+']'); + System.out.println("====Context=========\r\n"+ XmlSaxFragmenter.prettyPrint(context)); + System.out.println("====Fragment========\r\n"+fragment+"\r\n===================\r\n"); + } + } + +} diff --git a/services/imports/service/src/main/java/org/collectionspace/services/imports/nuxeo/ImportCommand.java b/services/imports/service/src/main/java/org/collectionspace/services/imports/nuxeo/ImportCommand.java new file mode 100755 index 000000000..68a4c1ef4 --- /dev/null +++ b/services/imports/service/src/main/java/org/collectionspace/services/imports/nuxeo/ImportCommand.java @@ -0,0 +1,56 @@ +package org.collectionspace.services.imports.nuxeo; + +import java.io.File; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.collectionspace.services.nuxeo.client.java.NuxeoConnector; +import org.nuxeo.ecm.core.api.repository.RepositoryInstance; +import org.nuxeo.ecm.core.client.NuxeoClient; +import org.nuxeo.ecm.core.io.DocumentPipe; +import org.nuxeo.ecm.core.io.DocumentReader; +import org.nuxeo.ecm.core.io.DocumentWriter; +import org.nuxeo.ecm.core.io.impl.DocumentPipeImpl; +import org.nuxeo.ecm.core.io.impl.plugins.DocumentModelWriter; +// we use our own override of this: import org.nuxeo.ecm.core.io.impl.plugins.XMLDirectoryReader; + +// based loosely on package org.nuxeo.ecm.shell.commands.io.ImportCommand; +public class ImportCommand { + private static final Log log = LogFactory.getLog(ImportCommand.class); + + public String run(String src, String dest) throws Exception { + File file = new File(src); + ///cspace way of configuring client and auth: + NuxeoClient client = NuxeoConnector.getInstance().getClient(); + RepositoryInstance repository = client.openRepository(); + try { + return importTree(repository, file, dest); + } finally { + repository.close(); + } + } + + String importTree(RepositoryInstance repository, File file, String toPath) throws Exception { + DocumentReader reader = null; + DocumentWriter writer = null; + String dump = "NO RESULTS"; + try { + System.out.println("importTree reading file: "+file+(file!=null ? " exists? "+file.exists() : " file param is null")); + reader = new LoggedXMLDirectoryReader(file); //our overload of XMLDirectoryReader. + writer = new DocumentModelWriter(repository, toPath, 10); + DocumentPipe pipe = new DocumentPipeImpl(10); + // pipe.addTransformer(transformer); + pipe.setReader(reader); + pipe.setWriter(writer); + pipe.run(); + } finally { + if (reader != null) { + reader.close(); + dump = ((LoggedXMLDirectoryReader)reader).report(); + } + if (writer != null) { + writer.close(); + } + } + return dump; + } +} \ No newline at end of file diff --git a/services/imports/service/src/main/java/org/collectionspace/services/imports/nuxeo/ImportsDocumentModelHandler.java b/services/imports/service/src/main/java/org/collectionspace/services/imports/nuxeo/ImportsDocumentModelHandler.java new file mode 100755 index 000000000..27a24f334 --- /dev/null +++ b/services/imports/service/src/main/java/org/collectionspace/services/imports/nuxeo/ImportsDocumentModelHandler.java @@ -0,0 +1,32 @@ +/** + * This document is a part of the source code and related artifacts + * for CollectionSpace, an open source collections management system + * for museums and related institutions: + + * http://www.collectionspace.org + * http://wiki.collectionspace.org + + * Copyright 2011 University of California at Berkeley + + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + + * You may obtain a copy of the ECL 2.0 License at + + * https://source.collectionspace.org/collection-space/LICENSE.txt + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.collectionspace.services.imports.nuxeo; + +import org.collectionspace.services.nuxeo.client.java.DocHandlerBase; +import org.collectionspace.services.imports.ImportsCommon; + +public class ImportsDocumentModelHandler + extends DocHandlerBase { +} + diff --git a/services/imports/service/src/main/java/org/collectionspace/services/imports/nuxeo/LoggedXMLDirectoryReader.java b/services/imports/service/src/main/java/org/collectionspace/services/imports/nuxeo/LoggedXMLDirectoryReader.java new file mode 100755 index 000000000..125976ff2 --- /dev/null +++ b/services/imports/service/src/main/java/org/collectionspace/services/imports/nuxeo/LoggedXMLDirectoryReader.java @@ -0,0 +1,134 @@ +package org.collectionspace.services.imports.nuxeo; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.io.SAXReader; +import org.nuxeo.common.utils.FileTreeIterator; +import org.nuxeo.common.utils.FileUtils; +import org.nuxeo.common.utils.Path; +import org.nuxeo.ecm.core.api.impl.blob.StreamingBlob; +import org.nuxeo.ecm.core.io.ExportConstants; +import org.nuxeo.ecm.core.io.ExportedDocument; +import org.nuxeo.ecm.core.io.impl.AbstractDocumentReader; +import org.nuxeo.ecm.core.io.impl.ExportedDocumentImpl; +import org.nuxeo.ecm.core.io.impl.plugins.XMLDirectoryReader; +import org.nuxeo.runtime.services.streaming.FileSource; + +public class LoggedXMLDirectoryReader extends AbstractDocumentReader { + + protected Document loadXML(File file) throws IOException { + String filename = file.getCanonicalPath(); + System.out.println("~~~~~~~~~~~~~~~~~~~ LoggedXMLDirectoryReader :: "+filename); + BufferedInputStream in = null; + try { + in = new BufferedInputStream(new FileInputStream(file)); + System.out.println("~~~~~~~~~~~~~~~~~~~ LoggedXMLDirectoryReader :: "+filename+" :: DONE"); + reportList.add("READ: "+filename); + return new SAXReader().read(in); + } catch (DocumentException e) { + IOException ioe = new IOException("Failed to read file document " + + file + ": " + e.getMessage()); + ioe.setStackTrace(e.getStackTrace()); + System.out.println("~~~~~~~~~~~~~~~~~~~ LoggedXMLDirectoryReader :: "+filename+" :: ERROR"); + reportList.add("ERROR: "+filename); + throw ioe; + } finally { + if (in != null) { + in.close(); + } + } + } + + private File source; + + private FileTreeIterator iterator; + + public LoggedXMLDirectoryReader(String sourcePath) { + this(new File(sourcePath)); + } + + public LoggedXMLDirectoryReader(File source) { + this.source = source; + iterator = new FileTreeIterator(source); + iterator.setFilter(new FileFilter() { + public boolean accept(File pathname) { + return pathname.isDirectory(); + } + }); + } + + public Object getSource() { + return source; + } + + public void setSource(File source) { + this.source = source; + } + + public void close() { + source = null; + iterator = null; + } + + private List reportList = new ArrayList(); + public String report(){ + StringBuffer result = new StringBuffer(); + for (String s: reportList){ + result.append(s).append("\r\n"); + } + return result.toString(); + } + + + @Override + public ExportedDocument read() throws IOException { + if (iterator.hasNext()) { + File dir = iterator.next(); + if (dir == null) { + return null; + } + // read document files + ExportedDocument xdoc = new ExportedDocumentImpl(); + for (File file : dir.listFiles()) { + if (file.isFile()) { + String name = file.getName(); + if (ExportConstants.DOCUMENT_FILE.equals(name)) { + Document doc = loadXML(file); + xdoc.setDocument(doc); + Path relPath = computeRelativePath(dir); + xdoc.setPath(relPath); + reportList.add(relPath.toString()); + } else if (name.endsWith(".xml")) { + xdoc.putDocument( + FileUtils.getFileNameNoExt(file.getName()), + loadXML(file)); + } else { // presume a blob + xdoc.putBlob(file.getName(), new StreamingBlob( + new FileSource(file))); + } + } + } + return xdoc; + } + return null; + } + + /*NXP-1688 Rux: the path was somehow left over when migrated from + core 1.3.4 to 1.4.0. Pull back.*/ + private Path computeRelativePath(File file) { + /*NXP-2507 Rux: preserve directory structure with slashes instead OS name separator*/ + String subPathS = + file.getAbsolutePath().substring(source.getAbsolutePath().length()); + subPathS = subPathS.replace(File.separatorChar, '/'); + return new Path(subPathS); + } + +} \ No newline at end of file diff --git a/services/imports/service/src/main/resources/templates/authority-request-naturalhistory.xml b/services/imports/service/src/main/resources/templates/authority-request-naturalhistory.xml new file mode 100755 index 000000000..c234556ae --- /dev/null +++ b/services/imports/service/src/main/resources/templates/authority-request-naturalhistory.xml @@ -0,0 +1,27 @@ + + + + + + In test-data + + + Perf Test Person Auth ${docID} + perfTestPersons-${docID} + PersonAuthority + urn:cspace:collectionspace.org:Personauthorities(perfTestPersons)'Perf Test Person Auth' + + + + + + In test-data + + + Perf Test Person Auth ${docID} + perfTestPersons-${docID} + PersonAuthority + urn:cspace:collectionspace.org:Personauthorities(perfTestPersons)'Perf Test Person Auth' + + + \ No newline at end of file diff --git a/services/imports/service/src/main/resources/templates/authority.xml b/services/imports/service/src/main/resources/templates/authority.xml new file mode 100755 index 000000000..43ba4cfa0 --- /dev/null +++ b/services/imports/service/src/main/resources/templates/authority.xml @@ -0,0 +1,51 @@ + + + + ${ServiceType} + ${ServiceName}/${docID} + undefined + undefined + + + + + + + + + Administrator + + Administrator + + + 2011-03-05T00:06:17Z + + + + + + + 2011-03-05T00:06:17Z + + + + + + + + + + + + 2011-03-05T00:06:17Z + 2011-03-05T00:06:17Z + 1 + + ${Schema} + + diff --git a/services/imports/service/src/main/resources/templates/person.xml b/services/imports/service/src/main/resources/templates/person.xml new file mode 100755 index 000000000..af03c0768 --- /dev/null +++ b/services/imports/service/src/main/resources/templates/person.xml @@ -0,0 +1,51 @@ + + + + Person + Persons/${docID} + undefined + undefined + + + + + + + + + Administrator + + Administrator + + + 2011-03-05T00:06:18Z + + + + + + + 2011-03-05T00:06:18Z + + + + + + + + + + + + 2011-03-05T00:06:18Z + 2011-03-05T00:06:18Z + 1 + + ${personsSchema} + + diff --git a/services/imports/service/src/main/resources/templates/personauthorities-part.xml b/services/imports/service/src/main/resources/templates/personauthorities-part.xml new file mode 100755 index 000000000..fbff6ed84 --- /dev/null +++ b/services/imports/service/src/main/resources/templates/personauthorities-part.xml @@ -0,0 +1,7 @@ + + Perf Test Person Auth ${docID} + perfTestPersons-${docID} + PersonAuthority + urn:cspace:collectionspace.org:Personauthorities(perfTestPersons)'Perf Test Person Auth' + + diff --git a/services/imports/service/src/main/resources/templates/personauthorities-workspace-document.xml b/services/imports/service/src/main/resources/templates/personauthorities-workspace-document.xml new file mode 100755 index 000000000..8e9a26841 --- /dev/null +++ b/services/imports/service/src/main/resources/templates/personauthorities-workspace-document.xml @@ -0,0 +1,65 @@ + + + Workspace + ${ServiceName} + project + default + + + + + + + + + Administrator + + Administrator + + + 2011-03-04T23:51:05Z + A CollectionSpace workspace for ${ServiceName} + + + + + + 2011-03-04T23:51:05Z + + + + ${ServiceName} + + + + + + /icons/workspace.gif + + + + + + + + + + + + sites + + + + + + workspace + ${ServiceName} + aposteriori + ${ServiceName} + + + + + + + diff --git a/services/imports/service/src/main/resources/templates/service-document.xml b/services/imports/service/src/main/resources/templates/service-document.xml new file mode 100755 index 000000000..9fcf69b6a --- /dev/null +++ b/services/imports/service/src/main/resources/templates/service-document.xml @@ -0,0 +1,45 @@ + + + ${ServiceType} + ${ServiceName}/${docID} + undefined + undefined + + + + + + + + + Administrator + + Administrator + + + 2011-03-05T00:06:17Z + + + + + + + 2011-03-05T00:06:17Z + + + + + + + + + + + + 2011-03-05T00:06:17Z + 2011-03-05T00:06:17Z + 1 + + ${Schema} + + diff --git a/services/imports/service/src/main/resources/templates/workspace-document.xml b/services/imports/service/src/main/resources/templates/workspace-document.xml new file mode 100755 index 000000000..8e9a26841 --- /dev/null +++ b/services/imports/service/src/main/resources/templates/workspace-document.xml @@ -0,0 +1,65 @@ + + + Workspace + ${ServiceName} + project + default + + + + + + + + + Administrator + + Administrator + + + 2011-03-04T23:51:05Z + A CollectionSpace workspace for ${ServiceName} + + + + + + 2011-03-04T23:51:05Z + + + + ${ServiceName} + + + + + + /icons/workspace.gif + + + + + + + + + + + + sites + + + + + + workspace + ${ServiceName} + aposteriori + ${ServiceName} + + + + + + + diff --git a/services/imports/service/src/test/java/org/collectionspace/services/test/ImportsServiceTest.java b/services/imports/service/src/test/java/org/collectionspace/services/test/ImportsServiceTest.java new file mode 100755 index 000000000..89239a0e9 --- /dev/null +++ b/services/imports/service/src/test/java/org/collectionspace/services/test/ImportsServiceTest.java @@ -0,0 +1,65 @@ +/** + * This document is a part of the source code and related artifacts + * for CollectionSpace, an open source collections management system + * for museums and related institutions: + + * http://www.collectionspace.org + * http://wiki.collectionspace.org + + * Copyright 2011 University of California at Berkeley + + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + + * You may obtain a copy of the ECL 2.0 License at + + * https://source.collectionspace.org/collection-space/LICENSE.txt + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.collectionspace.services.test; + +import org.collectionspace.services.common.IFragmentHandler; +import org.collectionspace.services.common.XmlSaxFragmenter; +import org.collectionspace.services.common.api.FileTools; +import org.collectionspace.services.common.api.Tools; +import org.collectionspace.services.imports.ImportsResource; +import org.collectionspace.services.imports.TemplateExpander; +import org.dom4j.Document; +import org.dom4j.Element; +import org.restlet.util.Template; +import org.testng.annotations.Test; +import org.xml.sax.InputSource; + +import java.io.File; + +/** Run this with something like: + * cd C:\src\trunk\services\imports\service + * mvn test -Dtest=ImportsServiceTest + */ +public class ImportsServiceTest { + //These paths won't work when deployed in jboss, but they will work in the build in the source tree, which is what this test is for. + public static final String TEMPLATES_REL_DIR_TO_MODULE = "./src/main/resources/templates"; + public static final String REQUESTS_REL_DIR_TO_MODULE = "./src/test/resources/requests"; + + /** this test just attempts to expand a single file upload to nuxeo's import/export file/directory format, + * but does not do the import, so that this test may be run without a nuxeo instance running. + * @throws Exception + */ + @Test + public void testImports() throws Exception { + String TEMPLATE_DIR = (new File(TEMPLATES_REL_DIR_TO_MODULE)).getCanonicalPath(); + String REQUESTS_DIR = (new File(REQUESTS_REL_DIR_TO_MODULE)).getCanonicalPath(); + String outputDir = FileTools.createTmpDir("imports-test-").getCanonicalPath(); + + String xmlPayload = FileTools.readFile(REQUESTS_DIR,"authority-request.xml"); + InputSource inputSource = ImportsResource.payloadToInputSource(xmlPayload); + ImportsResource.expandXmlPayloadToDir(inputSource, TEMPLATE_DIR, outputDir); + + //TODO: inspect dir, then *cleanup*!! + } +} diff --git a/services/imports/service/src/test/resources/log4j.xml b/services/imports/service/src/test/resources/log4j.xml new file mode 100644 index 000000000..52121cb83 --- /dev/null +++ b/services/imports/service/src/test/resources/log4j.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/services/imports/service/src/test/resources/requests/authority-request.xml b/services/imports/service/src/test/resources/requests/authority-request.xml new file mode 100755 index 000000000..682ad9f5c --- /dev/null +++ b/services/imports/service/src/test/resources/requests/authority-request.xml @@ -0,0 +1,20 @@ + + + + + + Perf Test Person Auth ${docID} + perfTestPersons-${docID} + PersonAuthority + urn:cspace:collectionspace.org:Personauthorities(perfTestPersons)'Perf Test Person Auth' + + + + + Perf Test Person Auth ${docID} + perfTestPersons-${docID} + PersonAuthority + urn:cspace:collectionspace.org:Personauthorities(perfTestPersons)'Perf Test Person Auth' + + + \ No newline at end of file diff --git a/services/imports/service/src/test/resources/requests/collectionobject-request.xml b/services/imports/service/src/test/resources/requests/collectionobject-request.xml new file mode 100755 index 000000000..1906410c1 --- /dev/null +++ b/services/imports/service/src/test/resources/requests/collectionobject-request.xml @@ -0,0 +1,282 @@ + + + + + + + + + + + + + + + + + public + + + + + + + The Ogres hand + + + + urn:cspace:org.collectionspace.demo:personauthority:name(person):person:name(maryannecasseta)'Mary+Anne+Cassata' + + Big symbol at the base + + + + 78 + record-speed + rpm + + + No Idea + + + + It could mean a lot of things, but oddly no connection to ogres + + + + urn:cspace:org.collectionspace.demo:orgauthority:name(organization):organization:name(boardwalkrecords)'Boardwalk+Records' + + + + + + sleeve + + + + + + + + + + + + + + + + 1 + poundsterling + + + + + + + 123-bg-192 + + + + + + A petrified Ogre found in the woods of Neverland + Or it could be a petrified tree looking slightly like an ogre + Or just a rock, looking a lot like a petrified tree + + arabic + + + + + + + These object records are tedious to fill out + Content of a piece of rock?! .. well there might be diamonds and petrified fish in it + urn:cspace:org.collectionspace.demo:personauthority:name(person):person:name(reginabadet)'Regina+Badet' + + + + + + + + + + + + + + + It's pretty big - the size of an ogre.. Three arms and a hump-back + + + years + + + + + + + + + + pst., it's not a real ogre + +
+
+ + Non, c'est vrai! Je ne suis pas une baguette + + + none + + + urn:cspace:org.collectionspace.demo:orgauthority:name(organization):organization:name(7-eleven)'7-Eleven' + + label + I'm a vegetarian + CompleteObject001 + bottom + No, it's true, I'm not a baguette + + decoration + + + + + + + urn:cspace:org.collectionspace.demo:orgauthority:name(organization):organization:name(wolperorganization)'Wolper+Organization' + + exchange + + + .. But it wasn't + 10223 + study-collection + Made out of rock, pretty big + + fieldCollectionEventName + + urn:cspace:org.collectionspace.demo:orgauthority:name(organization):organization:name(screenmagicinc.)'Screen+Magic+Inc.' + + urn:cspace:org.collectionspace.demo:personauthority:name(person):person:name(gingerrogers)'Ginger+Rogers' + + + + + urn:cspace:org.collectionspace.demo:personauthority:name(person):person:name(virginiaboardman)'Virginia+Boardman' + + + Haven't really contributed with much + Should have gone with an automagic solution + Someone found it, then gave it to a museum, duh! + 1 + + + Petrified Ogre + klingon + waka waka + generic + swahili + + + base + + + Probably a horrible one, considering how uninteresting this object is + + + + + + Seriously guys, it's just a piece of rock + + + adult + + + current + french + + nomenclature + simple + Je ne suis pas une baguette + subgroup + + + + + + + + + You got the basic details down - it was horrible, what else can I say + + + + + + + + + + + + + + + associated act. note + + + + + \"yeah, that was pretty horrible\", viewer, 1982 + + + + + Dont know what viewers role is + in-process + Document + + + + + + + + + + + + open + + 189 + + + + + + + gothic-script + female + + + + rocky balboa rocks + It is not gold + + + + + + + antiquities + decorative-arts + ethnography + +
+
+
\ No newline at end of file diff --git a/services/person/service/src/main/java/org/collectionspace/services/person/nuxeo/PersonValidatorHandler.java b/services/person/service/src/main/java/org/collectionspace/services/person/nuxeo/PersonValidatorHandler.java index b32293873..ade5d8457 100644 --- a/services/person/service/src/main/java/org/collectionspace/services/person/nuxeo/PersonValidatorHandler.java +++ b/services/person/service/src/main/java/org/collectionspace/services/person/nuxeo/PersonValidatorHandler.java @@ -51,7 +51,7 @@ package org.collectionspace.services.person.nuxeo; import java.util.regex.Pattern; -import org.collectionspace.services.common.Tools; +import org.collectionspace.services.common.api.Tools; import org.collectionspace.services.person.PersonsCommon; import org.collectionspace.services.common.context.MultipartServiceContext; import org.collectionspace.services.common.context.ServiceContext; diff --git a/services/pom.xml b/services/pom.xml index 2cfe2aff9..3dc110364 100644 --- a/services/pom.xml +++ b/services/pom.xml @@ -28,6 +28,7 @@ hyperjaxb common authorization-mgt + common-api common-test account note -- 2.47.3