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