]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
41d71ea3cdd9536a5e6bd93e88287d7cdc38e8f1
[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.sql.Connection;
30 import java.sql.SQLException;
31 import java.util.HashMap;
32 import java.util.List;
33
34 import javax.naming.NamingException;
35 import javax.ws.rs.WebApplicationException;
36 import javax.ws.rs.core.Response;
37
38 import net.sf.jasperreports.engine.JRException;
39 import net.sf.jasperreports.engine.JasperExportManager;
40 import net.sf.jasperreports.engine.JasperFillManager;
41 import net.sf.jasperreports.engine.JasperPrint;
42
43 import org.collectionspace.services.ReportJAXBSchema;
44 import org.collectionspace.services.report.ReportsCommon;
45 import org.collectionspace.services.client.PoxPayloadIn;
46 import org.collectionspace.services.client.PoxPayloadOut;
47 import org.collectionspace.services.common.ServiceMain;
48 import org.collectionspace.services.common.config.ConfigReader;
49 import org.collectionspace.services.common.context.ServiceContext;
50 import org.collectionspace.services.common.document.BadRequestException;
51 import org.collectionspace.services.common.document.DocumentException;
52 import org.collectionspace.services.common.document.DocumentWrapper;
53 import org.collectionspace.services.common.invocable.Invocable;
54 import org.collectionspace.services.common.invocable.InvocationContext;
55 import org.collectionspace.services.common.storage.JDBCTools;
56 import org.collectionspace.services.jaxb.InvocableJAXBSchema;
57 import org.collectionspace.services.nuxeo.client.java.DocHandlerBase;
58 import org.collectionspace.services.nuxeo.client.java.RepositoryJavaClientImpl;
59 import org.jfree.util.Log;
60 import org.nuxeo.ecm.core.api.DocumentModel;
61 import org.nuxeo.ecm.core.api.model.PropertyException;
62 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
65
66 /**
67  * ReportDocumentModelHandler
68  *
69  * $LastChangedRevision: $
70  * $LastChangedDate: $
71  */
72 public class ReportDocumentModelHandler extends DocHandlerBase<ReportsCommon> {
73     private final Logger logger = LoggerFactory.getLogger(ReportDocumentModelHandler.class);
74     private static String REPORTS_FOLDER = "reports";
75     private static String CSID_LIST_SEPARATOR = ",";
76     
77     private static String REPORTS_STD_CSID_PARAM = "csid";
78     private static String REPORTS_STD_GROUPCSID_PARAM = "groupcsid";
79     private static String REPORTS_STD_CSIDLIST_PARAM = "csidlist";
80     private static String REPORTS_STD_TENANTID_PARAM = "tenantid";
81         
82         public Response invokeReport(
83                         ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
84                         String csid,
85                         InvocationContext invContext) throws Exception {
86                 RepositoryInstance repoSession = null;
87                 boolean releaseRepoSession = false;
88
89                 String invocationMode = invContext.getMode();
90                 String modeProperty = null;
91                 HashMap<String, Object> params = new HashMap<String, Object>();
92                 params.put(REPORTS_STD_TENANTID_PARAM, ctx.getTenantId());
93                 boolean checkDocType = true;
94                 if(Invocable.INVOCATION_MODE_SINGLE.equalsIgnoreCase(invocationMode)) {
95                         modeProperty = InvocableJAXBSchema.SUPPORTS_SINGLE_DOC;
96                 params.put(REPORTS_STD_CSID_PARAM, invContext.getSingleCSID());
97                 } else if(Invocable.INVOCATION_MODE_LIST.equalsIgnoreCase(invocationMode)) {
98                         modeProperty = InvocableJAXBSchema.SUPPORTS_DOC_LIST;
99                         List<String> csids = null;
100                         InvocationContext.ListCSIDs listThing = invContext.getListCSIDs();
101                                 if(listThing!=null) {
102                                         csids = listThing.getCsid();
103                                 }
104                                 if(csids==null||csids.isEmpty()){
105                                 throw new BadRequestException(
106                                                 "ReportResource: Report invoked in list mode, with no csids in list." );
107                                 }
108                                 StringBuilder sb = new StringBuilder();
109                                 boolean first = true;
110                                 for(String csidItem : csids) {
111                                         if(first)
112                                                 first = false;
113                                         else
114                                                 sb.append(CSID_LIST_SEPARATOR);
115                                         sb.append(csidItem);
116                                 }
117                 params.put(REPORTS_STD_CSIDLIST_PARAM, sb.toString());
118                 } else if(Invocable.INVOCATION_MODE_GROUP.equalsIgnoreCase(invocationMode)) {
119                         modeProperty = InvocableJAXBSchema.SUPPORTS_GROUP;
120                 params.put(REPORTS_STD_GROUPCSID_PARAM, invContext.getGroupCSID());
121                 } else if(Invocable.INVOCATION_MODE_NO_CONTEXT.equalsIgnoreCase(invocationMode)) {
122                         modeProperty = InvocableJAXBSchema.SUPPORTS_NO_CONTEXT;
123                         checkDocType = false;
124                 } else {
125                         throw new BadRequestException("ReportResource: unknown Invocation Mode: "
126                                 +invocationMode);
127                 }
128                 
129                 RepositoryJavaClientImpl repoClient = (RepositoryJavaClientImpl)this.getRepositoryClient(ctx);
130                 repoSession = this.getRepositorySession();
131                 if (repoSession == null) {
132                         repoSession = repoClient.getRepositorySession(ctx);
133                         releaseRepoSession = true;
134                 }
135
136                 String reportFileName = null;
137                 // Get properties from the batch docModel, and release the session
138                 try {
139                         DocumentWrapper<DocumentModel> wrapper = repoClient.getDoc(repoSession, ctx, csid);
140                         DocumentModel docModel = wrapper.getWrappedObject();
141                         Boolean supports = (Boolean)docModel.getPropertyValue(modeProperty);
142                         if(supports == null || !supports) {
143                                 throw new BadRequestException(
144                                                 "ReportResource: This Report does not support Invocation Mode: "
145                                         +invocationMode);
146                         }
147                 if(checkDocType) {
148                         List<String> forDocTypeList = 
149                                 (List<String>)docModel.getPropertyValue(InvocableJAXBSchema.FOR_DOC_TYPES);
150                         if(forDocTypeList==null
151                                         || !forDocTypeList.contains(invContext.getDocType())) {
152                                 throw new BadRequestException(
153                                                 "ReportResource: Invoked with unsupported document type: "
154                                                 +invContext.getDocType());
155                         }
156                 }
157                         reportFileName = (String)docModel.getPropertyValue(ReportJAXBSchema.FILENAME);
158                 } catch (PropertyException pe) {
159                         if (logger.isDebugEnabled()) {
160                                 logger.debug("Property exception getting batch values: ", pe);
161                         }
162                         throw pe;
163                 } catch (DocumentException de) {
164                         if (logger.isDebugEnabled()) {
165                                 logger.debug("Problem getting batch doc: ", de);
166                         }
167                         throw de;
168                 } catch (Exception e) {
169                         if (logger.isDebugEnabled()) {
170                                 logger.debug("Caught exception ", e);
171                         }
172                         throw new DocumentException(e);
173                 } finally {
174                         if (releaseRepoSession && repoSession != null) {
175                                 repoClient.releaseRepositorySession(ctx, repoSession);
176                         }
177                 }
178         return buildReportResponse(csid, params, reportFileName);
179         }
180
181
182     private Response buildReportResponse(String reportCSID, HashMap<String, Object> params, String reportFileName)
183                                 throws Exception {
184                 Connection conn = null;
185                 Response response = null;
186         try {
187                         String fullPath = ServiceMain.getInstance().getServerRootDir() +
188                                                                 File.separator + ConfigReader.CSPACE_DIR_NAME + 
189                                                                 File.separator + REPORTS_FOLDER +
190                                                                 // File.separator + tenantName +
191                                                                 File.separator + reportFileName;
192                         conn = getConnection();
193         
194             if (logger.isTraceEnabled()) {
195                 logger.trace("ReportResource for Report csid=" + reportCSID
196                                 +" opening report file: "+fullPath);
197             }
198                         FileInputStream fileStream = new FileInputStream(fullPath);
199         
200                 // fill the report
201                         JasperPrint jasperprint = JasperFillManager.fillReport(fileStream, params,conn);
202                         // export report to pdf and build a response with the bytes
203                         byte[] pdfasbytes = JasperExportManager.exportReportToPdf(jasperprint);
204                         
205                         // Need to set response type for what is requested...
206                 response = Response.ok(pdfasbytes, "application/pdf").build();
207         
208                 return response;        
209         } catch (SQLException sqle) {
210             // SQLExceptions can be chained. We have at least one exception, so
211             // set up a loop to make sure we let the user know about all of them
212             // if there happens to be more than one.
213             if (logger.isDebugEnabled()) {
214                     SQLException tempException = sqle;
215                     while (null != tempException) {
216                                 logger.debug("SQL Exception: " + sqle.getLocalizedMessage());
217         
218                         // loop to the next exception
219                         tempException = tempException.getNextException();
220                     }
221             }
222             response = Response.status(
223                     Response.Status.INTERNAL_SERVER_ERROR).entity(
224                                 "Invoke failed (SQL problem) on Report csid=" + reportCSID).type("text/plain").build();
225             throw new WebApplicationException(response);
226         } catch (JRException jre) {
227             if (logger.isDebugEnabled()) {
228                 logger.debug("JR Exception: " + jre.getLocalizedMessage() + " Cause: "+jre.getCause());
229             }
230             response = Response.status(
231                     Response.Status.INTERNAL_SERVER_ERROR).entity(
232                                 "Invoke failed (Jasper problem) on Report csid=" + reportCSID).type("text/plain").build();
233             throw new WebApplicationException(response);
234         } catch (FileNotFoundException fnfe) {
235             if (logger.isDebugEnabled()) {
236                 logger.debug("FileNotFoundException: " + fnfe.getLocalizedMessage());
237             }
238             response = Response.status(
239                     Response.Status.INTERNAL_SERVER_ERROR).entity(
240                                 "Invoke failed (SQL problem) on Report csid=" + reportCSID).type("text/plain").build();
241             throw new WebApplicationException(response);
242                 } finally {
243                 if(conn!=null) {
244                         try {
245                         conn.close();
246                 } catch (SQLException sqle) {
247                     // SQLExceptions can be chained. We have at least one exception, so
248                     // set up a loop to make sure we let the user know about all of them
249                     // if there happens to be more than one.
250                     if (logger.isDebugEnabled()) {
251                                 logger.debug("SQL Exception closing connection: " 
252                                                 + sqle.getLocalizedMessage());
253                     }
254                 } catch (Exception e) {
255                     if (logger.isDebugEnabled()) {
256                         logger.debug("Exception closing connection", e);
257                     }
258                 }
259                 }
260         }
261     }
262
263     private Connection getConnection() throws NamingException, SQLException {
264         Connection result = null;
265         
266         ServiceContext ctx = this.getServiceContext();
267         try {
268                 String repositoryName = ctx.getRepositoryName();
269                 if (repositoryName != null && repositoryName.trim().isEmpty() == false) {
270                         result = JDBCTools.getConnection(JDBCTools.NUXEO_DATASOURCE_NAME, repositoryName);
271                 }
272                 } catch (Exception e) {
273                         Log.error(e);
274                         throw new NamingException();
275                 }
276         
277         return result;
278     }
279
280 }
281