001: /*
002: * Copyright 2006 Pentaho Corporation. All rights reserved.
003: * This software was developed by Pentaho Corporation and is provided under the terms
004: * of the Mozilla Public License, Version 1.1, or any later version. You may not use
005: * this file except in compliance with the license. If you need a copy of the license,
006: * please go to http://www.mozilla.org/MPL/MPL-1.1.txt. The Original Code is the Pentaho
007: * BI Platform. The Initial Developer is Pentaho Corporation.
008: *
009: * Software distributed under the Mozilla Public License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
011: * the license for the specific language governing your rights and limitations.
012: */
013: package org.pentaho.plugin.jfreereport.components;
014:
015: import java.io.ByteArrayInputStream;
016: import java.io.FileNotFoundException;
017: import java.io.IOException;
018: import java.io.InputStream;
019: import java.io.UnsupportedEncodingException;
020: import java.net.URL;
021: import java.util.HashMap;
022: import java.util.Iterator;
023:
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogFactory;
026: import org.jfree.report.JFreeReport;
027: import org.jfree.report.modules.parser.base.ReportGenerator;
028: import org.jfree.resourceloader.FactoryParameterKey;
029: import org.jfree.resourceloader.ResourceException;
030: import org.jfree.resourceloader.ResourceKey;
031: import org.jfree.resourceloader.ResourceManager;
032: import org.pentaho.core.repository.ISolutionRepository;
033: import org.pentaho.core.runtime.IActionParameter;
034: import org.pentaho.core.solution.IActionResource;
035: import org.pentaho.core.system.PentahoSystem;
036: import org.pentaho.messages.Messages;
037: import org.pentaho.plugin.jfreereport.AbstractJFreeReportComponent;
038: import org.pentaho.plugin.jfreereport.helper.PentahoResourceData;
039: import org.pentaho.plugin.jfreereport.helper.PentahoResourceLoader;
040: import org.pentaho.plugin.jfreereport.helper.ReportUtils;
041: import org.xml.sax.InputSource;
042:
043: /**
044: * A JFreeReport run contains at least three steps. Step 1: Parse the report definition. Step 2: Grab some data. Step 3: Spit out some content. Alternativly,
045: * show the print-preview. <p/> This class loads or parses the report definition.
046: *
047: * @author Thomas Morgner
048: */
049: public class JFreeReportLoadComponent extends
050: AbstractJFreeReportComponent {
051: private static final long serialVersionUID = -2240691437049710246L;
052:
053: public JFreeReportLoadComponent() {
054: }
055:
056: protected boolean validateAction() {
057: if (isDefinedResource(REPORTGENERATEDEFN_REPORTDEFN)) {
058: return true;
059: }
060:
061: if (isDefinedInput(REPORTGENERATEDEFN_REPORTDEFN)) {
062: IActionParameter o = getInputParameter(REPORTGENERATEDEFN_REPORTDEFN);
063: if ((o != null) && (o.getValue() instanceof String)) {
064: return true;
065: }
066: return false;
067: }
068:
069: // Handle late-bind of report resource name
070: if (isDefinedInput(REPORTLOAD_RESOURCENAME)) {
071: if (isDefinedResource(getInputStringValue(REPORTLOAD_RESOURCENAME))) {
072: return true;
073: } else {
074: error(Messages
075: .getErrorString("JFreeReport.ERROR_0004_REPORT_DEFINITION_UNREADABLE")); //$NON-NLS-1$
076: return false;
077: }
078: }
079:
080: if (isDefinedResource(DATACOMPONENT_JARINPUT)) {
081: if (!isDefinedInput(REPORTLOAD_REPORTLOC)) {
082: error(Messages
083: .getErrorString("JFreeReport.ERROR_0011_REPORT_LOCATION_MISSING")); //$NON-NLS-1$
084: return false;
085: }
086:
087: final IActionResource resource = getResource(DATACOMPONENT_JARINPUT);
088: final ISolutionRepository solutionRepository = PentahoSystem
089: .getSolutionRepository(getSession());
090: final InputStream in;
091: try {
092: in = solutionRepository.getResourceInputStream(
093: resource, true);
094: } catch (FileNotFoundException e1) {
095: error(Messages
096: .getErrorString(
097: "JFreeReport.ERROR_0010_REPORT_JAR_MISSING", resource.getAddress())); //$NON-NLS-1$
098: return false;
099: }
100:
101: try {
102: // not being able to read a single char is definitly a big boo ..
103: if (in.read() == -1) {
104: error(Messages
105: .getErrorString("JFreeReport.ERROR_0009_REPORT_JAR_UNREADABLE")); //$NON-NLS-1$
106: return false;
107: }
108: } catch (Exception e) {
109: error(Messages
110: .getErrorString("JFreeReport.ERROR_0009_REPORT_JAR_UNREADABLE")); //$NON-NLS-1$
111: return false;
112: }
113:
114: if (!isDefinedInput(REPORTLOAD_REPORTLOC)) {
115: error(Messages
116: .getErrorString("JFreeReport.ERROR_0012_CLASS_LOCATION_MISSING")); //$NON-NLS-1$
117: return false;
118: }
119: return true;
120: }
121: return false;
122: }
123:
124: protected boolean validateSystemSettings() {
125: return true;
126: }
127:
128: public void done() {
129:
130: }
131:
132: private JFreeReport getReportFromResource()
133: throws ResourceException, IOException {
134: JFreeReport report = null;
135: if (isDefinedResource(REPORTGENERATEDEFN_REPORTDEFN)) {
136: final IActionResource resource = getResource(REPORTGENERATEDEFN_REPORTDEFN);
137:
138: if (resource.getSourceType() == IActionResource.XML) {
139: String repDef = resource.getAddress();
140: ReportGenerator generator = ReportGenerator
141: .getInstance();
142:
143: // add the runtime context so that PentahoResourceData class can get access to the solution repo
144: generator
145: .setObject(
146: PentahoResourceData.PENTAHO_RUNTIME_CONTEXT_KEY,
147: getRuntimeContext());
148:
149: report = generator.parseReport(new InputSource(
150: new ByteArrayInputStream(repDef.getBytes())),
151: getDefinedResourceURL(null));
152: }
153: report = parseReport(resource);
154: } else if (isDefinedInput(REPORTLOAD_RESOURCENAME)) {
155: final String resName = getInputStringValue(REPORTLOAD_RESOURCENAME);
156: if (isDefinedResource(resName)) {
157: final IActionResource resource = getResource(resName);
158: report = parseReport(resource);
159: }
160: }
161: return report;
162: }
163:
164: private JFreeReport getReportFromInputParam()
165: throws ResourceException, UnsupportedEncodingException,
166: IOException {
167: JFreeReport report = null;
168:
169: if (isDefinedInput(REPORTGENERATEDEFN_REPORTDEFN)) {
170: IActionParameter o = getInputParameter(REPORTGENERATEDEFN_REPORTDEFN);
171: if (o != null) {
172: String repDef = o.getStringValue();
173: ReportGenerator generator = ReportGenerator
174: .getInstance();
175:
176: // add the runtime context so that PentahoResourceData class can get access to the solution repo
177: generator
178: .setObject(
179: PentahoResourceData.PENTAHO_RUNTIME_CONTEXT_KEY,
180: getRuntimeContext());
181:
182: // get base URL
183: String baseURL = PentahoSystem.getApplicationContext()
184: .getBaseUrl();
185: URL url = null;
186: try {
187: url = new URL(baseURL);
188: } catch (Exception e) {
189: // a null URL is ok
190: warn(Messages
191: .getString("JFreeReportLoadComponent.WARN_COULD_NOT_CREATE_URL")); //$NON-NLS-1$
192: }
193: report = generator
194: .parseReport(
195: new InputSource(
196: new ByteArrayInputStream(repDef
197: .getBytes("UTF-8"))), getDefinedResourceURL(url)); //$NON-NLS-1$
198: }
199: }
200:
201: return report;
202: }
203:
204: private JFreeReport getReportFromJar() throws Exception {
205: JFreeReport report;
206: final IActionResource resource = getResource(DATACOMPONENT_JARINPUT);
207: final ClassLoader loader = ReportUtils.createJarLoader(
208: getSession(), resource);
209: if (loader == null) {
210: throw new Exception(
211: Messages
212: .getString("JFreeReportLoadComponent.ERROR_0035_COULD_NOT_CREATE_CLASSLOADER")); //$NON-NLS-1$
213: }
214:
215: String reportLocation = getInputStringValue(REPORTLOAD_REPORTLOC);
216: URL resourceUrl = loader.getResource(reportLocation);
217: if (resourceUrl == null) {
218: throw new Exception(Messages.getErrorString(
219: "JFreeReport.ERROR_0016_REPORT_RESOURCE_INVALID", //$NON-NLS-1$
220: reportLocation, resource.getAddress()));
221: }
222:
223: try {
224: ReportGenerator generator = ReportGenerator.getInstance();
225:
226: // add the runtime context so that PentahoResourceData class can get access to the solution repo
227: generator.setObject(
228: PentahoResourceData.PENTAHO_RUNTIME_CONTEXT_KEY,
229: getRuntimeContext());
230:
231: report = generator.parseReport(resourceUrl,
232: getDefinedResourceURL(resourceUrl));
233: } catch (Exception ex) {
234: throw new Exception(
235: Messages
236: .getErrorString(
237: "JFreeReport.ERROR_0007_COULD_NOT_PARSE", reportLocation), ex); //$NON-NLS-1$
238: }
239: return report;
240: }
241:
242: public JFreeReport getReport() throws Exception {
243: JFreeReport report = getReportFromResource();
244: if (report == null) {
245: report = getReportFromInputParam();
246: if (report == null) {
247: report = getReportFromJar();
248: }
249: }
250: return report;
251: }
252:
253: protected boolean executeAction() throws Throwable {
254: boolean result = false;
255: try {
256: JFreeReport report = getReport();
257: if (report != null) {
258: addTempParameterObject(
259: DATACOMPONENT_REPORTTEMP_OBJINPUT, report);
260: result = true;
261: }
262: } catch (Exception ex) {
263: error(ex.getMessage());
264: }
265: return result;
266: }
267:
268: private URL getDefinedResourceURL(URL defaultValue) {
269: if (isDefinedInput(REPORTLOAD_RESURL) == false) {
270: return defaultValue;
271: }
272:
273: try {
274: final String inputStringValue = getInputStringValue(Messages
275: .getString(REPORTLOAD_RESURL));
276: return new URL(inputStringValue);
277: } catch (Exception e) {
278: return defaultValue;
279: }
280: }
281:
282: private String getBaseServerURL(String pentahoBaseURL) {
283: try {
284: URL url = new URL(pentahoBaseURL);
285: return url.getProtocol()
286: + "://" + url.getHost() + ":" + url.getPort(); //$NON-NLS-1$ //$NON-NLS-2$
287: } catch (Exception e) {
288: }
289: return pentahoBaseURL;
290: }
291:
292: private String getHostColonPort(String pentahoBaseURL) {
293: try {
294: URL url = new URL(pentahoBaseURL);
295: return url.getHost() + ":" + url.getPort();//$NON-NLS-1$
296: } catch (Exception e) {
297: }
298: return pentahoBaseURL;
299: }
300:
301: /**
302: * Parses the report, using the given ActionResource as initial report definition.
303: *
304: * @param resource
305: * @return
306: */
307: private JFreeReport parseReport(IActionResource resource) {
308: try {
309: // define the resource url so that PentahoResourceLoader recognizes the path.
310: String resourceUrl = PentahoResourceLoader.SOLUTION_SCHEMA_NAME
311: + PentahoResourceLoader.SCHEMA_SEPARATOR
312: + resource.getAddress();
313:
314: String pentahoBaseURL = PentahoSystem
315: .getApplicationContext().getBaseUrl();
316:
317: HashMap helperObjects = new HashMap();
318:
319: helperObjects
320: .put(
321: new FactoryParameterKey("pentahoBaseURL"), PentahoSystem.getApplicationContext().getBaseUrl()); //$NON-NLS-1$
322:
323: // trim out the server and port
324: helperObjects
325: .put(
326: new FactoryParameterKey("serverBaseURL"), getBaseServerURL(pentahoBaseURL)); //$NON-NLS-1$
327:
328: helperObjects
329: .put(
330: new FactoryParameterKey("solutionRoot"), PentahoSystem.getApplicationContext().getSolutionPath("")); //$NON-NLS-1$ //$NON-NLS-2$
331:
332: // get the host:port portion only
333: helperObjects
334: .put(
335: new FactoryParameterKey("hostColonPort"), getHostColonPort(pentahoBaseURL)); //$NON-NLS-1$
336:
337: // add the runtime context so that PentahoResourceData class can get access to the solution repo
338: helperObjects.put(new FactoryParameterKey(
339: PentahoResourceData.PENTAHO_RUNTIME_CONTEXT_KEY),
340: getRuntimeContext());
341:
342: Iterator it = getInputNames().iterator();
343: while (it.hasNext()) {
344: try {
345: String inputName = (String) it.next();
346: String inputValue = getInputStringValue(inputName);
347: helperObjects.put(
348: new FactoryParameterKey(inputName),
349: inputValue);
350: } catch (Exception e) {
351: }
352: }
353:
354: ResourceManager resourceManager = new ResourceManager();
355: resourceManager.registerDefaults();
356:
357: ResourceKey contextKey = resourceManager.createKey(
358: resourceUrl, helperObjects);
359: ResourceKey key = resourceManager.createKey(resourceUrl,
360: helperObjects);
361:
362: return ReportGenerator.getInstance().parseReport(
363: resourceManager, key, contextKey);
364:
365: } catch (Exception ex) {
366: error(
367: Messages
368: .getErrorString(
369: "JFreeReport.ERROR_0007_COULD_NOT_PARSE", resource.getAddress()), ex); //$NON-NLS-1$
370: return null;
371: }
372: }
373:
374: public boolean init() {
375: return true;
376: }
377:
378: public Log getLogger() {
379: return LogFactory.getLog(JFreeReportLoadComponent.class);
380: }
381: }
|