From 35d24e63ed6aaf3ecd149a420f631fe2ecb46612 Mon Sep 17 00:00:00 2001 From: Patrick Schmitz Date: Mon, 11 Jul 2011 22:12:50 +0000 Subject: [PATCH] CSPACE-2391, 2503, 4201, 4202, 4204, 4206 Updated Reporting invocation to follow model of batch process with an invocation context. Allows passing CSID, list of CSIDs, or group CSID into a report using paramater map. Ported simple acquisition report to Postgres to test. Still working on test support that verifies PDF output. Added groundwork looking ahead for passing in additional parameters to reports. Updated dependencies for build to use libs that support version 4 of iReport. Tweaked Batch support to use common definitions for invocation-related definitions. Added basic grant information for reader user, although admin must currently complete grant by hand. --- .../services/BatchJAXBSchema.java | 9 +- .../services/batch/BatchResource.java | 17 +-- .../services/jaxb/InvocableJAXBSchema.java | 12 ++ .../src/main/resources/invocationContext.xsd | 14 +++ .../main/resources/schemas/reports_common.xsd | 5 +- .../services/ReportJAXBSchema.java | 6 +- .../services/ReportListItemJAXBSchema.java | 10 -- .../src/main/resources/reports-common.xsd | 21 ++-- services/report/pom.xml | 8 +- .../services/report/ReportResource.java | 114 +++++++++++++++++- .../nuxeo/ReportDocumentModelHandler.java | 8 +- src/main/resources/db/postgresql/init_db.sql | 10 +- 12 files changed, 183 insertions(+), 51 deletions(-) create mode 100644 services/jaxb/src/main/java/org/collectionspace/services/jaxb/InvocableJAXBSchema.java delete mode 100644 services/report/jaxb/src/main/java/org/collectionspace/services/ReportListItemJAXBSchema.java diff --git a/services/batch/jaxb/src/main/java/org/collectionspace/services/BatchJAXBSchema.java b/services/batch/jaxb/src/main/java/org/collectionspace/services/BatchJAXBSchema.java index da083363c..5d2c60b08 100644 --- a/services/batch/jaxb/src/main/java/org/collectionspace/services/BatchJAXBSchema.java +++ b/services/batch/jaxb/src/main/java/org/collectionspace/services/BatchJAXBSchema.java @@ -3,14 +3,11 @@ */ package org.collectionspace.services; -public interface BatchJAXBSchema { +import org.collectionspace.services.jaxb.InvocableJAXBSchema; + +public interface BatchJAXBSchema extends InvocableJAXBSchema { final static String BATCH_NAME = "name"; final static String BATCH_NOTES = "notes"; - final static String BATCH_FOR_DOC_TYPE = "forDocType"; - final static String BATCH_SUPPORTS_SINGLE_DOC = "supportsSingleDoc"; - final static String BATCH_SUPPORTS_DOC_LIST = "supportsDocList"; - final static String BATCH_SUPPORTS_GROUP = "supportsGroup"; - // NYI final static String BATCH_SUPPORTS_SINGLE_DOC = "supportsSingleDoc"; final static String BATCH_CREATES_NEW_FOCUS = "createsNewFocus"; final static String BATCH_CLASS_NAME = "className"; } 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 c3b12682a..0db8fecb2 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 @@ -26,6 +26,7 @@ package org.collectionspace.services.batch; import java.util.List; import org.collectionspace.services.BatchJAXBSchema; +import org.collectionspace.services.jaxb.InvocableJAXBSchema; import org.collectionspace.services.client.BatchClient; import org.collectionspace.services.client.IQueryManager; import org.collectionspace.services.client.PoxPayloadIn; @@ -151,7 +152,7 @@ public class BatchResource extends ResourceBase { throw new RuntimeException("No docType specified."); } String ptClause = COMMON_SCHEMA + ":" - + BatchJAXBSchema.BATCH_FOR_DOC_TYPE + + BatchJAXBSchema.FOR_DOC_TYPE + "='" + trimmed + "'"; return ptClause; } @@ -163,11 +164,11 @@ public class BatchResource extends ResourceBase { } String ptClause = COMMON_SCHEMA + ":"; if(Invocable.INVOCATION_MODE_SINGLE.equalsIgnoreCase(trimmed)) { - ptClause += BatchJAXBSchema.BATCH_SUPPORTS_SINGLE_DOC + "!=0"; + ptClause += BatchJAXBSchema.SUPPORTS_SINGLE_DOC + "!=0"; } else if(Invocable.INVOCATION_MODE_LIST.equalsIgnoreCase(trimmed)) { - ptClause += BatchJAXBSchema.BATCH_SUPPORTS_DOC_LIST + "!=0"; + ptClause += BatchJAXBSchema.SUPPORTS_DOC_LIST + "!=0"; } else if(Invocable.INVOCATION_MODE_GROUP.equalsIgnoreCase(trimmed)) { - ptClause += BatchJAXBSchema.BATCH_SUPPORTS_GROUP + "!=0"; + ptClause += BatchJAXBSchema.SUPPORTS_GROUP + "!=0"; } else { throw new BadRequestException("No mode specified."); } @@ -192,11 +193,11 @@ public class BatchResource extends ResourceBase { String invocationMode = invContext.getMode(); String modeProperty = null; if(BatchInvocable.INVOCATION_MODE_SINGLE.equalsIgnoreCase(invocationMode)) { - modeProperty = BatchJAXBSchema.BATCH_SUPPORTS_SINGLE_DOC; + modeProperty = BatchJAXBSchema.SUPPORTS_SINGLE_DOC; } else if(BatchInvocable.INVOCATION_MODE_LIST.equalsIgnoreCase(invocationMode)) { - modeProperty = BatchJAXBSchema.BATCH_SUPPORTS_DOC_LIST; + modeProperty = BatchJAXBSchema.SUPPORTS_DOC_LIST; } else if(BatchInvocable.INVOCATION_MODE_GROUP.equalsIgnoreCase(invocationMode)) { - modeProperty = BatchJAXBSchema.BATCH_SUPPORTS_GROUP; + modeProperty = BatchJAXBSchema.SUPPORTS_GROUP; } else { throw new BadRequestException("BatchResource: unknown Invocation Mode: " +invocationMode); @@ -225,7 +226,7 @@ public class BatchResource extends ResourceBase { +invocationMode); } String forDocType = - (String)docModel.getPropertyValue(BatchJAXBSchema.BATCH_FOR_DOC_TYPE); + (String)docModel.getPropertyValue(BatchJAXBSchema.FOR_DOC_TYPE); if(!forDocType.equalsIgnoreCase(invContext.getDocType())) { throw new BadRequestException( "BatchResource: Invoked with unsupported document type: " diff --git a/services/jaxb/src/main/java/org/collectionspace/services/jaxb/InvocableJAXBSchema.java b/services/jaxb/src/main/java/org/collectionspace/services/jaxb/InvocableJAXBSchema.java new file mode 100644 index 000000000..cfae32486 --- /dev/null +++ b/services/jaxb/src/main/java/org/collectionspace/services/jaxb/InvocableJAXBSchema.java @@ -0,0 +1,12 @@ +/** + * + */ +package org.collectionspace.services.jaxb; + +public interface InvocableJAXBSchema { + final static String FOR_DOC_TYPE = "forDocType"; + final static String SUPPORTS_SINGLE_DOC = "supportsSingleDoc"; + final static String SUPPORTS_DOC_LIST = "supportsDocList"; + final static String SUPPORTS_GROUP = "supportsGroup"; + // NYI final static String SUPPORTS_QUERY "supportsQuery"; +} diff --git a/services/jaxb/src/main/resources/invocationContext.xsd b/services/jaxb/src/main/resources/invocationContext.xsd index 8c5089af9..8c8ed9cec 100644 --- a/services/jaxb/src/main/resources/invocationContext.xsd +++ b/services/jaxb/src/main/resources/invocationContext.xsd @@ -30,6 +30,20 @@ + + + + + + + + + + + + + + diff --git a/services/report/3rdparty/nuxeo-platform-cs-report/src/main/resources/schemas/reports_common.xsd b/services/report/3rdparty/nuxeo-platform-cs-report/src/main/resources/schemas/reports_common.xsd index 9632dad0c..fe3f02c34 100644 --- a/services/report/3rdparty/nuxeo-platform-cs-report/src/main/resources/schemas/reports_common.xsd +++ b/services/report/3rdparty/nuxeo-platform-cs-report/src/main/resources/schemas/reports_common.xsd @@ -23,7 +23,10 @@ - + + + + diff --git a/services/report/jaxb/src/main/java/org/collectionspace/services/ReportJAXBSchema.java b/services/report/jaxb/src/main/java/org/collectionspace/services/ReportJAXBSchema.java index 19548d4c6..d5a461fea 100644 --- a/services/report/jaxb/src/main/java/org/collectionspace/services/ReportJAXBSchema.java +++ b/services/report/jaxb/src/main/java/org/collectionspace/services/ReportJAXBSchema.java @@ -3,16 +3,16 @@ */ package org.collectionspace.services; +import org.collectionspace.services.jaxb.InvocableJAXBSchema; + /** * @author pschmitz * */ -public interface ReportJAXBSchema { +public interface ReportJAXBSchema extends InvocableJAXBSchema { final static String NAME = "name"; final static String NOTES = "notes"; final static String FILENAME = "filename"; - final static String FOR_SINGLE_DOC = "forSingleDoc"; - final static String FOR_DOC_TYPE = "forDocType"; final static String OUTPUT_MIME = "outputMIME"; } diff --git a/services/report/jaxb/src/main/java/org/collectionspace/services/ReportListItemJAXBSchema.java b/services/report/jaxb/src/main/java/org/collectionspace/services/ReportListItemJAXBSchema.java deleted file mode 100644 index 379ec85f1..000000000 --- a/services/report/jaxb/src/main/java/org/collectionspace/services/ReportListItemJAXBSchema.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.collectionspace.services; - -public interface ReportListItemJAXBSchema { - final static String NAME = "name"; - final static String FOR_SINGLE_DOC = "forSingleDoc"; - final static String FOR_DOC_TYPE = "forDocType"; - final static String OUTPUT_MIME ="outputMIME"; - final static String CSID = "csid"; - final static String URI = "url"; -} diff --git a/services/report/jaxb/src/main/resources/reports-common.xsd b/services/report/jaxb/src/main/resources/reports-common.xsd index 7e874858b..8745f0a38 100644 --- a/services/report/jaxb/src/main/resources/reports-common.xsd +++ b/services/report/jaxb/src/main/resources/reports-common.xsd @@ -32,12 +32,15 @@ - - - - - - + + + + + + + + + @@ -66,7 +69,11 @@ minOccurs="1" /> - + + - net.sf.jasperreports - jasperreports - 3.7.3 + net.sf.jasperreports + jasperreports + 4.0.1 org.codehaus.groovy groovy-all - 1.5.5 + 1.7.5 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 7935018b1..58c23b3e2 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 @@ -27,17 +27,28 @@ 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.jaxb.InvocableJAXBSchema; import org.collectionspace.services.ReportJAXBSchema; import org.collectionspace.services.client.PoxPayloadIn; import org.collectionspace.services.client.PoxPayloadOut; import org.collectionspace.services.client.ReportClient; import org.collectionspace.services.common.ResourceBase; +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.DocumentHandler; import org.collectionspace.services.common.document.DocumentNotFoundException; 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.collectionspace.services.common.security.UnauthorizedException; +import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.nuxeo.ecm.core.api.DocumentModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,24 +59,28 @@ import javax.security.auth.login.LoginException; import javax.sql.DataSource; import javax.ws.rs.Consumes; import javax.ws.rs.GET; +import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import java.io.File; import java.io.FileInputStream; import java.sql.Connection; import java.sql.SQLException; import java.util.HashMap; +import java.util.List; @Path(ReportClient.SERVICE_PATH) @Consumes("application/xml") @Produces("application/xml") //@Produces("application/xml;charset=UTF-8") public class ReportResource extends ResourceBase { - private static String repositoryName = "NuxeoDS"; - private static String reportsFolder = "reports"; + private static String REPOSITORY_NAME = "NuxeoDS"; + private static String REPORTS_FOLDER = "reports"; + private static String CSID_LIST_SEPARATOR = ","; final Logger logger = LoggerFactory.getLogger(ReportResource.class); @Override @@ -83,6 +98,17 @@ public class ReportResource extends ResourceBase { public Class getCommonPartClass() { return ReportsCommon.class; } + + /* + * TODO: provide a static utility that will load a report, interrogate it + * for information about the properties, and return that information. + * See: http://jasperreports.sourceforge.net/api/net/sf/jasperreports/engine/JasperManager.html#loadReport%28java.lang.String%29 + * to get the report from the file. + * Use: http://jasperreports.sourceforge.net/api/net/sf/jasperreports/engine/base/JRBaseReport.html#getParameters%28%29 + * to get an array of http://jasperreports.sourceforge.net/api/net/sf/jasperreports/engine/JRParameter.html + * Cast each to JRBaseParameter and use isSystemDefined to filter out + * the system defined parameters. + */ /** * Gets the report. @@ -112,7 +138,7 @@ public class ReportResource extends ResourceBase { String reportFileName = (String)docModel.getPropertyValue(ReportJAXBSchema.FILENAME); String fullPath = ServiceMain.getInstance().getServerRootDir() + File.separator + ConfigReader.CSPACE_DIR_NAME + - File.separator + reportsFolder + + File.separator + REPORTS_FOLDER + File.separator + reportFileName; Connection conn = getConnection(); HashMap params = new HashMap(); @@ -176,20 +202,96 @@ public class ReportResource extends ResourceBase { } return response; } + + @POST + @Path("{csid}") + @Produces("application/pdf") + public Response invokeReport( + @PathParam("csid") String csid, + 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; + HashMap params = new HashMap(); + if(Invocable.INVOCATION_MODE_SINGLE.equalsIgnoreCase(invocationMode)) { + modeProperty = InvocableJAXBSchema.SUPPORTS_SINGLE_DOC; + params.put("csid", 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("csidlist", sb.toString()); + } else if(Invocable.INVOCATION_MODE_GROUP.equalsIgnoreCase(invocationMode)) { + modeProperty = InvocableJAXBSchema.SUPPORTS_GROUP; + params.put("groupcsid", invContext.getGroupCSID()); + } else { + throw new BadRequestException("ReportResource: unknown Invocation Mode: " + +invocationMode); + } + Boolean supports = (Boolean)docModel.getPropertyValue(modeProperty); + if(!supports) { + throw new BadRequestException( + "ReportResource: This Report does not support Invocation Mode: " + +invocationMode); + } + String reportFileName = (String)docModel.getPropertyValue(ReportJAXBSchema.FILENAME); + String fullPath = ServiceMain.getInstance().getServerRootDir() + + File.separator + ConfigReader.CSPACE_DIR_NAME + + File.separator + REPORTS_FOLDER + + // File.separator + tenantName + + File.separator + reportFileName; + Connection conn = getConnection(); + + 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 = Response.ok(pdfasbytes, "application/pdf").build(); + + return response; + } catch (Exception e) { + throw bigReThrow(e, ServiceMessages.POST_FAILED); + } + } private Connection getConnection() throws LoginException, SQLException { InitialContext ctx = null; Connection conn = null; try { ctx = new InitialContext(); - DataSource ds = (DataSource) ctx.lookup(repositoryName); + DataSource ds = (DataSource) ctx.lookup(REPOSITORY_NAME); if (ds == null) { - throw new IllegalArgumentException("datasource not found: " + repositoryName); + throw new IllegalArgumentException("datasource not found: " + REPOSITORY_NAME); } conn = ds.getConnection(); return conn; } catch (NamingException ex) { - LoginException le = new LoginException("Error looking up DataSource from: " + repositoryName); + LoginException le = new LoginException("Error looking up DataSource from: " + REPOSITORY_NAME); le.initCause(ex); throw le; } finally { 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 1518bc8a8..db40ddf92 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 @@ -132,10 +132,14 @@ public class ReportDocumentModelHandler ReportJAXBSchema.NAME)); ilistItem.setOutputMIME((String) docModel.getProperty(label, ReportJAXBSchema.OUTPUT_MIME)); - ilistItem.setForSingleDoc((Boolean) docModel.getProperty(label, - ReportJAXBSchema.FOR_SINGLE_DOC)); ilistItem.setForDocType((String) docModel.getProperty(label, ReportJAXBSchema.FOR_DOC_TYPE)); + ilistItem.setSupportsSingleDoc((Boolean) docModel.getProperty(label, + ReportJAXBSchema.SUPPORTS_SINGLE_DOC)); + ilistItem.setSupportsDocList((Boolean) docModel.getProperty(label, + ReportJAXBSchema.SUPPORTS_DOC_LIST)); + ilistItem.setSupportsGroup((Boolean) docModel.getProperty(label, + ReportJAXBSchema.SUPPORTS_GROUP)); String id = getCsid(docModel);//NuxeoUtils.extractId(docModel.getPathAsString()); ilistItem.setUri(getServiceContextPath() + id); ilistItem.setCsid(id); diff --git a/src/main/resources/db/postgresql/init_db.sql b/src/main/resources/db/postgresql/init_db.sql index 9817d6156..29d3658bd 100644 --- a/src/main/resources/db/postgresql/init_db.sql +++ b/src/main/resources/db/postgresql/init_db.sql @@ -19,7 +19,9 @@ CREATE DATABASE nuxeo ENCODING 'UTF8' OWNER @DB_NUXEO_USER@; -- -- Grant privileges to read-only user on Nuxeo, for reporting. -- --- GRANT SELECT ON ALL TABLES IN DATABASE nuxeo TO reader; --- Will have to do this with a script after the nuxeo DB has been started, --- since there is no wildcard syntax for grants (!). If nuxeo used a schema, --- it would be easy. Check that. +GRANT CONNECT ON DATABASE nuxeo TO reader; + +-- GRANT SELECT ON ALL TABLES IN SCHEMA public TO reader; +-- This must be run by hand, after the system has already started up, +-- so that it gives access to all the tables created on init. + -- 2.47.3