]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
b3244829a98534515fa87e15d2489bd22493d219
[tmp/jakarta-migration.git] /
1 /**
2  *  This document is a part of the source code and related artifacts
3  *  for CollectionSpace, an open source collections management system
4  *  for museums and related institutions:
5
6  *  http://www.collectionspace.org
7  *  http://wiki.collectionspace.org
8
9  *  Copyright 2009 University of California at Berkeley
10
11  *  Licensed under the Educational Community License (ECL), Version 2.0.
12  *  You may not use this file except in compliance with this License.
13
14  *  You may obtain a copy of the ECL 2.0 License at
15
16  *  https://source.collectionspace.org/collection-space/LICENSE.txt
17
18  *  Unless required by applicable law or agreed to in writing, software
19  *  distributed under the License is distributed on an "AS IS" BASIS,
20  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  *  See the License for the specific language governing permissions and
22  *  limitations under the License.
23  */
24 package org.collectionspace.services.report.nuxeo;
25
26 import java.io.File;
27 import java.io.FileInputStream;
28 import java.io.FileNotFoundException;
29 import java.io.FileOutputStream;
30 import java.io.InputStream;
31 import java.nio.file.Files;
32 import java.sql.Connection;
33 import java.sql.SQLException;
34 import java.util.HashMap;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.regex.Pattern;
38
39 import javax.ws.rs.core.MediaType;
40 import javax.naming.NamingException;
41 import javax.ws.rs.core.Response;
42
43 import net.sf.jasperreports.engine.JRException;
44 import net.sf.jasperreports.engine.JRExporter;
45 import net.sf.jasperreports.engine.JRExporterParameter;
46 import net.sf.jasperreports.engine.JRParameter;
47 import net.sf.jasperreports.engine.JasperCompileManager;
48 import net.sf.jasperreports.engine.JasperFillManager;
49 import net.sf.jasperreports.engine.JasperPrint;
50 import net.sf.jasperreports.engine.export.JRCsvExporter;
51 import net.sf.jasperreports.engine.export.JRCsvExporterParameter;
52 import net.sf.jasperreports.engine.export.JRHtmlExporter;
53 import net.sf.jasperreports.engine.export.JRPdfExporter;
54 import net.sf.jasperreports.engine.export.JRXmlExporter;
55 import net.sf.jasperreports.engine.export.ooxml.JRDocxExporter;
56 import net.sf.jasperreports.engine.export.ooxml.JRPptxExporter;
57 import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter;
58
59 import org.collectionspace.authentication.AuthN;
60 import org.collectionspace.services.ReportJAXBSchema;
61 import org.collectionspace.services.account.AccountResource;
62 import org.collectionspace.services.authorization.AuthZ;
63 import org.collectionspace.services.authorization.CSpaceResource;
64 import org.collectionspace.services.authorization.PermissionException;
65 import org.collectionspace.services.authorization.URIResourceImpl;
66 import org.collectionspace.services.authorization.perms.ActionType;
67 import org.collectionspace.services.report.ResourceActionGroup;
68 import org.collectionspace.services.report.ResourceActionGroupList;
69 import org.collectionspace.services.report.ReportsCommon.ForRoles;
70 import org.collectionspace.services.report.MIMEType;
71 import org.collectionspace.services.report.MIMETypeItemType;
72 import org.collectionspace.services.report.ReportsCommon;
73 import org.collectionspace.services.report.ReportsOuputMimeList;
74 import org.collectionspace.services.client.PoxPayloadIn;
75 import org.collectionspace.services.client.PoxPayloadOut;
76 import org.collectionspace.services.client.ReportClient;
77 import org.collectionspace.services.common.CSWebApplicationException;
78 import org.collectionspace.services.common.ServiceMain;
79 import org.collectionspace.services.common.api.JEEServerDeployment;
80 import org.collectionspace.services.common.api.FileTools;
81 import org.collectionspace.services.common.api.Tools;
82 import org.collectionspace.services.common.authorization_mgt.ActionGroup;
83 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
84 import org.collectionspace.services.common.context.ServiceBindingUtils;
85 import org.collectionspace.services.common.context.ServiceContext;
86 import org.collectionspace.services.common.document.BadRequestException;
87 import org.collectionspace.services.common.document.DocumentException;
88 import org.collectionspace.services.common.document.DocumentWrapper;
89 import org.collectionspace.services.common.invocable.Invocable;
90 import org.collectionspace.services.common.invocable.InvocationContext;
91 import org.collectionspace.services.common.storage.JDBCTools;
92 import org.collectionspace.services.config.service.ServiceBindingType;
93 import org.collectionspace.services.config.types.PropertyItemType;
94 import org.collectionspace.services.jaxb.InvocableJAXBSchema;
95 import org.collectionspace.services.nuxeo.client.java.NuxeoDocumentModelHandler;
96 import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface;
97 import org.collectionspace.services.nuxeo.client.java.NuxeoRepositoryClientImpl;
98 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
99
100 import org.jfree.util.Log;
101
102 import org.nuxeo.ecm.core.api.model.PropertyException;
103 import org.nuxeo.ecm.core.api.DocumentModel;
104
105 import org.slf4j.Logger;
106 import org.slf4j.LoggerFactory;
107
108 /**
109  * ReportDocumentModelHandler
110  *
111  * $LastChangedRevision: $
112  * $LastChangedDate: $
113  */
114 public class ReportDocumentModelHandler extends NuxeoDocumentModelHandler<ReportsCommon> {
115                 private final Logger logger = LoggerFactory.getLogger(ReportDocumentModelHandler.class);
116
117                 private static final Pattern INVALID_CSID_PATTERN = Pattern.compile("[^\\w\\-]");
118     private static String REPORTS_FOLDER = "reports";
119     private static String CSID_LIST_SEPARATOR = ",";
120
121     private static String REPORTS_STD_CSID_PARAM = "csid";
122     private static String REPORTS_STD_GROUPCSID_PARAM = "groupcsid";
123     private static String REPORTS_STD_CSIDLIST_PARAM = "csidlist";
124     private static String REPORTS_STD_TENANTID_PARAM = "tenantid";
125
126     //
127     // Map the MIME types from the service bindings to our payload output
128     //
129     public ReportsOuputMimeList getSupportMIMETypes(
130                 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx) {
131         //
132         // Create a new payload response instance and initialize it
133         //
134         ReportsOuputMimeList result = new ReportsOuputMimeList();
135         MIMEType resultMIMEType = result.getMIMETypeList();
136         if (resultMIMEType == null) {
137                 result.setMIMETypeList(resultMIMEType = new MIMEType());
138         }
139         List<MIMETypeItemType> resultMIMETypeItemList = resultMIMEType.getMIMEType();
140
141         //
142         // Read the MIME type values from the service bindings and put into our response payload
143         //
144         TenantBindingConfigReaderImpl tReader =
145                 ServiceMain.getInstance().getTenantBindingConfigReader();
146         ServiceBindingType reportServiceBinding = tReader.getServiceBinding(ctx.getTenantId(), ctx.getServiceName());
147         List<PropertyItemType> bindingsMIMETypeList = ServiceBindingUtils.getPropertyValueList(reportServiceBinding, ServiceBindingUtils.OUTPUT_MIME_PROP);
148
149         if (bindingsMIMETypeList != null) {
150                 for (PropertyItemType bindingItemMimeType : bindingsMIMETypeList) {
151                         MIMETypeItemType resultMimeTypeItem = new MIMETypeItemType();
152                         String displayName = bindingItemMimeType.getDisplayName();
153                         if (displayName != null && displayName.trim().isEmpty() == false) {
154                         resultMimeTypeItem.setKey(displayName);
155                         } else {
156                         resultMimeTypeItem.setKey(bindingItemMimeType.getValue());
157                         }
158                         resultMimeTypeItem.setValue(bindingItemMimeType.getValue());
159                         resultMIMETypeItemList.add(resultMimeTypeItem);
160                 }
161         }
162
163         return result;
164     }
165
166     private String getInvocationContextLogging(InvocationContext invContext, Map<String, Object> params) {
167                 String outputMIME = invContext.getOutputMIME();
168                 String mode = invContext.getMode();
169                 String updateCoreValues = invContext.getUpdateCoreValues();
170                 String docType = invContext.getDocType();
171                 String singleCSID = invContext.getSingleCSID();
172                 String groupCSID = invContext.getGroupCSID();
173                 String listCSIDs = invContext.getListCSIDs() == null ? "" : invContext.getListCSIDs().toString();
174
175                 String result =
176                                 "{MIME type: "  + outputMIME +
177                                 "\n \t Context mode: " + mode +
178                                 "\n \t Update Core Values: " + updateCoreValues +
179                                 "\n \t Document type: " + docType +
180                                 "\n \t CSID: " + singleCSID +
181                                 "\n \t Group CSID: " + groupCSID +
182                                 "\n \t List CSIDs: " + listCSIDs +
183                                 "\n \t Parameters: " + params.toString() + "}";
184                 return result;
185         }
186
187         private String assertValidCsid(String csid) throws IllegalArgumentException {
188                 if (INVALID_CSID_PATTERN.matcher(csid).find()) {
189                         throw new IllegalArgumentException("Invalid csid: " + csid);
190                 }
191
192                 return csid;
193         }
194
195         public InputStream invokeReport(
196                         ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
197                         String csid,
198                         ReportsCommon reportsCommon,
199                         InvocationContext invContext,
200                         StringBuffer outMimeType,
201                         StringBuffer outReportFileName) throws Exception {
202                 CoreSessionInterface repoSession = null;
203                 boolean releaseRepoSession = false;
204
205                 // Ensure the current user has permission to run this report
206                 if (isAuthoritzed(reportsCommon) == false) {
207                         String msg = String.format("Report Resource: The user '%s' is not authorized to run the report '%s' CSID='%s'",
208                                         AuthN.get().getUserId(), reportsCommon.getName(), csid);
209                         throw new PermissionException(msg);
210                 }
211
212                 String invocationMode = invContext.getMode();
213                 String modeProperty = null;
214                 HashMap<String, Object> params = new HashMap<String, Object>();
215                 params.put(REPORTS_STD_TENANTID_PARAM, ctx.getTenantId());
216                 boolean checkDocType = true;
217
218                 // Note we set before we put in the default ones, so they cannot override tenant or CSID.
219                 setParamsFromContext(params, invContext);
220
221                 if (Invocable.INVOCATION_MODE_SINGLE.equalsIgnoreCase(invocationMode)) {
222                         modeProperty = InvocableJAXBSchema.SUPPORTS_SINGLE_DOC;
223                         params.put(REPORTS_STD_CSID_PARAM, assertValidCsid(invContext.getSingleCSID()));
224                 } else if (Invocable.INVOCATION_MODE_LIST.equalsIgnoreCase(invocationMode)) {
225                         modeProperty = InvocableJAXBSchema.SUPPORTS_DOC_LIST;
226                         List<String> csids = null;
227                         InvocationContext.ListCSIDs listThing = invContext.getListCSIDs();
228                                 if (listThing!=null) {
229                                         csids = listThing.getCsid();
230                                 }
231                                 if (csids==null||csids.isEmpty()){
232                                 throw new BadRequestException(
233                                                 "ReportResource: Report invoked in list mode, with no csids in list." );
234                                 }
235                                 StringBuilder sb = new StringBuilder();
236                                 boolean first = true;
237                                 for(String csidItem : csids) {
238                                         if(first)
239                                                 first = false;
240                                         else
241                                                 sb.append(CSID_LIST_SEPARATOR);
242                                         sb.append(assertValidCsid(csidItem));
243                                 }
244                 params.put(REPORTS_STD_CSIDLIST_PARAM, sb.toString());
245                 } else if(Invocable.INVOCATION_MODE_GROUP.equalsIgnoreCase(invocationMode)) {
246                         modeProperty = InvocableJAXBSchema.SUPPORTS_GROUP;
247                         params.put(REPORTS_STD_GROUPCSID_PARAM, assertValidCsid(invContext.getGroupCSID()));
248                 } else if(Invocable.INVOCATION_MODE_NO_CONTEXT.equalsIgnoreCase(invocationMode)) {
249                         modeProperty = InvocableJAXBSchema.SUPPORTS_NO_CONTEXT;
250                         checkDocType = false;
251                 } else {
252                         throw new BadRequestException("ReportResource: unknown Invocation Mode: "
253                                 +invocationMode);
254                 }
255
256                 logger.debug("The invocation context is: \n " + getInvocationContextLogging(invContext, params));
257                 logger.debug("The report is being called with the following parameters, which are being passed to Jasper: \n" + params.toString());
258                 logger.debug("The mode being passed to Jasper is: " + invocationMode);
259
260                 NuxeoRepositoryClientImpl repoClient = (NuxeoRepositoryClientImpl)this.getRepositoryClient(ctx);
261                 repoSession = this.getRepositorySession();
262                 if (repoSession == null) {
263                         repoSession = repoClient.getRepositorySession(ctx);
264                         releaseRepoSession = true;
265                 }
266
267                 // Get properties from the report docModel, and release the session
268                 String reportFileNameProperty;
269                 try {
270                         DocumentWrapper<DocumentModel> wrapper = repoClient.getDoc(repoSession, ctx, csid);
271                         DocumentModel docModel = wrapper.getWrappedObject();
272                         Boolean supports = (Boolean) NuxeoUtils.getProperyValue(docModel, modeProperty); //docModel.getPropertyValue(modeProperty);
273                         if(supports == null || !supports) {
274                                 throw new BadRequestException(
275                                                 "ReportResource: This Report does not support Invocation Mode: "
276                                         +invocationMode);
277                         }
278                 if (checkDocType) {
279                         List<String> forDocTypeList =
280                                 (List<String>) NuxeoUtils.getProperyValue(docModel, InvocableJAXBSchema.FOR_DOC_TYPES); //docModel.getPropertyValue(InvocableJAXBSchema.FOR_DOC_TYPES);
281                         if (forDocTypeList==null || !forDocTypeList.contains(invContext.getDocType())) {
282                                 throw new BadRequestException(
283                                                 "ReportResource: Invoked with unsupported document type: "
284                                                 +invContext.getDocType());
285                         }
286                 }
287                 reportFileNameProperty = (String) NuxeoUtils.getProperyValue(docModel, ReportJAXBSchema.FILENAME); //docModel.getPropertyValue(ReportJAXBSchema.FILENAME)); // Set the outgoing param with the report file name
288                         //
289                 // If the invocation context contains a MIME type then use it.  Otherwise, look in the report resource.  If no MIME type in the report resource,
290                 // use the default MIME type.
291                 //
292                 if (!Tools.isEmpty(invContext.getOutputMIME())) {
293                         outMimeType.append(invContext.getOutputMIME());
294                 } else if (Tools.isEmpty(outMimeType.toString()) && params.containsKey("OutputMIME")) {
295                         // See UCB - https://github.com/cspace-deployment/services/pull/140/files
296                         outMimeType.append(params.get("OutputMIME"));
297                 } else {
298                         // Use the default
299                         String reportOutputMime = (String) NuxeoUtils.getProperyValue(docModel, ReportJAXBSchema.OUTPUT_MIME); //docModel.getPropertyValue(ReportJAXBSchema.OUTPUT_MIME);
300                         if (!Tools.isEmpty(reportOutputMime)) {
301                                 outMimeType.append(reportOutputMime);
302                         } else {
303                                 outMimeType.append(ReportClient.DEFAULT_REPORT_OUTPUT_MIME);
304                         }
305                 }
306                 } catch (PropertyException pe) {
307                         if (logger.isDebugEnabled()) {
308                                 logger.debug("Property exception getting report values: ", pe);
309                         }
310                         throw pe;
311                 } catch (DocumentException de) {
312                         if (logger.isDebugEnabled()) {
313                                 logger.debug("Problem getting report report: ", de);
314                         }
315                         throw de;
316                 } catch (Exception e) {
317                         if (logger.isDebugEnabled()) {
318                                 logger.debug("Caught exception ", e);
319                         }
320                         throw new DocumentException(e);
321                 } finally {
322                         if (releaseRepoSession && repoSession != null) {
323                                 repoClient.releaseRepositorySession(ctx, repoSession);
324                         }
325                 }
326
327         return buildReportResult(csid, params, reportFileNameProperty, outMimeType.toString(), outReportFileName);
328         }
329
330         private void setParamsFromContext(Map<String, Object> params, InvocationContext invContext) {
331                 InvocationContext.Params icParams = invContext.getParams();
332                 if(icParams!= null) {
333                         List<InvocationContext.Params.Param> icParamList = icParams.getParam();
334                         if(icParamList != null) {
335                                 for(InvocationContext.Params.Param param:icParamList) {
336                                         String key = param.getKey();
337                                         String value = param.getValue();
338                                         if(!Tools.isEmpty(key) && !Tools.isEmpty(value)) {
339                                                 params.put(key, value);
340                                         }
341                                 }
342                         }
343                 }
344
345         }
346
347     private InputStream buildReportResult(String reportCSID,
348                 HashMap<String, Object> params, String reportFileName, String outputMimeType, StringBuffer outReportFileName)
349                                 throws Exception {
350                 Connection conn = null;
351                 InputStream result = null;
352
353         try {
354                 String fileNameBase = Tools.getFilenameBase(reportFileName);
355                 String compiledReportFilename = fileNameBase+ReportClient.COMPILED_REPORT_EXTENSION;
356                 String reportDescriptionFilename = fileNameBase+ReportClient.REPORT_DECSRIPTION_EXTENSION;
357
358                         String basePath = ServiceMain.getInstance().getServerRootDir() +
359                                                                 File.separator + JEEServerDeployment.CSPACE_DIR_NAME +
360                                                                 File.separator + REPORTS_FOLDER +
361                                                                 // File.separator + tenantName +
362                                                                 File.separator; // + reportFileName;
363
364                         String compiledFilePath = basePath+compiledReportFilename;
365                         File f = new File(compiledFilePath);
366                         if(!f.exists()) { // Need to compile the file
367                                 // First verify that there is a source file.
368                                 String sourceFilePath = basePath+reportDescriptionFilename;
369                                 File f2 = new File(sourceFilePath);
370                                 if(!f2.exists()) { // Missing source file - error!
371                                         logger.error("Report for csid={} is missing the specified source file: {}",
372                                                                         reportCSID, sourceFilePath);
373                                         throw new RuntimeException("Report is missing the specified source file!");
374                                 }
375                 logger.info("Report for csid={} is not compiled. Compiling first, and saving to: {}",
376                                 reportCSID, compiledFilePath);
377                 JasperCompileManager.compileReportToFile(sourceFilePath, compiledFilePath);
378                         }
379
380                         conn = getConnection();
381
382             if (logger.isTraceEnabled()) {
383                 logger.trace("ReportResource for csid=" + reportCSID
384                                 +" output as "+outputMimeType+" using report file: "+compiledFilePath);
385             }
386                         FileInputStream fileStream = new FileInputStream(compiledFilePath);
387
388                         // export report to pdf and build a response with the bytes
389                         //JasperExportManager.exportReportToPdf(jasperprint);
390
391                         JRExporter exporter = null;
392                         // Strip extension from report filename.
393                         String outputFilename = reportFileName;
394                         // Strip extension from report filename.
395                         int idx = outputFilename.lastIndexOf(".");
396                         if(idx>0)
397                                 outputFilename = outputFilename.substring(0, idx);
398                         // Strip any sub-dir from report filename.
399                         idx = outputFilename.lastIndexOf(File.separator);
400                         if(idx>0)
401                                 outputFilename = outputFilename.substring(idx+1);
402                         if(outputMimeType.equals(MediaType.APPLICATION_XML)) {
403                                 params.put(JRParameter.IS_IGNORE_PAGINATION, Boolean.TRUE);
404                                 exporter = new JRXmlExporter();
405                                 outputFilename = outputFilename+".xml";
406                         } else if(outputMimeType.equals(MediaType.TEXT_HTML)) {
407                                 exporter = new JRHtmlExporter();
408                                 outputFilename = outputFilename+".html";
409                         } else if(outputMimeType.equals(ReportClient.PDF_MIME_TYPE)) {
410                                 exporter = new JRPdfExporter();
411                                 outputFilename = outputFilename+".pdf";
412                         } else if(outputMimeType.equals(ReportClient.CSV_MIME_TYPE)) {
413                                 params.put(JRParameter.IS_IGNORE_PAGINATION, Boolean.TRUE);
414                                 exporter = new JRCsvExporter();
415                                 exporter.setParameter(JRCsvExporterParameter.FIELD_DELIMITER, ",");
416                                 outputFilename = outputFilename+".csv";
417                         } else if(outputMimeType.equals(ReportClient.TSV_MIME_TYPE)) {
418                                 params.put(JRParameter.IS_IGNORE_PAGINATION, Boolean.TRUE);
419                                 exporter = new JRCsvExporter();
420                                 exporter.setParameter(JRCsvExporterParameter.FIELD_DELIMITER, "\t");
421                                 outputFilename = outputFilename+".csv";
422                         } else if(outputMimeType.equals(ReportClient.MSWORD_MIME_TYPE)  // Understand msword as docx
423                                         || outputMimeType.equals(ReportClient.OPEN_DOCX_MIME_TYPE)) {
424                                 exporter = new JRDocxExporter();
425                                 outputFilename = outputFilename+".docx";
426                         } else if(outputMimeType.equals(ReportClient.MSEXCEL_MIME_TYPE) // Understand msexcel as xlsx
427                                         || outputMimeType.equals(ReportClient.OPEN_XLSX_MIME_TYPE)) {
428                                 exporter = new JRXlsxExporter();
429                                 outputFilename = outputFilename+".xlsx";
430                         } else if(outputMimeType.equals(ReportClient.MSPPT_MIME_TYPE)   // Understand msppt as xlsx
431                                         || outputMimeType.equals(ReportClient.OPEN_PPTX_MIME_TYPE)) {
432                                 exporter = new JRPptxExporter();
433                                 outputFilename = outputFilename+".pptx";
434                         } else {
435                                 logger.error("Reporting: unsupported output MIME type - defaulting to PDF");
436                                 exporter = new JRPdfExporter();
437                                 outputFilename = outputFilename+"-default-to.pdf";
438                         }
439                         outReportFileName.append(outputFilename); // Set the out going param to the report's final file name
440                         // FIXME: Logging temporarily set to INFO level for CSPACE-5766;
441                         // can change to TRACE or DEBUG level as warranted thereafter
442                         if (logger.isInfoEnabled()) {
443                             logger.info(FileTools.getJavaTmpDirInfo());
444                         }
445                         // fill the report
446                         JasperPrint jasperPrint = JasperFillManager.fillReport(fileStream, params,conn);
447
448                         // Report will be to a temporary file.
449                         File tempOutputFile = Files.createTempFile("report-", null).toFile();
450                         FileOutputStream tempOutputStream = new FileOutputStream(tempOutputFile);
451                         exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
452                         exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, tempOutputStream);
453                         exporter.exportReport();
454                         tempOutputStream.close();
455
456                         result = new FileInputStream(tempOutputFile);
457                 return result;
458         } catch (SQLException sqle) {
459             // SQLExceptions can be chained. We have at least one exception, so
460             // set up a loop to make sure we let the user know about all of them
461             // if there happens to be more than one.
462             if (logger.isDebugEnabled()) {
463                     SQLException tempException = sqle;
464                     while (null != tempException) {
465                                 logger.debug("SQL Exception: " + sqle.getLocalizedMessage());
466
467                         // loop to the next exception
468                         tempException = tempException.getNextException();
469                     }
470             }
471             Response response = Response.status(
472                     Response.Status.INTERNAL_SERVER_ERROR).entity(
473                                 "Invoke failed (SQL problem) on Report csid=" + reportCSID).type("text/plain").build();
474             throw new CSWebApplicationException(sqle, response);
475         } catch (JRException jre) {
476             if (logger.isDebugEnabled()) {
477                 logger.debug("JR Exception: " + jre.getLocalizedMessage() + " Cause: "+jre.getCause());
478             }
479             Response response = Response.status(
480                     Response.Status.INTERNAL_SERVER_ERROR).entity(
481                                 "Invoke failed (Jasper problem) on Report csid=" + reportCSID).type("text/plain").build();
482             throw new CSWebApplicationException(jre, response);
483         } catch (FileNotFoundException fnfe) {
484             if (logger.isDebugEnabled()) {
485                 logger.debug("FileNotFoundException: " + fnfe.getLocalizedMessage());
486             }
487             Response response = Response.status(
488                     Response.Status.INTERNAL_SERVER_ERROR).entity(
489                                 "Invoke failed (SQL problem) on Report csid=" + reportCSID).type("text/plain").build();
490             throw new CSWebApplicationException(fnfe, response);
491                 } finally {
492                 if (conn!=null) {
493                         try {
494                                 conn.close();
495                 } catch (SQLException sqle) {
496                     // SQLExceptions can be chained. We have at least one exception, so
497                     // set up a loop to make sure we let the user know about all of them
498                     // if there happens to be more than one.
499                     if (logger.isDebugEnabled()) {
500                                 logger.debug("SQL Exception closing connection: "
501                                                 + sqle.getLocalizedMessage());
502                     }
503                 } catch (Exception e) {
504                     if (logger.isDebugEnabled()) {
505                         logger.debug("Exception closing connection", e);
506                     }
507                 }
508                 }
509         }
510     }
511
512     private Connection getConnection() throws NamingException, SQLException {
513         Connection result = null;
514
515         ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = this.getServiceContext();
516         try {
517                 String repositoryName = ctx.getRepositoryName();
518                 if (repositoryName != null && repositoryName.trim().isEmpty() == false) {
519                         String cspaceInstanceId = ServiceMain.getInstance().getCspaceInstanceId();
520                         String databaseName = JDBCTools.getDatabaseName(repositoryName, cspaceInstanceId);
521                         result = JDBCTools.getConnection(JDBCTools.NUXEO_READER_DATASOURCE_NAME, databaseName);
522                 }
523                 } catch (Exception e) {
524                         Log.error(e);
525                         throw new NamingException();
526                 }
527
528         return result;
529     }
530
531         /**
532          * Check to see if the current user is authorized to run/invoke this report.  If the report
533          * did not specify any permissions, we assume that the current user is authorized to run the report.
534          * @param reportsCommon
535          * @return
536          */
537         protected boolean isAuthoritzedWithPermissions(ReportsCommon reportsCommon) {
538                 boolean result = true;
539
540                 ResourceActionGroupList resourceActionGroupList = reportsCommon.getResourceActionGroupList();
541                 if (resourceActionGroupList != null) {
542                         String tenantId = AuthN.get().getCurrentTenantId();
543                         for (ResourceActionGroup resourceActionGroup: resourceActionGroupList.getResourceActionGroup()) {
544                                 String resourceName = resourceActionGroup.getResourceName();
545                                 ActionGroup actionGroup = ActionGroup.creatActionGroup(resourceActionGroup.getActionGroup());
546                                 for (ActionType actionType: actionGroup.getActions()) {
547                                         CSpaceResource res = new URIResourceImpl(tenantId, resourceName, AuthZ.getMethod(actionType));
548                                         if (AuthZ.get().isAccessAllowed(res) == false) {
549                                                 return false;
550                                         }
551                                 }
552                         }
553                 }
554
555                 return result;
556         }
557
558         /**
559          * Returns true if we found any required permissions.
560          *
561          * @param reportCommon
562          * @return
563          */
564         private boolean hasRequiredPermissions(ReportsCommon reportCommon) {
565                 boolean result = false;
566
567                 try {
568                         result = reportCommon.getResourceActionGroupList().getResourceActionGroup().size() > 0;
569                 } catch (NullPointerException e) {
570                         // ignore exception, we're just testing to see if we have any list elements
571                 }
572
573                 return result;
574         }
575
576         /**
577          * Returns true if we found any required roles.
578          *
579          * @param reportCommon
580          * @return
581          */
582         private boolean hasRequiredRoles(ReportsCommon reportCommon) {
583                 boolean result = false;
584
585                 try {
586                         result = reportCommon.getForRoles().getRoleDisplayName().size() > 0;
587                 } catch (NullPointerException e) {
588                         // ignore exception, we're just testing to see if we have any list elements
589                 }
590
591                 return result;
592         }
593
594         /**
595          * The current user is authorized to run the report if:
596          *      1. No permissions or roles are specified in the report
597          *  2. No roles are specified, but permissions are specified and the current user has those permissions
598          *  3. Roles are specified and the current user is a member of at least one of the roles.
599          *
600          * @param reportsCommon
601          * @return
602          */
603         protected boolean isAuthoritzed(ReportsCommon reportsCommon) {
604                 boolean result = true;
605
606                 if (hasRequiredRoles(reportsCommon)) {
607                         result = isAuthorizedWithRoles(reportsCommon);
608                 } else if (hasRequiredPermissions(reportsCommon)) {
609                         result = isAuthoritzedWithPermissions(reportsCommon);
610                 }
611
612                 return result;
613         }
614
615         protected boolean isAuthorizedWithRoles(ReportsCommon reportCommon) {
616                 boolean result = false;
617
618                 ForRoles forRolesList = reportCommon.getForRoles();
619                 if (forRolesList != null) {
620                         AccountResource accountResource = new AccountResource();
621                         List<String> roleDisplayNameList = accountResource.getAccountRoleDisplayNames(AuthN.get().getUserId(), AuthN.get().getCurrentTenantId());
622                         for (String target : forRolesList.getRoleDisplayName()) {
623                                 if (Tools.listContainsIgnoreCase(roleDisplayNameList, target)) {
624                                         result = true;
625                                         break;
626                                 }
627                         }
628                 }
629
630                 return result;
631         }
632
633 }