001: package org.emforge.report;
002:
003: import java.io.ByteArrayInputStream;
004: import java.io.File;
005: import java.io.FileNotFoundException;
006: import java.io.InputStream;
007: import java.util.ArrayList;
008: import java.util.Collection;
009: import java.util.Date;
010:
011: import javax.jws.WebService;
012:
013: import net.sf.jasperreports.engine.JRException;
014: import net.sf.jasperreports.engine.JasperReport;
015: import net.sf.jasperreports.engine.util.JRLoader;
016:
017: import org.acegisecurity.AccessDeniedException;
018: import org.apache.commons.collections.CollectionUtils;
019: import org.apache.commons.io.FilenameUtils;
020: import org.apache.commons.io.IOUtils;
021: import org.apache.commons.lang.StringUtils;
022: import org.apache.commons.logging.Log;
023: import org.apache.commons.logging.LogFactory;
024: import org.emforge.BpmService;
025: import org.emforge.EmForgeException;
026: import org.emforge.ReportService;
027: import org.emforge.report.dao.Report;
028: import org.emforge.report.dao.ReportDaoHibernateImpl;
029: import org.emforge.report.dao.ReportTransformer;
030: import org.emforge.xfer.ReportTO;
031: import org.jbpm.util.ClassLoaderUtil;
032: import org.springframework.beans.factory.InitializingBean;
033: import org.springframework.core.io.Resource;
034: import org.springframework.transaction.annotation.Propagation;
035: import org.springframework.transaction.annotation.Transactional;
036:
037: import ru.emdev.EmForge.security.UserFactory;
038: import ru.emdev.EmForge.security.web.SiteRole;
039:
040: import com.ecyrd.jspwiki.WikiContext;
041: import com.ecyrd.jspwiki.WikiEngine;
042: import com.ecyrd.jspwiki.WikiException;
043: import com.ecyrd.jspwiki.WikiPage;
044: import com.ecyrd.jspwiki.attachment.Attachment;
045: import com.ecyrd.jspwiki.attachment.AttachmentManager;
046:
047: /**
048: * Implementation of Report Service implementation
049: *
050: * @author szakusov, 11.03.2008:
051: */
052: @WebService(endpointInterface="org.emforge.ReportService")
053: @Transactional(propagation=Propagation.REQUIRES_NEW,rollbackFor=EmForgeException.class)
054: public class ReportServiceImpl implements ReportService,
055: InitializingBean {
056:
057: public static final String EXT_COMPILED = "jasper";
058:
059: protected final Log m_logger = LogFactory.getLog(getClass());
060:
061: protected ReportDaoHibernateImpl m_reportDao;
062: protected BpmService m_bpmService;
063: protected WikiEngine m_wikiEngine;
064: protected UserFactory m_userFactory;
065: protected Resource m_reportsFolder;
066:
067: private boolean m_skipPermissionCheck;
068:
069: /**
070: * @param i_reportDao
071: */
072: public void setReportDao(ReportDaoHibernateImpl i_reportDao) {
073:
074: m_reportDao = i_reportDao;
075: }
076:
077: /**
078: * @param service
079: */
080: public void setBpmService(BpmService service) {
081:
082: m_bpmService = service;
083: }
084:
085: /**
086: * @param engine
087: */
088: public void setWikiEngine(WikiEngine engine) {
089:
090: m_wikiEngine = engine;
091: }
092:
093: /**
094: * @param i_userFactory
095: */
096: public void setUserFactory(UserFactory i_userFactory) {
097:
098: m_userFactory = i_userFactory;
099: }
100:
101: /**
102: * @param i_reportsFolder
103: */
104: public void setReportsFolder(Resource i_reportsFolder) {
105:
106: m_reportsFolder = i_reportsFolder;
107: }
108:
109: /**
110: * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
111: */
112: public void afterPropertiesSet() throws Exception {
113:
114: if (m_reportDao == null) {
115: throw new IllegalArgumentException(
116: "reportDao should be specified for "
117: + this .getClass());
118: }
119: if (m_bpmService == null) {
120: throw new IllegalArgumentException(
121: "bpmService should be specified for "
122: + this .getClass());
123: }
124: if (m_wikiEngine == null) {
125: throw new IllegalArgumentException(
126: "wikiEngine should be specified for "
127: + this .getClass());
128: }
129: if (m_userFactory == null) {
130: throw new IllegalArgumentException(
131: "userFactory should be specified for "
132: + this .getClass());
133: }
134:
135: // Check if reports included into distribution then try to install them
136: if (m_reportsFolder != null) {
137:
138: File directory = null;
139:
140: try {
141: directory = m_reportsFolder.getFile();
142: } catch (FileNotFoundException ex) {
143: // just ignore it (we do not have directory with default reports)
144: }
145:
146: if (directory != null) {
147: m_skipPermissionCheck = true;
148: for (String filename : directory.list()) {
149: if (FilenameUtils.isExtension(filename,
150: EXT_COMPILED)) {
151: m_logger.debug("Deploying '" + filename
152: + "' report...");
153: try {
154: InputStream stream = ClassLoaderUtil
155: .getStream("reports/" + filename);
156: byte[] content = new byte[stream
157: .available()];
158: stream.read(content);
159: if (!exists(getReportName(content))) {
160: add(content,
161: "Installed from distribution");
162: m_logger.debug("Successful.");
163: } else {
164: m_logger.debug("Skipped.");
165: }
166: } catch (Exception ex) {
167: m_logger.error("Could not deploy '"
168: + filename + "' report: ", ex);
169: }
170: }
171: }
172: m_skipPermissionCheck = false;
173: }
174: }
175: }
176:
177: /**
178: * @see org.emforge.ReportService#add(byte[], java.lang.String)
179: */
180: public ReportTO add(byte[] i_content, String i_description)
181: throws EmForgeException {
182:
183: // Check permissions
184: if (!canOperate()) {
185: throw new AccessDeniedException(PERM_CANNOT_ADD);
186: }
187:
188: assert i_content != null : "Report content is not initialized!";
189: assert i_description != null : "Description is not initialized!";
190:
191: // Load content
192: InputStream content = new ByteArrayInputStream(i_content);
193: JasperReport compilation = null;
194: try {
195: // compilation = JasperCompileManager.compileReport(JRXmlLoader.load(content)); // when uploaded design file
196: compilation = (JasperReport) JRLoader.loadObject(content);
197: } catch (JRException ex) {
198: // throw new EmForgeException("Report compilation error", ex); // when uploaded design file
199: throw new EmForgeException("Could not load report content",
200: ex);
201: }
202:
203: // Get the wiki-page
204: String name = compilation.getName();
205: WikiPage page = m_wikiEngine.getPage(name);
206: if (page == null) {
207: page = new WikiPage(m_wikiEngine, name);
208: }
209:
210: // Save description
211: WikiContext wikiContext = new WikiContext(m_wikiEngine, page);
212: String user = getUserName();
213: wikiContext.getPage().setAuthor(user);
214: wikiContext.getPage().setLastModified(new Date());
215: try {
216: m_wikiEngine.saveText(wikiContext, i_description);
217: } catch (WikiException ex) {
218: throw new EmForgeException(
219: "Could not save report description", ex);
220: }
221:
222: // Get attachment information
223: String pageName = page.getName();
224: // String filename = pageName + ".jrxml"; // when uploaded design file
225: String filename = getFilename(pageName);
226: try {
227: AttachmentManager mngr = m_wikiEngine
228: .getAttachmentManager();
229: Attachment attch = mngr.getAttachmentInfo(pageName);
230: attch = new Attachment(m_wikiEngine, pageName, filename);
231: attch.setAuthor(user);
232: mngr.storeAttachment(attch, new ByteArrayInputStream(
233: i_content));
234:
235: } catch (Exception ex) {
236: throw new EmForgeException("Could not attach report", ex);
237: }
238:
239: // Save report information to data store
240: ReportTO result = new ReportTO(-1, pageName, page.getVersion(),
241: name, i_description, filename);
242: m_reportDao.save(result);
243: m_reportDao.getHibernateTemplate().flush();
244:
245: return result;
246: }
247:
248: /**
249: * @see org.emforge.ReportService#getFilename(java.lang.String)
250: */
251: public String getFilename(String i_name) {
252:
253: String[] parts = { i_name, ".", EXT_COMPILED };
254: return StringUtils.join(parts);
255: }
256:
257: /**
258: * @see org.emforge.ReportService#getReport(java.lang.String, int)
259: */
260: public ReportTO get(String i_name) throws EmForgeException {
261:
262: // Check permissions
263: if (!canReview()) {
264: throw new AccessDeniedException(PERM_CANNOT_REVIEW);
265: }
266:
267: // Get required report
268: Report report = m_reportDao.getByName(i_name);
269:
270: // Convert DO to TO
271: return new ReportTransformer().transform(report);
272: }
273:
274: /**
275: * @see org.emforge.ReportService#getAll()
276: */
277: public ReportTO[] getAll() throws EmForgeException {
278:
279: // Check permissions
280: if (!canReview()) {
281: throw new AccessDeniedException(PERM_CANNOT_REVIEW);
282: }
283:
284: // Get all reports
285: Collection<Report> reports = m_reportDao.getAll();
286:
287: // Convert DO to TO
288: ReportTransformer transformer = new ReportTransformer();
289: Collection<ReportTO> outputCollection = new ArrayList<ReportTO>();
290: CollectionUtils.collect(reports, transformer, outputCollection);
291:
292: // Return result
293: return outputCollection.toArray(new ReportTO[outputCollection
294: .size()]);
295: }
296:
297: /**
298: * @see org.emforge.ReportService#getContent(java.lang.String)
299: */
300: @SuppressWarnings("unchecked")
301: public byte[] getContent(String i_name) throws EmForgeException {
302:
303: // Check permissions
304: if (!canReview()) {
305: throw new AccessDeniedException(PERM_CANNOT_REVIEW);
306: }
307:
308: byte[] result = null;
309: Collection<Attachment> attachments = new ArrayList<Attachment>();
310:
311: // Get content
312: try {
313: WikiPage page = m_wikiEngine.getPage(i_name);
314: if (page != null) {
315: AttachmentManager mngr = m_wikiEngine
316: .getAttachmentManager();
317: attachments = mngr.listAttachments(page);
318: String filename = getFilename(i_name);
319: for (Attachment att : attachments) {
320: if (StringUtils.equals(att.getFileName(), filename)) {
321: InputStream stream = mngr
322: .getAttachmentStream(att);
323: result = IOUtils.toByteArray(stream);
324: break;
325: }
326: }
327: }
328: } catch (Exception ex) {
329: throw new EmForgeException(
330: "Could not retrieve report content", ex);
331: }
332: return result;
333: }
334:
335: /**
336: * @see org.emforge.ReportService#exists(java.lang.String)
337: */
338: public boolean exists(String i_name) {
339:
340: boolean result = false;
341: try {
342: if (get(i_name) != null) {
343: result = true;
344: }
345: } catch (EmForgeException e) {
346: // just skip it
347: }
348: return result;
349: }
350:
351: private String getUserName() {
352:
353: String result;
354: if (m_skipPermissionCheck) {
355: result = "admin";
356: } else {
357: result = m_userFactory.getCurrentUser().getUsername();
358: }
359: return result;
360: }
361:
362: /**
363: * @param i_content
364: * @return
365: * @throws JRException
366: */
367: private String getReportName(byte[] i_content) throws JRException {
368:
369: InputStream stream = new ByteArrayInputStream(i_content);
370: JasperReport report = (JasperReport) JRLoader
371: .loadObject(stream);
372:
373: return report.getName();
374: }
375:
376: /**
377: * @see org.emforge.ReportService#delete(java.lang.String)
378: */
379: public boolean delete(String i_name) throws EmForgeException {
380:
381: if (!canOperate()) {
382: throw new AccessDeniedException(PERM_CANNOT_DELETE);
383: }
384:
385: try {
386: m_wikiEngine.deletePage(i_name);
387: m_reportDao.delete(i_name);
388:
389: } catch (Exception ex) {
390: throw new EmForgeException("Could not delete report", ex);
391: }
392:
393: return true;
394: }
395:
396: /**
397: * @see org.emforge.ReportService#canOperate()
398: */
399: public boolean canOperate() {
400:
401: return m_skipPermissionCheck
402: || m_userFactory.getCurrentUser().hasRole(
403: SiteRole.ADMIN.getId());
404: }
405:
406: /**
407: * @see org.emforge.ReportService#canReview()
408: */
409: public boolean canReview() {
410:
411: return m_skipPermissionCheck
412: || !m_userFactory.getCurrentUser().isAnonymous();
413: }
414: }
|