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: * @created Jul 5, 2005
014: * @author William Seyler
015: **/package org.pentaho.plugin.print;
016:
017: import java.awt.print.PrinterException;
018: import java.awt.print.PrinterJob;
019: import java.io.FileNotFoundException;
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.io.OutputStream;
023: import java.util.ArrayList;
024:
025: import javax.print.PrintService;
026:
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029: import org.apache.fop.apps.Driver;
030: import org.apache.fop.render.awt.AWTRenderer;
031: import org.pentaho.actionsequence.dom.ActionOutput;
032: import org.pentaho.actionsequence.dom.ActionResource;
033: import org.pentaho.actionsequence.dom.IActionInputValueProvider;
034: import org.pentaho.actionsequence.dom.actions.PrinterAction;
035: import org.pentaho.core.repository.ISolutionRepository;
036: import org.pentaho.core.solution.IActionResource;
037: import org.pentaho.core.system.PentahoSystem;
038: import org.pentaho.messages.Messages;
039: import org.pentaho.plugin.ComponentBase;
040: import org.pentaho.plugin.core.StandardSettings;
041: import org.xml.sax.InputSource;
042:
043: /**
044: *
045: * Implements a PrintComponent class that will send a attached print file to a
046: * specified printer.
047: */
048: public class PrintComponent extends ComponentBase {
049: /**
050: *
051: */
052: private static final long serialVersionUID = 7377566797214172734L;
053:
054: private static final String DEFAULT_PRINTER = "PENTAHO_DEFAULT_PRINTER"; // This should never be a real printer //$NON-NLS-1$
055:
056: public Log getLogger() {
057: return LogFactory.getLog(PrintComponent.class);
058: }
059:
060: public boolean init() {
061: // TODO Auto-generated method stub
062: return true;
063: }
064:
065: protected boolean validateSystemSettings() {
066: // This component does not have any system settings to validate
067: return true;
068: }
069:
070: protected boolean validateAction() {
071: PrinterAction printerAction = null;
072: boolean actionValidated = true;
073:
074: if (getActionDefinition() instanceof PrinterAction) {
075: printerAction = (PrinterAction) getActionDefinition();
076:
077: if (printerAction.getPrintfile() == IActionInputValueProvider.NULL_INPUT
078: && printerAction.getResourcesPrintFile() == null
079: && printerAction.getReportOutput() == IActionInputValueProvider.NULL_INPUT
080: && printerAction.getOutputPrinterName() == null) {
081: actionValidated = false;
082: error(Messages
083: .getErrorString("PrintComponent.ERROR_0001_NO_PRINT_FILE_DEFINED") + getActionName()); //$NON-NLS-1$
084: }
085: } else {
086: actionValidated = false;
087: error(Messages
088: .getErrorString(
089: "ComponentBase.ERROR_0001_UNKNOWN_ACTION_TYPE", getActionDefinition().getElement().asXML())); //$NON-NLS-1$
090: }
091:
092: return actionValidated;
093: }
094:
095: protected boolean executeAction() {
096: String printFileName = null;
097: IActionResource printFileResource = null;
098: PrinterAction printAction = (PrinterAction) getActionDefinition();
099:
100: if (printAction.getPrintfile() != IActionInputValueProvider.NULL_INPUT) {
101: printFileName = printAction.getPrintfile().getStringValue();
102: } else if (printAction.getResourcesPrintFile() != null) {
103: ActionResource tempResource = printAction
104: .getResourcesPrintFile();
105: printFileResource = getResource(tempResource.getName());
106:
107: }
108:
109: InputStream inStream = null;
110: String printerName = printerName = printAction.getPrinterName()
111: .getStringValue(DEFAULT_PRINTER);
112: String lastPrinter = printAction.getDefaultPrinter()
113: .getStringValue();
114:
115: if (printAction.getOutputPrinterName() != null
116: && !printerName.equals("")) { //$NON-NLS-1$
117: ActionOutput output = printAction.getOutputPrinterName();
118: output.setValue(printerName);
119: if (printAction.getOutputDefaultPrinter() != null) {
120: ActionOutput defaultPrinterOutput = printAction
121: .getOutputDefaultPrinter();
122: defaultPrinterOutput.setValue(printerName);
123: }
124: return true;
125: }
126:
127: PrintService printer = getPrinterInternal(printerName,
128: lastPrinter);
129: if (printer == null) {
130: if (!feedbackAllowed()) {
131: error(Messages
132: .getErrorString("PrintComponent.ERROR_0002_NO_SUITABLE_PRINTER")); //$NON-NLS-1$
133: return false;
134: }
135: // we created the printer feedback entry already
136: return true;
137: }
138:
139: if (printAction.getOutputDefaultPrinter() != null) {
140: ActionOutput defaultPrinterOutput = printAction
141: .getOutputDefaultPrinter();
142: defaultPrinterOutput.setValue(printerName);
143: }
144:
145: // Get the number of copies
146: int copies = printAction.getCopies().getIntValue(1);
147:
148: // Check for a valid printFileName or printFile Resource
149: if (printFileName != null) {
150: ISolutionRepository repository = PentahoSystem
151: .getSolutionRepository(getSession());
152: try {
153: inStream = repository.getResourceInputStream(
154: printFileName, true);
155: } catch (FileNotFoundException e) {
156: return false;
157: }
158: } else if (printFileResource != null) {
159: try {
160: inStream = getResourceInputStream(printFileResource);
161: } catch (FileNotFoundException e) {
162: return false;
163: }
164: } else if (printAction.getReportOutput() != IActionInputValueProvider.NULL_INPUT) {
165: inStream = getInputStream(PrinterAction.REPORT_OUTPUT);
166: } else { // This should never happen if we validated ok.
167: return false;
168: }
169: try {
170: // Set the input source for sending to the driver.
171: InputSource source = new InputSource(inStream);
172: try {
173: Driver driver = new Driver(source, null);
174: PrinterJob pj = PrinterJob.getPrinterJob();
175: // Check to see if we're using the default printer or the user
176: // requested a different printer.
177: if (!(PrinterAction.DEFAULT_PRINTER.equals(printerName))) {
178: pj.setPrintService(getPrinterInternal(printerName,
179: lastPrinter));
180: }
181: PrintRenderer renderer = new PrintRenderer(pj, copies);
182: driver.setRenderer(renderer);
183: driver.run();
184: } catch (Exception ex) {
185: return false;
186: }
187: } finally {
188: try {
189: inStream.close();
190: } catch (IOException ex) {
191: // TODO: Provide message here...
192: ex.printStackTrace();
193: }
194: }
195: return true;
196: }
197:
198: public void done() {
199: // TODO Auto-generated method stub
200:
201: }
202:
203: /**
204: * Takes a printer name and find the associated PrintService. If no match
205: * can be made it randomly picks the first printer listed from the call to
206: * lookupPrintServices.
207: *
208: * @param printerName
209: * @return PrintService referenced by the printerName
210: */
211: public PrintService getPrinterInternal(String printerName,
212: String lastPrinterName) {
213: // The parameter value was not provided, and we are allowed to create
214: // user interface forms
215:
216: PrintService[] services = PrinterJob.lookupPrintServices();
217: // If the printerName is valid then we just return the servies
218: // associated with it.
219: for (int i = 0; i < services.length; i++) {
220: if (services[i].getName().equals(printerName)) {
221: return services[i];
222: }
223: }
224: if (feedbackAllowed()) {
225: // If it's not valid then lets find one and end this current run.
226: ArrayList values = new ArrayList();
227: for (int i = 0; i < services.length; i++) {
228: String value = services[i].getName();
229: values.add(value);
230: }
231: createFeedbackParameter(
232: StandardSettings.PRINTER_NAME,
233: Messages
234: .getString("PrintComponent.USER_PRINTER_NAME"), "", lastPrinterName, values, null, "select"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
235: promptNeeded();
236: return null;
237: }
238: return services[0];
239: }
240:
241: /**
242: * Takes a printer name and find the associated PrintService. If no match
243: * can be made it randomly picks the first printer listed from the call to
244: * lookupPrintServices.
245: *
246: * @param printerName
247: * @return PrintService referenced by the printerName
248: */
249: public static PrintService getPrinter(String printerName) {
250: // The parameter value was not provided, and we are allowed to create
251: // user interface forms
252:
253: PrintService[] services = PrinterJob.lookupPrintServices();
254: // If the printerName is valid then we just return the servies
255: // associated with it.
256: for (int i = 0; i < services.length; i++) {
257: if (services[i].getName().equals(printerName)) {
258: return services[i];
259: }
260: }
261: return services[0];
262: }
263:
264: public static PrintService getDefaultPrinter() {
265: // The parameter value was not provided, and we are allowed to create
266: // user interface forms
267:
268: PrintService[] services = PrinterJob.lookupPrintServices();
269: if (services == null || services.length == 0) {
270: return null;
271: }
272: return services[0];
273: }
274:
275: /**
276: *
277: * Extends AWTRenderer to create a class that will print to a specified
278: * printerJob
279: *
280: */
281: class PrintRenderer extends AWTRenderer {
282:
283: private static final int EVEN_AND_ALL = 0;
284:
285: private static final int EVEN = 1;
286:
287: private static final int ODD = 2;
288:
289: private int startNumber;
290:
291: private int endNumber;
292:
293: private int mode = EVEN_AND_ALL;
294:
295: private int copies = 1;
296:
297: private PrinterJob printerJob;
298:
299: PrintRenderer(PrinterJob printerJob, int copies) {
300: super (null);
301:
302: this .printerJob = printerJob;
303: this .copies = copies;
304: startNumber = 0;
305: endNumber = -1;
306:
307: printerJob.setPageable(this );
308: printerJob.setCopies(this .copies);
309: mode = EVEN_AND_ALL;
310: String str = null;
311: if (str != null) {
312: try {
313: mode = Boolean.valueOf(str).booleanValue() ? EVEN
314: : ODD;
315: } catch (Exception e) {
316: }
317:
318: }
319:
320: }
321:
322: public void stopRenderer(OutputStream outputStream)
323: throws IOException {
324: super .stopRenderer(outputStream);
325:
326: if (endNumber == -1)
327: endNumber = getPageCount();
328:
329: ArrayList numbers = getInvalidPageNumbers();
330: for (int i = numbers.size() - 1; i > -1; i--)
331: removePage(Integer.parseInt((String) numbers.get(i)));
332:
333: try {
334: printerJob.print();
335: } catch (PrinterException e) {
336: e.printStackTrace();
337: throw new IOException(
338: Messages
339: .getString(
340: "PrintComponent.ERROR_0003_UNABLE_TO_PRINT", e.getClass().getName(), e.getMessage())); //$NON-NLS-1$
341: }
342: }
343:
344: // public void renderPage(Page page) {
345: // pageWidth = (int) (page.getWidth() / 1000f);
346: // pageHeight = (int) (page.getHeight() / 1000f);
347: // super.renderPage(page);
348: // }
349:
350: private ArrayList getInvalidPageNumbers() {
351: ArrayList vec = new ArrayList();
352: int max = getPageCount();
353: boolean isValid;
354: for (int i = 0; i < max; i++) {
355: isValid = true;
356: if (i < startNumber || i > endNumber) {
357: isValid = false;
358: } else if (mode != EVEN_AND_ALL) {
359: if (mode == EVEN && ((i + 1) % 2 != 0))
360: isValid = false;
361: else if (mode == ODD && ((i + 1) % 2 != 1))
362: isValid = false;
363: }
364: if (!isValid)
365: vec.add(i + ""); //$NON-NLS-1$
366: }
367: return vec;
368: }
369: } // class PrintRenderer
370: }
|