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