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