From 2c2eafa048fb593373b8a60531840083811744ba Mon Sep 17 00:00:00 2001 From: Patrick Schmitz Date: Sat, 10 Dec 2011 03:04:20 +0000 Subject: [PATCH] CSPACE-2323, CSPACE-3016, etc., Fixes to properly integrate with new Nuxeo libs, making code clean w.r.t. sessions, fixes to hierarchy handling in authorities. Changed logging configuration to rotate among 10 files of 5MB each, so we have more context on the server. Also removed the stdout copy that was bloating catalina.out (on 1.13 QA, the file is over 1.1GB). Added new tests to exercise refObjs and authRefs more carefully. Tweaked XMLReplay to output clock times for each test, making it easier to align tests with log output. Added some debug support for startup issues with Nuxeo and Workspaces. Removed pointless output from LoanoutValidatorHandler. --- .../IntegrationTests/xmlreplay/XmlReplay.java | 9 +- .../test-data/xmlreplay/authrefs/authrefs.xml | 11 - .../xmlreplay/authrefs/authrefsSimple.xml | 2 +- .../xmlreplay/authrefs/authrefsSimple2.xml | 62 +++++ .../test-data/xmlreplay/authrefs/loanin.xml | 15 ++ .../xmlreplay/authrefs/res/refObjs.res.xml | 6 + .../src/main/resources/log4j.properties | 10 +- .../common/vocabulary/AuthorityResource.java | 41 ++- .../AuthorityItemDocumentModelHandler.java | 251 ++++++++++++++---- .../services/batch/BatchResource.java | 89 +------ .../nuxeo/BatchDocumentModelHandler.java | 153 +++++++++++ .../services/common/ResourceBase.java | 11 +- .../common/repository/RepositoryClient.java | 4 +- .../common/security/SecurityInterceptor.java | 8 +- .../vocabulary/RefNameServiceUtils.java | 9 +- .../java/RemoteDocumentModelHandlerImpl.java | 53 ++++ .../client/java/RepositoryJavaClientImpl.java | 43 ++- .../nuxeo/client/java/TenantRepository.java | 15 ++ .../nuxeo/LoanoutValidatorHandler.java | 2 +- .../nuxeo/RelationDocumentModelHandler.java | 9 +- .../services/report/ReportResource.java | 151 +---------- .../nuxeo/ReportDocumentModelHandler.java | 233 ++++++++++++++++ 22 files changed, 830 insertions(+), 357 deletions(-) create mode 100644 services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefsSimple2.xml create mode 100644 services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/loanin.xml create mode 100644 services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/res/refObjs.res.xml 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 41c18d30c..ccde889b3 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 @@ -693,7 +693,7 @@ public class XmlReplay { || (dump.dumpServiceResult == ServiceResult.DUMP_OPTIONS.full) ){ System.out.println("\r\n#---------------------#"); } - System.out.println(leader+serviceResultRow+"\r\n"); + System.out.println(timeString()+" "+leader+serviceResultRow+"\r\n"); if (dump.payloads || (doingAuto&&hasError) ) { if (Tools.notBlank(serviceResult.requestPayload)){ System.out.println("\r\n========== request payload ==============="); @@ -738,7 +738,12 @@ public class XmlReplay { return results; } - + private static String timeString() { + java.util.Date date= new java.util.Date(); + java.sql.Timestamp ts = new java.sql.Timestamp(date.getTime()); + return ts.toString(); + } + //======================== MAIN =================================================================== diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefs.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefs.xml index 92e864af1..414f53a51 100644 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefs.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefs.xml @@ -143,9 +143,6 @@ authrefs/updatePerson2.xml - - - - - diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefsSimple.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefsSimple.xml index 721c67ca3..66adebb96 100644 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefsSimple.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefsSimple.xml @@ -65,7 +65,7 @@ /cspace-services/personauthorities/${PersonAuth1.CSID}/items/${Person1.CSID}/refObjs - authrefs/res/foo.res.xml + authrefs/res/refObjs.res.xml diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefsSimple2.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefsSimple2.xml new file mode 100644 index 000000000..8fab390db --- /dev/null +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefsSimple2.xml @@ -0,0 +1,62 @@ + + + + + + POST + /cspace-services/personauthorities/ + authrefs/newPersonAuthority.xml + + + POST + /cspace-services/personauthorities/${PersonAuth1.CSID}/items/ + authrefs/newPerson1.xml + + + + GET + /cspace-services/personauthorities/${PersonAuth1.CSID}/items/${Person1.CSID} + + + + POST + /cspace-services/loansin/ + authrefs/loanin.xml + + 42 + ${GetPerson1.got("//refName")} + + + + + GET + /cspace-services/loansin/${loanin1.CSID}/ + + + authrefs/res/foo.res.xml + + + + + GET + /cspace-services/loansin/${loanin1.CSID}/authorityrefs + + + authrefs/res/foo.res.xml + + + + + GET + /cspace-services/personauthorities/${PersonAuth1.CSID}/items/${Person1.CSID}/refObjs + + + authrefs/res/refObjs.res.xml + + + + + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/loanin.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/loanin.xml new file mode 100644 index 000000000..dc8d5f4f2 --- /dev/null +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/loanin.xml @@ -0,0 +1,15 @@ + + + + loaninNumber-${loannum} + + + October 29, 2009 + ${person} + + + For Surfboards of the 1960s exhibition. + Loan in conditions. + + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/res/refObjs.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/res/refObjs.res.xml new file mode 100644 index 000000000..635f8dbe4 --- /dev/null +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/res/refObjs.res.xml @@ -0,0 +1,6 @@ + + + 1 + 1 + diff --git a/services/JaxRsServiceProvider/src/main/resources/log4j.properties b/services/JaxRsServiceProvider/src/main/resources/log4j.properties index 2be5675d6..848dd0718 100644 --- a/services/JaxRsServiceProvider/src/main/resources/log4j.properties +++ b/services/JaxRsServiceProvider/src/main/resources/log4j.properties @@ -1,4 +1,4 @@ -log4j.rootLogger=debug, stdout, R +log4j.rootLogger=debug, R log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout @@ -9,9 +9,9 @@ log4j.appender.stdout.layout.ConversionPattern=%d %-5p [%t] [%c:%L] %m%n log4j.appender.R=org.apache.log4j.RollingFileAppender log4j.appender.R.File=${catalina.home}/logs/cspace-services.log -log4j.appender.R.MaxFileSize=1000KB -# Keep one backup file -log4j.appender.R.MaxBackupIndex=1 +log4j.appender.R.MaxFileSize=5000KB +# Keep ten backup files +log4j.appender.R.MaxBackupIndex=10 log4j.appender.R.layout=org.apache.log4j.PatternLayout log4j.appender.R.layout.ConversionPattern=%d %-5p [%t] [%c:%L] %m%n @@ -24,9 +24,11 @@ log4j.appender.R.layout.ConversionPattern=%d %-5p [%t] [%c:%L] %m%n # CollectionSpace log levels # log4j.logger.org.collectionspace=DEBUG +#log4j.logger.org.collectionspace.services.common.vocabulary.nuxeo=TRACE log4j.logger.perf.collectionspace=ERROR log4j.logger.org.nuxeo=ERROR +#log4j.logger.org.nuxeo.ecm.core.storage.sql=TRACE log4j.logger.org.apache=ERROR log4j.logger.httpclient=ERROR log4j.logger.org.jboss.resteasy=ERROR diff --git a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResource.java b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResource.java index caf493758..b5119587d 100644 --- a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResource.java +++ b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResource.java @@ -58,11 +58,13 @@ import org.collectionspace.services.common.workflow.service.nuxeo.WorkflowDocume import org.collectionspace.services.jaxb.AbstractCommonList; import org.collectionspace.services.nuxeo.client.java.DocumentModelHandler; import org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl; +import org.collectionspace.services.nuxeo.client.java.RepositoryJavaClientImpl; import org.collectionspace.services.relation.RelationResource; import org.collectionspace.services.relation.RelationsCommonList; import org.collectionspace.services.relation.RelationshipType; import org.jboss.resteasy.util.HttpResponseCodes; import org.nuxeo.ecm.core.api.DocumentModel; +import org.nuxeo.ecm.core.api.repository.RepositoryInstance; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -260,13 +262,13 @@ public abstract class AuthorityResource String shortIdentifier; } - public String lookupParentCSID(String parentspecifier, String method, String op, MultivaluedMap queryParams) + protected String lookupParentCSID(String parentspecifier, String method, String op, MultivaluedMap queryParams) throws Exception { CsidAndShortIdentifier tempResult = lookupParentCSIDAndShortIdentifer(parentspecifier, method, op, queryParams); return tempResult.CSID; } - public CsidAndShortIdentifier lookupParentCSIDAndShortIdentifer(String parentspecifier, String method, String op, MultivaluedMap queryParams) + private CsidAndShortIdentifier lookupParentCSIDAndShortIdentifer(String parentspecifier, String method, String op, MultivaluedMap queryParams) throws Exception { CsidAndShortIdentifier result = new CsidAndShortIdentifier(); Specifier parentSpec = getSpecifier(parentspecifier, method, op); @@ -283,7 +285,7 @@ public abstract class AuthorityResource parentShortIdentifier = parentSpec.value; String whereClause = buildWhereForAuthByName(parentSpec.value); ServiceContext ctx = createServiceContext(getServiceName(), queryParams); - parentcsid = getRepositoryClient(ctx).findDocCSID(ctx, whereClause); //FIXME: REM - If the parent has been soft-deleted, should we be looking for the item? + parentcsid = getRepositoryClient(ctx).findDocCSID(null, ctx, whereClause); //FIXME: REM - If the parent has been soft-deleted, should we be looking for the item? } result.CSID = parentcsid; result.shortIdentifier = parentShortIdentifier; @@ -298,7 +300,7 @@ public abstract class AuthorityResource itemcsid = itemSpec.value; } else { String itemWhereClause = buildWhereForAuthItemByName(itemSpec.value, parentcsid); - itemcsid = getRepositoryClient(ctx).findDocCSID(ctx, itemWhereClause); //FIXME: REM - Should we be looking for the 'wf_deleted' query param and filtering on it? + itemcsid = getRepositoryClient(ctx).findDocCSID(null, ctx, itemWhereClause); //FIXME: REM - Should we be looking for the 'wf_deleted' query param and filtering on it? } return itemcsid; } @@ -309,7 +311,7 @@ public abstract class AuthorityResource * Resource. They then call this method on that resource. */ @Override - public DocumentModel getDocModelForAuthorityItem(RefName.AuthorityItem item) + public DocumentModel getDocModelForAuthorityItem(RepositoryInstance repoSession, RefName.AuthorityItem item) throws Exception, DocumentNotFoundException { if(item == null) { return null; @@ -318,11 +320,13 @@ public abstract class AuthorityResource // Ensure we have the right context. ServiceContext ctx = createServiceContext(item.inAuthority.resource); - String parentcsid = getRepositoryClient(ctx).findDocCSID(ctx, whereClause); + // HACK - this really must be moved to the doc handler, not here. No Nuxeo specific stuff here! + RepositoryJavaClientImpl client = (RepositoryJavaClientImpl)getRepositoryClient(ctx); + String parentcsid = client.findDocCSID(repoSession, ctx, whereClause); String itemWhereClause = buildWhereForAuthItemByName(item.getShortIdentifier(), parentcsid); ctx = createServiceContext(getItemServiceName()); - DocumentWrapper docWrapper = getRepositoryClient(ctx).findDoc(ctx, itemWhereClause); + DocumentWrapper docWrapper = client.findDoc(repoSession, ctx, itemWhereClause); DocumentModel docModel = docWrapper.getWrappedObject(); return docModel; } @@ -462,7 +466,7 @@ public abstract class AuthorityResource csid = spec.value; } else { String whereClause = buildWhereForAuthByName(spec.value); - csid = getRepositoryClient(ctx).findDocCSID(ctx, whereClause); + csid = getRepositoryClient(ctx).findDocCSID(null, ctx, whereClause); } getRepositoryClient(ctx).update(ctx, csid, handler); result = ctx.getOutput(); @@ -739,30 +743,21 @@ public abstract class AuthorityResource ServiceContext ctx = createServiceContext(getItemServiceName(), queryParams); String itemcsid = lookupItemCSID(itemspecifier, parentcsid, "getReferencingObjects(item)", "GET_ITEM_REF_OBJS", ctx); - // Note that we have to create the service context for the Items, not the main service - // We omit the parentShortId, only needed when doing a create... - DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid, null); - RepositoryClient repoClient = getRepositoryClient(ctx); - DocumentFilter myFilter = handler.getDocumentFilter(); String serviceType = ServiceBindingUtils.SERVICE_TYPE_PROCEDURE; List list = queryParams.remove(ServiceBindingUtils.SERVICE_TYPE_PROP); if (list != null) { serviceType = list.get(0); } - DocumentWrapper docWrapper = repoClient.getDoc(ctx, itemcsid); - DocumentModel docModel = docWrapper.getWrappedObject(); - String refName = (String) docModel.getPropertyValue(AuthorityItemJAXBSchema.REF_NAME); - // Could be smarter about using the list from above, and/or allowing multiple ArrayList serviceTypes = new ArrayList(1); serviceTypes.add(serviceType); - authRefDocList = RefNameServiceUtils.getAuthorityRefDocs(ctx, - repoClient, - serviceTypes, - refName, - getRefPropName(), - myFilter.getPageSize(), myFilter.getStartPage(), true /*computeTotal*/); + // Note that we have to create the service context for the Items, not the main service + // We omit the parentShortId, only needed when doing a create... + AuthorityItemDocumentModelHandler handler = (AuthorityItemDocumentModelHandler) + createItemDocumentHandler(ctx, parentcsid, null); + + authRefDocList = handler.getReferencingObjects(ctx, serviceTypes, getRefPropName(), itemcsid); } catch (Exception e) { throw bigReThrow(e, ServiceMessages.GET_FAILED); } diff --git a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemDocumentModelHandler.java b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemDocumentModelHandler.java index 8fdf55360..2b449d651 100644 --- a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemDocumentModelHandler.java +++ b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemDocumentModelHandler.java @@ -29,13 +29,17 @@ import org.collectionspace.services.client.PayloadOutputPart; import org.collectionspace.services.client.PoxPayloadIn; import org.collectionspace.services.client.PoxPayloadOut; import org.collectionspace.services.client.RelationClient; +import org.collectionspace.services.common.ResourceBase; +import org.collectionspace.services.common.ServiceMessages; import org.collectionspace.services.common.api.CommonAPI; import org.collectionspace.services.common.api.RefName; import org.collectionspace.services.common.api.Tools; +import org.collectionspace.services.common.authorityref.AuthorityRefDocList; import org.collectionspace.services.common.context.MultipartServiceContext; import org.collectionspace.services.common.context.ServiceBindingUtils; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.document.DocumentException; +import org.collectionspace.services.common.document.DocumentFilter; import org.collectionspace.services.common.document.DocumentWrapper; import org.collectionspace.services.common.document.DocumentWrapperImpl; import org.collectionspace.services.common.relation.IRelationsManager; @@ -46,6 +50,7 @@ import org.collectionspace.services.common.vocabulary.AuthorityJAXBSchema; import org.collectionspace.services.common.vocabulary.AuthorityItemJAXBSchema; import org.collectionspace.services.common.vocabulary.RefNameServiceUtils; import org.collectionspace.services.nuxeo.client.java.DocHandlerBase; +import org.collectionspace.services.nuxeo.client.java.RepositoryJavaClientImpl; import org.collectionspace.services.common.service.ListResultField; import org.collectionspace.services.nuxeo.util.NuxeoUtils; import org.collectionspace.services.relation.RelationResource; @@ -54,11 +59,17 @@ import org.collectionspace.services.relation.RelationsCommonList; import org.collectionspace.services.relation.RelationsDocListItem; import org.collectionspace.services.relation.RelationshipType; import org.nuxeo.ecm.core.api.DocumentModel; +import org.nuxeo.ecm.core.api.model.PropertyException; import org.nuxeo.ecm.core.api.model.PropertyNotFoundException; +import org.nuxeo.ecm.core.api.repository.RepositoryInstance; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.ws.rs.PathParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import java.util.ArrayList; import java.util.List; @@ -334,6 +345,60 @@ public abstract class AuthorityItemDocumentModelHandler docModel.setProperty(authorityItemCommonSchemaName, AuthorityItemJAXBSchema.IN_AUTHORITY, inAuthority); } + + + public AuthorityRefDocList getReferencingObjects( + ServiceContext ctx, + ArrayList serviceTypes, + String propertyName, + String itemcsid) throws Exception { + AuthorityRefDocList authRefDocList = null; + RepositoryInstance repoSession = null; + boolean releaseRepoSession = false; + + try { + RepositoryJavaClientImpl repoClient = (RepositoryJavaClientImpl)this.getRepositoryClient(ctx); + repoSession = this.getRepositorySession(); + if (repoSession == null) { + repoSession = repoClient.getRepositorySession(); + releaseRepoSession = true; + } + DocumentFilter myFilter = getDocumentFilter(); + + try { + DocumentWrapper wrapper = repoClient.getDoc(repoSession, ctx, itemcsid); + DocumentModel docModel = wrapper.getWrappedObject(); + String refName = (String) docModel.getPropertyValue(AuthorityItemJAXBSchema.REF_NAME); + authRefDocList = RefNameServiceUtils.getAuthorityRefDocs( + repoSession, ctx, repoClient, + serviceTypes, + refName, + propertyName, + myFilter.getPageSize(), myFilter.getStartPage(), true /*computeTotal*/); + } catch (PropertyException pe) { + throw pe; + } catch (DocumentException de) { + throw de; + } catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.debug("Caught exception ", e); + } + throw new DocumentException(e); + } finally { + if (releaseRepoSession && repoSession != null) { + repoClient.releaseRepositorySession(repoSession); + } + } + } catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.debug("Caught exception ", e); + } + throw new DocumentException(e); + } + return authRefDocList; + } + + /* (non-Javadoc) @@ -432,6 +497,11 @@ public abstract class AuthorityItemDocumentModelHandler RelationsCommonList childrenListOuter = getRelations(null, thisCSID, predicate); List childrenList = childrenListOuter.getRelationListItem(); + if(logger.isTraceEnabled()) { + String dump = dumpLists(thisCSID, parentList, childrenList, null); + logger.trace("~~~~~~~~~~~~~~~~~~~~~~ showRelations ~~~~~~~~~~~~~~~~~~~~~~~~" + CR + dump); + } + //Assume that there are more children than parents. Will be true for parent/child, but maybe not for other relations. //Now add all parents to our childrenList, to be able to return just one list of consolidated results. //Not optimal, but that's the current design spec. @@ -478,6 +548,10 @@ public abstract class AuthorityItemDocumentModelHandler long siblingSize = siblingList.size(); siblingListOuter.setTotalItems(siblingSize); siblingListOuter.setItemsInPage(siblingSize); + if(logger.isTraceEnabled()) { + String dump = dumpList(siblingList, "Siblings of: "+thisCSID); + logger.trace("~~~~~~~~~~~~~~~~~~~~~~ showSiblings ~~~~~~~~~~~~~~~~~~~~~~~~" + CR + dump); + } PayloadOutputPart relationsPart = new PayloadOutputPart(RelationClient.SERVICE_COMMON_LIST_NAME, siblingListOuter); ctx.addOutputPart(relationsPart); @@ -492,6 +566,10 @@ public abstract class AuthorityItemDocumentModelHandler RelationsCommonList objectListOuter = getRelations(null, thisCSID, null); // nulls are wildcards: subject=*, and predicate=* List objectList = objectListOuter.getRelationListItem(); + if(logger.isTraceEnabled()) { + String dump = dumpLists(thisCSID, subjectList, objectList, null); + logger.trace("~~~~~~~~~~~~~~~~~~~~~~ showAllRelations ~~~~~~~~~~~~~~~~~~~~~~~~" + CR + dump); + } // MERGE LISTS: subjectList.addAll(objectList); @@ -587,6 +665,7 @@ public abstract class AuthorityItemDocumentModelHandler List childList = null; List parentList = null; DocumentModel docModel = wrapDoc.getWrappedObject(); + String itemRefName = (String) docModel.getPropertyValue(AuthorityItemJAXBSchema.REF_NAME); ServiceContext ctx = getServiceContext(); //Do magic replacement of ${itemCSID} and fix URI's. @@ -629,36 +708,63 @@ public abstract class AuthorityItemDocumentModelHandler for (RelationsCommonList.RelationListItem inboundItem : inboundList) { // Note that the relations may specify the other (non-item) bit with a refName, not a CSID, // and so the CSID for those may be null - if (itemCSID.equals(inboundItem.getObject().getCsid()) - && inboundItem.getPredicate().equals(HAS_BROADER)) { - //then this is an item that says we have a child. That child is inboundItem - RelationsCommonList.RelationListItem childItem = - (childList == null) ? null : findInList(childList, inboundItem); - if (childItem != null) { - removeFromList(childList, childItem); //exists, just take it off delete list - } else { - actionList.add(inboundItem); //doesn't exist as a child, but is a child. Add to additions list - } - ensureChildHasNoOtherParents(ctx, queryParams, inboundItem.getSubject().getCsid()); - - } else if (itemCSID.equals(inboundItem.getSubject().getCsid()) - && inboundItem.getPredicate().equals(HAS_BROADER)) { - //then this is an item that says we have a parent. inboundItem is that parent. - RelationsCommonList.RelationListItem parentItem = - (parentList == null) ? null : findInList(parentList, inboundItem); - if (parentItem != null) { - removeFromList(parentList, parentItem); //exists, just take it off delete list + if(inboundItem.getPredicate().equals(HAS_BROADER)) { + // Look for parents and children + if(itemCSID.equals(inboundItem.getObject().getCsid()) + || itemRefName.equals(inboundItem.getObject().getRefName())) { + //then this is an item that says we have a child. That child is inboundItem + RelationsCommonList.RelationListItem childItem = + (childList == null) ? null : findInList(childList, inboundItem); + if (childItem != null) { + if (logger.isTraceEnabled()) { + StringBuilder sb = new StringBuilder(); + itemToString(sb, "== Child: ", childItem); + logger.trace("Found inboundChild in current child list: " + sb.toString()); + } + removeFromList(childList, childItem); //exists, just take it off delete list + } else { + if (logger.isTraceEnabled()) { + StringBuilder sb = new StringBuilder(); + itemToString(sb, "== Child: ", inboundItem); + logger.trace("inboundChild not in current child list, will add: " + sb.toString()); + } + actionList.add(inboundItem); //doesn't exist as a child, but is a child. Add to additions list + String newChildCsid = inboundItem.getSubject().getCsid(); + if(newChildCsid == null) { + String newChildRefName = inboundItem.getSubject().getRefName(); + if(newChildRefName==null) { + throw new RuntimeException("Child with no CSID or refName!"); + } + if (logger.isTraceEnabled()) { + logger.trace("Fetching CSID for child with only refname: "+newChildRefName); + } + DocumentModel newChildDocModel = + ResourceBase.getDocModelForRefName(this.getRepositorySession(), + newChildRefName, getServiceContext().getResourceMap()); + newChildCsid = getCsid(newChildDocModel); + } + ensureChildHasNoOtherParents(ctx, queryParams, newChildCsid); + } + + } else if (itemCSID.equals(inboundItem.getSubject().getCsid()) + || itemRefName.equals(inboundItem.getSubject().getRefName())) { + //then this is an item that says we have a parent. inboundItem is that parent. + RelationsCommonList.RelationListItem parentItem = + (parentList == null) ? null : findInList(parentList, inboundItem); + if (parentItem != null) { + removeFromList(parentList, parentItem); //exists, just take it off delete list + } else { + actionList.add(inboundItem); //doesn't exist as a parent, but is a parent. Add to additions list + } } else { - actionList.add(inboundItem); //doesn't exist as a parent, but is a parent. Add to additions list - } + logger.error("Parent/Child Element didn't link to this item. inboundItem: " + inboundItem); + } } else { - logger.warn("Element didn't match parent or child, but may have partial fields that match. inboundItem: " + inboundItem); - //not dealing with: hasNarrower or any other predicate. + logger.warn("Non-parent relation ignored. inboundItem: " + inboundItem); } } if (logger.isTraceEnabled()) { String dump = dumpLists(itemCSID, parentList, childList, actionList); - //System.out.println("====dump====="+CR+dump); logger.trace("~~~~~~~~~~~~~~~~~~~~~~dump~~~~~~~~~~~~~~~~~~~~~~~~" + CR + dump); } if (fUpdate) { @@ -683,6 +789,7 @@ public abstract class AuthorityItemDocumentModelHandler } private void ensureChildHasNoOtherParents(ServiceContext ctx, MultivaluedMap queryParams, String childCSID) { + logger.trace("ensureChildHasNoOtherParents for: " + childCSID ); queryParams.putSingle(IRelationsManager.SUBJECT_QP, childCSID); queryParams.putSingle(IRelationsManager.PREDICATE_QP, RelationshipType.HAS_BROADER.value()); queryParams.putSingle(IRelationsManager.OBJECT_QP, null); //null means ANY @@ -692,36 +799,48 @@ public abstract class AuthorityItemDocumentModelHandler deleteRelations(parentList, ctx, "parentList-delete"); } + + private void itemToString(StringBuilder sb, String prefix, RelationsCommonList.RelationListItem item ) { + sb.append(prefix); + sb.append((item.getCsid()!= null)?item.getCsid():"NO CSID"); + sb.append(": ["); + sb.append((item.getSubject().getCsid()!=null)?item.getSubject().getCsid():item.getSubject().getRefName()); + sb.append("]--"); + sb.append(item.getPredicate()); + sb.append("-->["); + sb.append((item.getObject().getCsid()!=null)?item.getObject().getCsid():item.getObject().getRefName()); + sb.append("]"); + } + private String dumpLists(String itemCSID, List parentList, List childList, List actionList) { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); sb.append("itemCSID: " + itemCSID + CR); - sb.append(dumpList(parentList, "parentList")); - sb.append(dumpList(childList, "childList")); - sb.append(dumpList(actionList, "actionList")); + if(parentList!=null) { + sb.append(dumpList(parentList, "parentList")); + } + if(childList!=null) { + sb.append(dumpList(childList, "childList")); + } + if(actionList!=null) { + sb.append(dumpList(actionList, "actionList")); + } return sb.toString(); } private final static String CR = "\r\n"; private final static String T = " "; private String dumpList(List list, String label) { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); String s; if (list.size() > 0) { sb.append("=========== " + label + " ==========" + CR); } for (RelationsCommonList.RelationListItem item : list) { - s = - T + item.getSubject().getCsid() //+T4 + item.getSubject().getUri() - + T + item.getPredicate() - + T + item.getObject().getCsid() //+T4 + item.getObject().getUri() - + CR //+"subject:{"+item.getSubject()+"}\r\n object:{"+item.getObject()+"}" - //+ CR + "relation-record: {"+item+"}" - ; - sb.append(s); - + itemToString(sb, "== ", item); + sb.append(CR); } return sb.toString(); } @@ -820,10 +939,13 @@ public abstract class AuthorityItemDocumentModelHandler private void deleteRelations(List list, ServiceContext ctx, String listName) { try { - //if (list.size()>0){ logger.info("==== deleteRelations from : "+listName); } for (RelationsCommonList.RelationListItem item : list) { RelationResource relationResource = new RelationResource(); - //logger.info("==== TO DELETE: " + item.getCsid() + ": " + item.getSubject().getCsid() + "--" + item.getPredicate() + "-->" + item.getObject().getCsid()); + if(logger.isTraceEnabled()) { + StringBuilder sb = new StringBuilder(); + itemToString(sb, "==== TO DELETE: ", item); + logger.trace(sb.toString()); + } Object res = relationResource.delete(item.getCsid()); } } catch (Throwable t) { @@ -845,30 +967,51 @@ public abstract class AuthorityItemDocumentModelHandler return result; } - private RelationsCommonList.RelationListItem findInList(List list, RelationsCommonList.RelationListItem item) { + // Note that the item argument may be sparse (only refName, no CSID for subject or object) + // But the list items must not be sparse + private RelationsCommonList.RelationListItem findInList( + List list, + RelationsCommonList.RelationListItem item) { + RelationsCommonList.RelationListItem foundItem = null; for (RelationsCommonList.RelationListItem listItem : list) { if (itemsEqual(listItem, item)) { //equals must be defined, else - return listItem; + foundItem = listItem; + break; } } - return null; + return foundItem; } - private boolean itemsEqual(RelationsCommonList.RelationListItem item, RelationsCommonList.RelationListItem item2) { - if (item == null || item2 == null) { + // Note that item2 may be sparse (only refName, no CSID for subject or object) + // But item1 must not be sparse + private boolean itemsEqual(RelationsCommonList.RelationListItem item1, RelationsCommonList.RelationListItem item2) { + if (item1 == null || item2 == null) { return false; } - RelationsDocListItem subj1 = item.getSubject(); + RelationsDocListItem subj1 = item1.getSubject(); RelationsDocListItem subj2 = item2.getSubject(); - RelationsDocListItem obj1 = item.getObject(); + RelationsDocListItem obj1 = item1.getObject(); RelationsDocListItem obj2 = item2.getObject(); - - return (subj1.getCsid().equals(subj2.getCsid())) - && (obj1.getCsid().equals(obj1.getCsid())) - && ((item.getPredicate().equals(item2.getPredicate())) - && (item.getRelationshipType().equals(item2.getRelationshipType()))) - && (obj1.getDocumentType().equals(obj2.getDocumentType())) - && (subj1.getDocumentType().equals(subj2.getDocumentType())); + String subj1Csid = subj1.getCsid(); + String subj2Csid = subj2.getCsid(); + String subj1RefName = subj1.getRefName(); + String subj2RefName = subj2.getRefName(); + + String obj1Csid = obj1.getCsid(); + String obj2Csid = obj2.getCsid(); + String obj1RefName = obj1.getRefName(); + String obj2RefName = obj2.getRefName(); + + boolean isEqual = + (subj1Csid.equals(subj2Csid) || ((subj2Csid==null) && subj1RefName.equals(subj2RefName))) + && (obj1Csid.equals(obj1Csid) || ((obj2Csid==null) && obj1RefName.equals(obj2RefName))) + // predicate is proper, but still allow relationshipType + && (item1.getPredicate().equals(item2.getPredicate()) + || ((item2.getPredicate()==null) && item1.getRelationshipType().equals(item2.getRelationshipType()))) + // Allow missing docTypes, so long as they do not conflict + && (obj1.getDocumentType().equals(obj2.getDocumentType()) || obj2.getDocumentType()==null) + && (subj1.getDocumentType().equals(subj2.getDocumentType()) || subj2.getDocumentType()==null); + return isEqual; } private void removeFromList(List list, RelationsCommonList.RelationListItem item) { diff --git a/services/batch/service/src/main/java/org/collectionspace/services/batch/BatchResource.java b/services/batch/service/src/main/java/org/collectionspace/services/batch/BatchResource.java index cc9e01425..b064cb147 100644 --- a/services/batch/service/src/main/java/org/collectionspace/services/batch/BatchResource.java +++ b/services/batch/service/src/main/java/org/collectionspace/services/batch/BatchResource.java @@ -27,6 +27,7 @@ import java.util.List; import org.collectionspace.services.BatchJAXBSchema; import org.collectionspace.services.jaxb.InvocableJAXBSchema; +import org.collectionspace.services.batch.nuxeo.BatchDocumentModelHandler; import org.collectionspace.services.client.BatchClient; import org.collectionspace.services.client.IQueryManager; import org.collectionspace.services.client.PoxPayloadIn; @@ -70,8 +71,6 @@ import javax.ws.rs.core.UriInfo; @Consumes({"application/xml"}) public class BatchResource extends ResourceBase { - protected final int BAD_REQUEST_STATUS = Response.Status.BAD_REQUEST.getStatusCode(); - protected final String COMMON_SCHEMA = "batch_common"; @Override @@ -186,89 +185,9 @@ public class BatchResource extends ResourceBase { InvocationContext invContext) { try { ServiceContext ctx = createServiceContext(); - DocumentHandler handler = createDocumentHandler(ctx); - DocumentWrapper wrapper = - getRepositoryClient(ctx).getDoc(ctx, csid); - DocumentModel docModel = wrapper.getWrappedObject(); - String invocationMode = invContext.getMode(); - String modeProperty = null; - boolean checkDocType = true; - if(BatchInvocable.INVOCATION_MODE_SINGLE.equalsIgnoreCase(invocationMode)) { - modeProperty = BatchJAXBSchema.SUPPORTS_SINGLE_DOC; - } else if(BatchInvocable.INVOCATION_MODE_LIST.equalsIgnoreCase(invocationMode)) { - modeProperty = BatchJAXBSchema.SUPPORTS_DOC_LIST; - } else if(BatchInvocable.INVOCATION_MODE_GROUP.equalsIgnoreCase(invocationMode)) { - modeProperty = BatchJAXBSchema.SUPPORTS_GROUP; - } else if(Invocable.INVOCATION_MODE_NO_CONTEXT.equalsIgnoreCase(invocationMode)) { - modeProperty = InvocableJAXBSchema.SUPPORTS_NO_CONTEXT; - checkDocType = false; - } else { - throw new BadRequestException("BatchResource: unknown Invocation Mode: " - +invocationMode); - } - Boolean supports = (Boolean)docModel.getPropertyValue(modeProperty); - if(!supports) { - throw new BadRequestException("BatchResource: This Batch Job does not support Invocation Mode: " - +invocationMode); - } - String className = - (String)docModel.getPropertyValue(BatchJAXBSchema.BATCH_CLASS_NAME); - className = className.trim(); - ClassLoader tccl = Thread.currentThread().getContextClassLoader(); - Class c = tccl.loadClass(className); - // enable validation assertions - tccl.setClassAssertionStatus(className, true); - if(!BatchInvocable.class.isAssignableFrom(c)) { - throw new RuntimeException("BatchResource: Class: " - +className+" does not implement BatchInvocable!"); - } else { - BatchInvocable batchInstance = (BatchInvocable)c.newInstance(); - List modes = batchInstance.getSupportedInvocationModes(); - if(!modes.contains(invocationMode)) { - throw new BadRequestException( - "BatchResource: Invoked with unsupported context mode: " - +invocationMode); - } - if(checkDocType) { - List forDocTypeList = - (List)docModel.getPropertyValue(BatchJAXBSchema.FOR_DOC_TYPES); - if(forDocTypeList==null - || !forDocTypeList.contains(invContext.getDocType())) { - throw new BadRequestException( - "BatchResource: Invoked with unsupported document type: " - +invContext.getDocType()); - } - } - batchInstance.setInvocationContext(invContext); - //ResourceMapHolder csapp = (ResourceMapHolder)app; - if(resourceMap!=null) { - batchInstance.setResourceMap(resourceMap); - } else { - resourceMap = ResteasyProviderFactory.getContextData(ResourceMap.class); - if(resourceMap!=null) { - batchInstance.setResourceMap(resourceMap); - } else { - logger.warn("BatchResource.invoke did not get a resourceMapHolder in Context!"); - } - } - batchInstance.run(); - int status = batchInstance.getCompletionStatus(); - if(status == Invocable.STATUS_ERROR) { - InvocationError error = batchInstance.getErrorInfo(); - if(error.getResponseCode() == BAD_REQUEST_STATUS) { - throw new BadRequestException( - "BatchResouce: batchProcess encountered error: " - +batchInstance.getErrorInfo()); - } else { - throw new RuntimeException( - "BatchResouce: batchProcess encountered error: " - +batchInstance.getErrorInfo()); - - } - } - InvocationResults results = batchInstance.getResults(); - return results; - } + BatchDocumentModelHandler handler = (BatchDocumentModelHandler)createDocumentHandler(ctx); + + return handler.invokeBatchJob(ctx, csid, resourceMap, invContext); } catch (Exception e) { throw bigReThrow(e, ServiceMessages.POST_FAILED); } diff --git a/services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/BatchDocumentModelHandler.java b/services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/BatchDocumentModelHandler.java index a5fe3e0c4..4777d291f 100644 --- a/services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/BatchDocumentModelHandler.java +++ b/services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/BatchDocumentModelHandler.java @@ -23,10 +23,163 @@ */ package org.collectionspace.services.batch.nuxeo; +import java.util.List; + +import javax.ws.rs.PathParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; + +import org.collectionspace.services.BatchJAXBSchema; +import org.collectionspace.services.jaxb.InvocableJAXBSchema; import org.collectionspace.services.nuxeo.client.java.DocHandlerBase; +import org.collectionspace.services.nuxeo.client.java.RepositoryJavaClientImpl; import org.collectionspace.services.batch.BatchCommon; +import org.collectionspace.services.batch.BatchInvocable; +import org.collectionspace.services.client.PoxPayloadIn; +import org.collectionspace.services.client.PoxPayloadOut; +import org.collectionspace.services.common.ResourceMap; +import org.collectionspace.services.common.ServiceMessages; +import org.collectionspace.services.common.context.ServiceContext; +import org.collectionspace.services.common.document.BadRequestException; +import org.collectionspace.services.common.document.DocumentException; +import org.collectionspace.services.common.document.DocumentFilter; +import org.collectionspace.services.common.document.DocumentHandler; +import org.collectionspace.services.common.document.DocumentWrapper; +import org.collectionspace.services.common.invocable.Invocable; +import org.collectionspace.services.common.invocable.InvocationContext; +import org.collectionspace.services.common.invocable.InvocationResults; +import org.collectionspace.services.common.invocable.Invocable.InvocationError; +import org.jboss.resteasy.spi.ResteasyProviderFactory; +import org.nuxeo.ecm.core.api.DocumentModel; +import org.nuxeo.ecm.core.api.model.PropertyException; +import org.nuxeo.ecm.core.api.repository.RepositoryInstance; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class BatchDocumentModelHandler extends DocHandlerBase { + private final Logger logger = LoggerFactory.getLogger(BatchDocumentModelHandler.class); + + protected final int BAD_REQUEST_STATUS = Response.Status.BAD_REQUEST.getStatusCode(); + + public InvocationResults invokeBatchJob( + ServiceContext ctx, + String csid, + ResourceMap resourceMap, + InvocationContext invContext) throws Exception { + + RepositoryInstance repoSession = null; + boolean releaseRepoSession = false; + + String invocationMode = invContext.getMode(); + String modeProperty = null; + boolean checkDocType = true; + if(BatchInvocable.INVOCATION_MODE_SINGLE.equalsIgnoreCase(invocationMode)) { + modeProperty = BatchJAXBSchema.SUPPORTS_SINGLE_DOC; + } else if(BatchInvocable.INVOCATION_MODE_LIST.equalsIgnoreCase(invocationMode)) { + modeProperty = BatchJAXBSchema.SUPPORTS_DOC_LIST; + } else if(BatchInvocable.INVOCATION_MODE_GROUP.equalsIgnoreCase(invocationMode)) { + modeProperty = BatchJAXBSchema.SUPPORTS_GROUP; + } else if(Invocable.INVOCATION_MODE_NO_CONTEXT.equalsIgnoreCase(invocationMode)) { + modeProperty = InvocableJAXBSchema.SUPPORTS_NO_CONTEXT; + checkDocType = false; + } else { + throw new BadRequestException("BatchResource: unknown Invocation Mode: " + +invocationMode); + } + + RepositoryJavaClientImpl repoClient = (RepositoryJavaClientImpl)this.getRepositoryClient(ctx); + repoSession = this.getRepositorySession(); + if (repoSession == null) { + repoSession = repoClient.getRepositorySession(); + releaseRepoSession = true; + } + + String className = null; + // Get properties from the batch docModel, and release the session + try { + DocumentWrapper wrapper = repoClient.getDoc(repoSession, ctx, csid); + DocumentModel docModel = wrapper.getWrappedObject(); + Boolean supports = (Boolean)docModel.getPropertyValue(modeProperty); + if(!supports) { + throw new BadRequestException("BatchResource: This Batch Job does not support Invocation Mode: " + +invocationMode); + } + if(checkDocType) { + List forDocTypeList = + (List)docModel.getPropertyValue(BatchJAXBSchema.FOR_DOC_TYPES); + if(forDocTypeList==null + || !forDocTypeList.contains(invContext.getDocType())) { + throw new BadRequestException( + "BatchResource: Invoked with unsupported document type: " + +invContext.getDocType()); + } + } + className = (String)docModel.getPropertyValue(BatchJAXBSchema.BATCH_CLASS_NAME); + } catch (PropertyException pe) { + if (logger.isDebugEnabled()) { + logger.debug("Property exception getting batch values: ", pe); + } + throw pe; + } catch (DocumentException de) { + if (logger.isDebugEnabled()) { + logger.debug("Problem getting batch doc: ", de); + } + throw de; + } catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.debug("Caught exception ", e); + } + throw new DocumentException(e); + } finally { + if (releaseRepoSession && repoSession != null) { + repoClient.releaseRepositorySession(repoSession); + } + } + className = className.trim(); + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + Class c = tccl.loadClass(className); + // enable validation assertions + tccl.setClassAssertionStatus(className, true); + if(!BatchInvocable.class.isAssignableFrom(c)) { + throw new RuntimeException("BatchResource: Class: " + +className+" does not implement BatchInvocable!"); + } + BatchInvocable batchInstance = (BatchInvocable)c.newInstance(); + List modes = batchInstance.getSupportedInvocationModes(); + if(!modes.contains(invocationMode)) { + throw new BadRequestException( + "BatchResource: Invoked with unsupported context mode: " + +invocationMode); + } + batchInstance.setInvocationContext(invContext); + if(resourceMap!=null) { + batchInstance.setResourceMap(resourceMap); + } else { + resourceMap = ResteasyProviderFactory.getContextData(ResourceMap.class); + if(resourceMap!=null) { + batchInstance.setResourceMap(resourceMap); + } else { + logger.warn("BatchResource.invoke did not get a resourceMapHolder in Context!"); + } + } + batchInstance.run(); + int status = batchInstance.getCompletionStatus(); + if(status == Invocable.STATUS_ERROR) { + InvocationError error = batchInstance.getErrorInfo(); + if(error.getResponseCode() == BAD_REQUEST_STATUS) { + throw new BadRequestException( + "BatchResouce: batchProcess encountered error: " + +batchInstance.getErrorInfo()); + } else { + throw new RuntimeException( + "BatchResouce: batchProcess encountered error: " + +batchInstance.getErrorInfo()); + + } + } + InvocationResults results = batchInstance.getResults(); + return results; + } } 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 5cb29bf8b..3f2d2896c 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 @@ -46,6 +46,7 @@ import org.jboss.resteasy.plugins.providers.multipart.MultipartInput; import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput; import org.jboss.resteasy.util.HttpResponseCodes; import org.nuxeo.ecm.core.api.DocumentModel; +import org.nuxeo.ecm.core.api.repository.RepositoryInstance; import javax.ws.rs.*; import javax.ws.rs.core.*; @@ -357,7 +358,7 @@ public abstract class ResourceBase * for all inheriting resource classes. Just use ServiceContext.getResourceMap() to get * the map, and pass it in. */ - public static DocumentModel getDocModelForRefName(String refName, ResourceMap resourceMap) + public static DocumentModel getDocModelForRefName(RepositoryInstance repoSession, String refName, ResourceMap resourceMap) throws Exception, DocumentNotFoundException { // TODO - we need to generalize the idea of a refName to more than Authorities and Items. RefName.AuthorityItem item = RefName.AuthorityItem.parse(refName); @@ -365,20 +366,20 @@ public abstract class ResourceBase return null; } ResourceBase resource = resourceMap.get(item.inAuthority.resource); - return resource.getDocModelForAuthorityItem(item); + return resource.getDocModelForAuthorityItem(repoSession, item); } // THis is ugly, but prevents us parsing the refName twice. Once we make refName a little more // general, and less Authority(Item) specific, this will look better. - public DocumentModel getDocModelForAuthorityItem(RefName.AuthorityItem item) + public DocumentModel getDocModelForAuthorityItem(RepositoryInstance repoSession, RefName.AuthorityItem item) throws Exception, DocumentNotFoundException { logger.warn("Default (ResourceBase) getDocModelForAuthorityItem called - should not happen!"); return null; } - public DocumentModel getDocModelForRefName(String refName) + public DocumentModel getDocModelForRefName(RepositoryInstance repoSession, String refName) throws Exception, DocumentNotFoundException { - return getDocModelForAuthorityItem(RefName.AuthorityItem.parse(refName)); + return getDocModelForAuthorityItem(repoSession, RefName.AuthorityItem.parse(refName)); } } diff --git a/services/common/src/main/java/org/collectionspace/services/common/repository/RepositoryClient.java b/services/common/src/main/java/org/collectionspace/services/common/repository/RepositoryClient.java index 43acb2113..c3d815a8e 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/repository/RepositoryClient.java +++ b/services/common/src/main/java/org/collectionspace/services/common/repository/RepositoryClient.java @@ -34,6 +34,7 @@ import org.collectionspace.services.common.storage.StorageClient; import org.nuxeo.ecm.core.api.ClientException; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentModelList; +import org.nuxeo.ecm.core.api.repository.RepositoryInstance; /** * RepositoryClient is a generic Document Repository client @@ -96,6 +97,7 @@ public interface RepositoryClient extends StorageClient { * of the document to retrieve * @throws DocumentException */ + @Deprecated public DocumentWrapper getDoc( ServiceContext ctx, String id) throws DocumentNotFoundException, DocumentException; @@ -124,7 +126,7 @@ public interface RepositoryClient extends StorageClient { * @param where NXQL where clause to get the document * @throws DocumentException */ - public String findDocCSID( + public String findDocCSID(RepositoryInstance repoSession, ServiceContext ctx, String where) throws DocumentNotFoundException, DocumentException; diff --git a/services/common/src/main/java/org/collectionspace/services/common/security/SecurityInterceptor.java b/services/common/src/main/java/org/collectionspace/services/common/security/SecurityInterceptor.java index 15b8c8c60..2c2148e70 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/security/SecurityInterceptor.java +++ b/services/common/src/main/java/org/collectionspace/services/common/security/SecurityInterceptor.java @@ -92,10 +92,16 @@ public class SecurityInterceptor implements PreProcessInterceptor, PostProcessIn @Override public ServerResponse preProcess(HttpRequest request, ResourceMethod method) throws Failure, WebApplicationException { + final String servicesResource = "/cspace-services/"; // HACK - this is configured in war + final int servicesResourceLen = servicesResource.length(); String httpMethod = request.getHttpMethod(); String uriPath = request.getUri().getPath(); if (logger.isDebugEnabled()) { - logger.debug("received " + httpMethod + " on " + uriPath); + String fullRequest = request.getUri().getRequestUri().toString(); + int servicesResourceIdx = fullRequest.indexOf(servicesResource); + String relativeRequest = (servicesResourceIdx<=0)? fullRequest + :fullRequest.substring(servicesResourceIdx+servicesResourceLen); + logger.debug("received " + httpMethod + " on " + relativeRequest); } String resName = SecurityUtils.getResourceName(request.getUri()); String resEntity = SecurityUtils.getResourceEntity(resName); diff --git a/services/common/src/main/java/org/collectionspace/services/common/vocabulary/RefNameServiceUtils.java b/services/common/src/main/java/org/collectionspace/services/common/vocabulary/RefNameServiceUtils.java index 4841eb4d6..ab2efb03c 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/vocabulary/RefNameServiceUtils.java +++ b/services/common/src/main/java/org/collectionspace/services/common/vocabulary/RefNameServiceUtils.java @@ -204,6 +204,7 @@ public class RefNameServiceUtils { } public static AuthorityRefDocList getAuthorityRefDocs( + RepositoryInstance repoSession, ServiceContext ctx, RepositoryClient repoClient, List serviceTypes, @@ -222,9 +223,7 @@ public class RefNameServiceUtils { Map> authRefFieldsByService = new HashMap>(); RepositoryJavaClientImpl nuxeoRepoClient = (RepositoryJavaClientImpl)repoClient; - RepositoryInstance repoSession = null; try { - repoSession = nuxeoRepoClient.getRepositorySession(); DocumentModelList docList = findAuthorityRefDocs(ctx, repoClient, repoSession, serviceTypes, refName, refPropName, queriedServiceBindings, authRefFieldsByService, pageSize, pageNum, computeTotal); @@ -244,10 +243,6 @@ public class RefNameServiceUtils { } catch (Exception e) { logger.error("Could not retrieve the Nuxeo repository", e); wrapperList = null; - } finally { - if (repoSession != null) { - nuxeoRepoClient.releaseRepositorySession(repoSession); - } } return wrapperList; @@ -353,7 +348,7 @@ public class RefNameServiceUtils { return docList; } - private static final boolean READY_FOR_COMPLEX_QUERY = false; + private static final boolean READY_FOR_COMPLEX_QUERY = true; private static String computeWhereClauseForAuthorityRefDocs( String escapedRefName, diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java index ca7ff53a1..c6bcde2bd 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java @@ -51,6 +51,8 @@ import org.collectionspace.services.common.context.MultipartServiceContext; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.datetime.DateTimeFormatUtils; import org.collectionspace.services.common.document.BadRequestException; +import org.collectionspace.services.common.document.DocumentException; +import org.collectionspace.services.common.document.DocumentNotFoundException; import org.collectionspace.services.common.document.DocumentUtils; import org.collectionspace.services.common.document.DocumentWrapper; import org.collectionspace.services.common.document.DocumentFilter; @@ -383,6 +385,57 @@ public abstract class RemoteDocumentModelHandlerImpl return result; } + /* + public String getStringPropertyFromDoc( + ServiceContext ctx, + String csid, + String propertyXPath ) throws DocumentNotFoundException, DocumentException { + RepositoryInstance repoSession = null; + boolean releaseRepoSession = false; + String returnValue = null; + + try{ + RepositoryJavaClientImpl repoClient = (RepositoryJavaClientImpl)this.getRepositoryClient(ctx); + repoSession = this.getRepositorySession(); + if (repoSession == null) { + repoSession = repoClient.getRepositorySession(); + releaseRepoSession = true; + } + + try { + DocumentWrapper wrapper = repoClient.getDoc(repoSession, ctx, csid); + DocumentModel docModel = wrapper.getWrappedObject(); + returnValue = (String) docModel.getPropertyValue(propertyXPath); + } catch (PropertyException pe) { + throw pe; + } catch (DocumentException de) { + throw de; + } catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.debug("Caught exception ", e); + } + throw new DocumentException(e); + } finally { + if (releaseRepoSession && repoSession != null) { + repoClient.releaseRepositorySession(repoSession); + } + } + } catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.debug("Caught exception ", e); + } + throw new DocumentException(e); + } + + + if (logger.isWarnEnabled() == true) { + logger.warn("Returned DocumentModel instance was created with a repository session that is now closed."); + } + return returnValue; + } + */ + + /* (non-Javadoc) * @see org.collectionspace.services.nuxeo.client.java.DocumentModelHandler#getAuthorityRefs(org.collectionspace.services.common.document.DocumentWrapper, java.util.List) diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java index b5885b718..f94da1362 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java @@ -170,9 +170,7 @@ public class RepositoryJavaClientImpl implements RepositoryClient findDoc( - ServiceContext ctx, RepositoryInstance repoSession, + ServiceContext ctx, String whereClause) throws DocumentNotFoundException, DocumentException { DocumentWrapper wrapDoc = null; @@ -411,7 +409,7 @@ public class RepositoryJavaClientImpl implements RepositoryClient ctx, String whereClause) throws DocumentNotFoundException, DocumentException { String csid = null; - RepositoryInstance repoSession = null; + boolean releaseSession = false; try { - repoSession = this.getRepositorySession(); - DocumentWrapper wrapDoc = findDoc(ctx, repoSession, whereClause); + if(repoSession== null) { + repoSession = this.getRepositorySession(); + releaseSession = true; + } + DocumentWrapper wrapDoc = findDoc(repoSession, ctx, whereClause); DocumentModel docModel = wrapDoc.getWrappedObject(); csid = NuxeoUtils.getCsid(docModel);//NuxeoUtils.extractId(docModel.getPathAsString()); } catch (DocumentNotFoundException dnfe) { @@ -456,7 +457,7 @@ public class RepositoryJavaClientImpl implements RepositoryClient(docList); } catch (IllegalArgumentException iae) { @@ -953,11 +957,14 @@ public class RepositoryJavaClientImpl implements RepositoryClient ctx = this.getServiceContext(); RepositoryInstance repoSession = this.getRepositorySession(); - DocumentModel subjectDocModel = getSubjectOrObjectDocModel(relationDocModel, SUBJ_DOC_MODEL); - DocumentModel objectDocModel = getSubjectOrObjectDocModel(relationDocModel, OBJ_DOC_MODEL); + DocumentModel subjectDocModel = getSubjectOrObjectDocModel(repoSession, relationDocModel, SUBJ_DOC_MODEL); + DocumentModel objectDocModel = getSubjectOrObjectDocModel(repoSession, relationDocModel, OBJ_DOC_MODEL); // Use values from the subject and object document models to populate the // relevant fields of the relation's own document model. @@ -309,6 +309,7 @@ public class RelationDocumentModelHandler private final boolean OBJ_DOC_MODEL = false; private DocumentModel getSubjectOrObjectDocModel( + RepositoryInstance repoSession, DocumentModel relationDocModel, boolean fSubject) throws Exception { ServiceContext ctx = this.getServiceContext(); @@ -331,13 +332,13 @@ public class RelationDocumentModelHandler } if (Tools.notBlank(csid)) { RepositoryJavaClientImpl nuxeoRepoClient = (RepositoryJavaClientImpl)getRepositoryClient(ctx); - DocumentWrapper docWrapper = nuxeoRepoClient.getDocFromCsid(ctx, this.getRepositorySession(), csid); + DocumentWrapper docWrapper = nuxeoRepoClient.getDocFromCsid(ctx, repoSession, csid); docModel = docWrapper.getWrappedObject(); } else { // if (Tools.isBlank(objectCsid)) { try { refName = (String) relationDocModel.getProperty(commonPartLabel, (fSubject?RelationJAXBSchema.SUBJECT_REFNAME:RelationJAXBSchema.OBJECT_REFNAME)); - docModel = ResourceBase.getDocModelForRefName(refName, ctx.getResourceMap()); + docModel = ResourceBase.getDocModelForRefName(repoSession, refName, ctx.getResourceMap()); } catch (Exception e) { throw new InvalidDocumentException( "Relation record must have a CSID or refName to identify the object of the relation.", e); diff --git a/services/report/service/src/main/java/org/collectionspace/services/report/ReportResource.java b/services/report/service/src/main/java/org/collectionspace/services/report/ReportResource.java index baa913746..3192d519d 100644 --- a/services/report/service/src/main/java/org/collectionspace/services/report/ReportResource.java +++ b/services/report/service/src/main/java/org/collectionspace/services/report/ReportResource.java @@ -30,6 +30,7 @@ import net.sf.jasperreports.engine.JasperPrint; import org.collectionspace.services.jaxb.AbstractCommonList; import org.collectionspace.services.jaxb.InvocableJAXBSchema; +import org.collectionspace.services.report.nuxeo.ReportDocumentModelHandler; import org.collectionspace.services.ReportJAXBSchema; import org.collectionspace.services.client.IQueryManager; import org.collectionspace.services.client.PoxPayloadIn; @@ -188,158 +189,14 @@ public class ReportResource extends ResourceBase { } try { ServiceContext ctx = createServiceContext(); - DocumentHandler handler = createDocumentHandler(ctx); - DocumentWrapper wrapper = - getRepositoryClient(ctx).getDoc(ctx, csid); - DocumentModel docModel = wrapper.getWrappedObject(); - String invocationMode = invContext.getMode(); - String modeProperty = null; - HashMap params = new HashMap(); - params.put(REPORTS_STD_TENANTID_PARAM, ctx.getTenantId()); - boolean checkDocType = true; - if(Invocable.INVOCATION_MODE_SINGLE.equalsIgnoreCase(invocationMode)) { - modeProperty = InvocableJAXBSchema.SUPPORTS_SINGLE_DOC; - params.put(REPORTS_STD_CSID_PARAM, invContext.getSingleCSID()); - } else if(Invocable.INVOCATION_MODE_LIST.equalsIgnoreCase(invocationMode)) { - modeProperty = InvocableJAXBSchema.SUPPORTS_DOC_LIST; - List csids = null; - InvocationContext.ListCSIDs listThing = invContext.getListCSIDs(); - if(listThing!=null) { - csids = listThing.getCsid(); - } - if(csids==null||csids.isEmpty()){ - throw new BadRequestException( - "ReportResource: Report invoked in list mode, with no csids in list." ); - } - StringBuilder sb = new StringBuilder(); - boolean first = true; - for(String csidItem : csids) { - if(first) - first = false; - else - sb.append(CSID_LIST_SEPARATOR); - sb.append(csidItem); - } - params.put(REPORTS_STD_CSIDLIST_PARAM, sb.toString()); - } else if(Invocable.INVOCATION_MODE_GROUP.equalsIgnoreCase(invocationMode)) { - modeProperty = InvocableJAXBSchema.SUPPORTS_GROUP; - params.put(REPORTS_STD_GROUPCSID_PARAM, invContext.getGroupCSID()); - } else if(Invocable.INVOCATION_MODE_NO_CONTEXT.equalsIgnoreCase(invocationMode)) { - modeProperty = InvocableJAXBSchema.SUPPORTS_NO_CONTEXT; - checkDocType = false; - } else { - throw new BadRequestException("ReportResource: unknown Invocation Mode: " - +invocationMode); - } - Boolean supports = (Boolean)docModel.getPropertyValue(modeProperty); - if(supports == null || !supports) { - throw new BadRequestException( - "ReportResource: This Report does not support Invocation Mode: " - +invocationMode); - } - if(checkDocType) { - List forDocTypeList = - (List)docModel.getPropertyValue(InvocableJAXBSchema.FOR_DOC_TYPES); - if(forDocTypeList==null - || !forDocTypeList.contains(invContext.getDocType())) { - throw new BadRequestException( - "ReportResource: Invoked with unsupported document type: " - +invContext.getDocType()); - } - } - String reportFileName = (String)docModel.getPropertyValue(ReportJAXBSchema.FILENAME); - - return buildReportResponse(csid, params, reportFileName); + ReportDocumentModelHandler handler = (ReportDocumentModelHandler)createDocumentHandler(ctx); + + return handler.invokeReport(ctx, csid, invContext); } catch (Exception e) { throw bigReThrow(e, ServiceMessages.POST_FAILED); } } - private Response buildReportResponse(String reportCSID, HashMap params, String reportFileName) { - Connection conn = null; - Response response = null; - try { - String fullPath = ServiceMain.getInstance().getServerRootDir() + - File.separator + ConfigReader.CSPACE_DIR_NAME + - File.separator + REPORTS_FOLDER + - // File.separator + tenantName + - File.separator + reportFileName; - conn = getConnection(); - - if (logger.isTraceEnabled()) { - logger.trace("ReportResource for Report csid=" + reportCSID - +" opening report file: "+fullPath); - } - FileInputStream fileStream = new FileInputStream(fullPath); - - // fill the report - JasperPrint jasperprint = JasperFillManager.fillReport(fileStream, params,conn); - // export report to pdf and build a response with the bytes - byte[] pdfasbytes = JasperExportManager.exportReportToPdf(jasperprint); - - // Need to set response type for what is requested... - response = Response.ok(pdfasbytes, "application/pdf").build(); - - return response; - } catch (SQLException sqle) { - // SQLExceptions can be chained. We have at least one exception, so - // set up a loop to make sure we let the user know about all of them - // if there happens to be more than one. - if (logger.isDebugEnabled()) { - SQLException tempException = sqle; - while (null != tempException) { - logger.debug("SQL Exception: " + sqle.getLocalizedMessage()); - - // loop to the next exception - tempException = tempException.getNextException(); - } - } - response = Response.status( - Response.Status.INTERNAL_SERVER_ERROR).entity( - "Invoke failed (SQL problem) on Report csid=" + reportCSID).type("text/plain").build(); - throw new WebApplicationException(response); - } catch (JRException jre) { - if (logger.isDebugEnabled()) { - logger.debug("JR Exception: " + jre.getLocalizedMessage() + " Cause: "+jre.getCause()); - } - response = Response.status( - Response.Status.INTERNAL_SERVER_ERROR).entity( - "Invoke failed (Jasper problem) on Report csid=" + reportCSID).type("text/plain").build(); - throw new WebApplicationException(response); - } catch (FileNotFoundException fnfe) { - if (logger.isDebugEnabled()) { - logger.debug("FileNotFoundException: " + fnfe.getLocalizedMessage()); - } - response = Response.status( - Response.Status.INTERNAL_SERVER_ERROR).entity( - "Invoke failed (SQL problem) on Report csid=" + reportCSID).type("text/plain").build(); - throw new WebApplicationException(response); - } catch (Exception e) { - throw bigReThrow(e, ServiceMessages.POST_FAILED); - } finally { - if(conn!=null) { - try { - conn.close(); - } catch (SQLException sqle) { - // SQLExceptions can be chained. We have at least one exception, so - // set up a loop to make sure we let the user know about all of them - // if there happens to be more than one. - if (logger.isDebugEnabled()) { - logger.debug("SQL Exception closing connection: " - + sqle.getLocalizedMessage()); - } - } catch (Exception e) { - if (logger.isDebugEnabled()) { - logger.debug("Exception closing connection", e); - } - } - } - } - } - - private Connection getConnection() throws NamingException, SQLException { - return JDBCTools.getConnection(REPOSITORY_NAME); - } } diff --git a/services/report/service/src/main/java/org/collectionspace/services/report/nuxeo/ReportDocumentModelHandler.java b/services/report/service/src/main/java/org/collectionspace/services/report/nuxeo/ReportDocumentModelHandler.java index 1f739c1b1..da78c16dc 100644 --- a/services/report/service/src/main/java/org/collectionspace/services/report/nuxeo/ReportDocumentModelHandler.java +++ b/services/report/service/src/main/java/org/collectionspace/services/report/nuxeo/ReportDocumentModelHandler.java @@ -23,8 +23,47 @@ */ package org.collectionspace.services.report.nuxeo; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; + +import javax.naming.NamingException; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperExportManager; +import net.sf.jasperreports.engine.JasperFillManager; +import net.sf.jasperreports.engine.JasperPrint; + +import org.collectionspace.services.ReportJAXBSchema; +import org.collectionspace.services.report.ReportResource; import org.collectionspace.services.report.ReportsCommon; +import org.collectionspace.services.client.PoxPayloadIn; +import org.collectionspace.services.client.PoxPayloadOut; +import org.collectionspace.services.common.ResourceMap; +import org.collectionspace.services.common.ServiceMain; +import org.collectionspace.services.common.ServiceMessages; +import org.collectionspace.services.common.config.ConfigReader; +import org.collectionspace.services.common.context.ServiceContext; +import org.collectionspace.services.common.document.BadRequestException; +import org.collectionspace.services.common.document.DocumentException; +import org.collectionspace.services.common.document.DocumentWrapper; +import org.collectionspace.services.common.invocable.Invocable; +import org.collectionspace.services.common.invocable.InvocationContext; +import org.collectionspace.services.common.storage.JDBCTools; +import org.collectionspace.services.jaxb.InvocableJAXBSchema; import org.collectionspace.services.nuxeo.client.java.DocHandlerBase; +import org.collectionspace.services.nuxeo.client.java.RepositoryJavaClientImpl; +import org.nuxeo.ecm.core.api.DocumentModel; +import org.nuxeo.ecm.core.api.model.PropertyException; +import org.nuxeo.ecm.core.api.repository.RepositoryInstance; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * ReportDocumentModelHandler @@ -33,6 +72,200 @@ import org.collectionspace.services.nuxeo.client.java.DocHandlerBase; * $LastChangedDate: $ */ public class ReportDocumentModelHandler extends DocHandlerBase { + private final Logger logger = LoggerFactory.getLogger(ReportDocumentModelHandler.class); + private static String REPOSITORY_NAME = JDBCTools.NUXEO_REPOSITORY_NAME; + private static String REPORTS_FOLDER = "reports"; + private static String CSID_LIST_SEPARATOR = ","; + + private static String REPORTS_STD_CSID_PARAM = "csid"; + private static String REPORTS_STD_GROUPCSID_PARAM = "groupcsid"; + private static String REPORTS_STD_CSIDLIST_PARAM = "csidlist"; + private static String REPORTS_STD_TENANTID_PARAM = "tenantid"; + + public Response invokeReport( + ServiceContext ctx, + String csid, + InvocationContext invContext) throws Exception { + RepositoryInstance repoSession = null; + boolean releaseRepoSession = false; + + String invocationMode = invContext.getMode(); + String modeProperty = null; + HashMap params = new HashMap(); + params.put(REPORTS_STD_TENANTID_PARAM, ctx.getTenantId()); + boolean checkDocType = true; + if(Invocable.INVOCATION_MODE_SINGLE.equalsIgnoreCase(invocationMode)) { + modeProperty = InvocableJAXBSchema.SUPPORTS_SINGLE_DOC; + params.put(REPORTS_STD_CSID_PARAM, invContext.getSingleCSID()); + } else if(Invocable.INVOCATION_MODE_LIST.equalsIgnoreCase(invocationMode)) { + modeProperty = InvocableJAXBSchema.SUPPORTS_DOC_LIST; + List csids = null; + InvocationContext.ListCSIDs listThing = invContext.getListCSIDs(); + if(listThing!=null) { + csids = listThing.getCsid(); + } + if(csids==null||csids.isEmpty()){ + throw new BadRequestException( + "ReportResource: Report invoked in list mode, with no csids in list." ); + } + StringBuilder sb = new StringBuilder(); + boolean first = true; + for(String csidItem : csids) { + if(first) + first = false; + else + sb.append(CSID_LIST_SEPARATOR); + sb.append(csidItem); + } + params.put(REPORTS_STD_CSIDLIST_PARAM, sb.toString()); + } else if(Invocable.INVOCATION_MODE_GROUP.equalsIgnoreCase(invocationMode)) { + modeProperty = InvocableJAXBSchema.SUPPORTS_GROUP; + params.put(REPORTS_STD_GROUPCSID_PARAM, invContext.getGroupCSID()); + } else if(Invocable.INVOCATION_MODE_NO_CONTEXT.equalsIgnoreCase(invocationMode)) { + modeProperty = InvocableJAXBSchema.SUPPORTS_NO_CONTEXT; + checkDocType = false; + } else { + throw new BadRequestException("ReportResource: unknown Invocation Mode: " + +invocationMode); + } + + RepositoryJavaClientImpl repoClient = (RepositoryJavaClientImpl)this.getRepositoryClient(ctx); + repoSession = this.getRepositorySession(); + if (repoSession == null) { + repoSession = repoClient.getRepositorySession(); + releaseRepoSession = true; + } + + String reportFileName = null; + // Get properties from the batch docModel, and release the session + try { + DocumentWrapper wrapper = repoClient.getDoc(repoSession, ctx, csid); + DocumentModel docModel = wrapper.getWrappedObject(); + Boolean supports = (Boolean)docModel.getPropertyValue(modeProperty); + if(supports == null || !supports) { + throw new BadRequestException( + "ReportResource: This Report does not support Invocation Mode: " + +invocationMode); + } + if(checkDocType) { + List forDocTypeList = + (List)docModel.getPropertyValue(InvocableJAXBSchema.FOR_DOC_TYPES); + if(forDocTypeList==null + || !forDocTypeList.contains(invContext.getDocType())) { + throw new BadRequestException( + "ReportResource: Invoked with unsupported document type: " + +invContext.getDocType()); + } + } + reportFileName = (String)docModel.getPropertyValue(ReportJAXBSchema.FILENAME); + } catch (PropertyException pe) { + if (logger.isDebugEnabled()) { + logger.debug("Property exception getting batch values: ", pe); + } + throw pe; + } catch (DocumentException de) { + if (logger.isDebugEnabled()) { + logger.debug("Problem getting batch doc: ", de); + } + throw de; + } catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.debug("Caught exception ", e); + } + throw new DocumentException(e); + } finally { + if (releaseRepoSession && repoSession != null) { + repoClient.releaseRepositorySession(repoSession); + } + } + return buildReportResponse(csid, params, reportFileName); + } + + + private Response buildReportResponse(String reportCSID, HashMap params, String reportFileName) + throws Exception { + Connection conn = null; + Response response = null; + try { + String fullPath = ServiceMain.getInstance().getServerRootDir() + + File.separator + ConfigReader.CSPACE_DIR_NAME + + File.separator + REPORTS_FOLDER + + // File.separator + tenantName + + File.separator + reportFileName; + conn = getConnection(); + + if (logger.isTraceEnabled()) { + logger.trace("ReportResource for Report csid=" + reportCSID + +" opening report file: "+fullPath); + } + FileInputStream fileStream = new FileInputStream(fullPath); + + // fill the report + JasperPrint jasperprint = JasperFillManager.fillReport(fileStream, params,conn); + // export report to pdf and build a response with the bytes + byte[] pdfasbytes = JasperExportManager.exportReportToPdf(jasperprint); + + // Need to set response type for what is requested... + response = Response.ok(pdfasbytes, "application/pdf").build(); + + return response; + } catch (SQLException sqle) { + // SQLExceptions can be chained. We have at least one exception, so + // set up a loop to make sure we let the user know about all of them + // if there happens to be more than one. + if (logger.isDebugEnabled()) { + SQLException tempException = sqle; + while (null != tempException) { + logger.debug("SQL Exception: " + sqle.getLocalizedMessage()); + + // loop to the next exception + tempException = tempException.getNextException(); + } + } + response = Response.status( + Response.Status.INTERNAL_SERVER_ERROR).entity( + "Invoke failed (SQL problem) on Report csid=" + reportCSID).type("text/plain").build(); + throw new WebApplicationException(response); + } catch (JRException jre) { + if (logger.isDebugEnabled()) { + logger.debug("JR Exception: " + jre.getLocalizedMessage() + " Cause: "+jre.getCause()); + } + response = Response.status( + Response.Status.INTERNAL_SERVER_ERROR).entity( + "Invoke failed (Jasper problem) on Report csid=" + reportCSID).type("text/plain").build(); + throw new WebApplicationException(response); + } catch (FileNotFoundException fnfe) { + if (logger.isDebugEnabled()) { + logger.debug("FileNotFoundException: " + fnfe.getLocalizedMessage()); + } + response = Response.status( + Response.Status.INTERNAL_SERVER_ERROR).entity( + "Invoke failed (SQL problem) on Report csid=" + reportCSID).type("text/plain").build(); + throw new WebApplicationException(response); + } finally { + if(conn!=null) { + try { + conn.close(); + } catch (SQLException sqle) { + // SQLExceptions can be chained. We have at least one exception, so + // set up a loop to make sure we let the user know about all of them + // if there happens to be more than one. + if (logger.isDebugEnabled()) { + logger.debug("SQL Exception closing connection: " + + sqle.getLocalizedMessage()); + } + } catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.debug("Exception closing connection", e); + } + } + } + } + } + + private Connection getConnection() throws NamingException, SQLException { + return JDBCTools.getConnection(REPOSITORY_NAME); + } } -- 2.47.3