KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > jasperreports > engine > export > JRHtmlExporter


1 /*
2  * ============================================================================
3  * GNU Lesser General Public License
4  * ============================================================================
5  *
6  * JasperReports - Free Java report-generating library.
7  * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22  *
23  * JasperSoft Corporation
24  * 303 Second Street, Suite 450 North
25  * San Francisco, CA 94107
26  * http://www.jaspersoft.com
27  */

28
29 /*
30  * Contributors:
31  * Alex Parfenov - aparfeno@users.sourceforge.net
32  * Adrian Jackson - iapetus@users.sourceforge.net
33  * David Taylor - exodussystems@users.sourceforge.net
34  * Lars Kristensen - llk@users.sourceforge.net
35  */

36
37 package net.sf.jasperreports.engine.export;
38
39 import java.awt.Color JavaDoc;
40 import java.awt.Dimension JavaDoc;
41 import java.awt.Rectangle JavaDoc;
42 import java.awt.font.TextAttribute JavaDoc;
43 import java.awt.geom.Dimension2D JavaDoc;
44 import java.io.File JavaDoc;
45 import java.io.FileOutputStream JavaDoc;
46 import java.io.IOException JavaDoc;
47 import java.io.OutputStream JavaDoc;
48 import java.io.OutputStreamWriter JavaDoc;
49 import java.io.StringWriter JavaDoc;
50 import java.io.Writer JavaDoc;
51 import java.text.AttributedCharacterIterator JavaDoc;
52 import java.util.ArrayList JavaDoc;
53 import java.util.HashMap JavaDoc;
54 import java.util.Iterator JavaDoc;
55 import java.util.LinkedList JavaDoc;
56 import java.util.List JavaDoc;
57 import java.util.Map JavaDoc;
58
59 import net.sf.jasperreports.engine.JRAbstractExporter;
60 import net.sf.jasperreports.engine.JRAlignment;
61 import net.sf.jasperreports.engine.JRBox;
62 import net.sf.jasperreports.engine.JRElement;
63 import net.sf.jasperreports.engine.JRException;
64 import net.sf.jasperreports.engine.JRExporterParameter;
65 import net.sf.jasperreports.engine.JRGraphicElement;
66 import net.sf.jasperreports.engine.JRHyperlink;
67 import net.sf.jasperreports.engine.JRImage;
68 import net.sf.jasperreports.engine.JRImageMapRenderer;
69 import net.sf.jasperreports.engine.JRImageRenderer;
70 import net.sf.jasperreports.engine.JRPrintElement;
71 import net.sf.jasperreports.engine.JRPrintElementIndex;
72 import net.sf.jasperreports.engine.JRPrintEllipse;
73 import net.sf.jasperreports.engine.JRPrintFrame;
74 import net.sf.jasperreports.engine.JRPrintHyperlink;
75 import net.sf.jasperreports.engine.JRPrintImage;
76 import net.sf.jasperreports.engine.JRPrintImageArea;
77 import net.sf.jasperreports.engine.JRPrintImageAreaHyperlink;
78 import net.sf.jasperreports.engine.JRPrintLine;
79 import net.sf.jasperreports.engine.JRPrintPage;
80 import net.sf.jasperreports.engine.JRPrintRectangle;
81 import net.sf.jasperreports.engine.JRPrintText;
82 import net.sf.jasperreports.engine.JRRenderable;
83 import net.sf.jasperreports.engine.JRRuntimeException;
84 import net.sf.jasperreports.engine.JRTextElement;
85 import net.sf.jasperreports.engine.JRWrappingSvgRenderer;
86 import net.sf.jasperreports.engine.JasperPrint;
87 import net.sf.jasperreports.engine.util.JRStringUtil;
88 import net.sf.jasperreports.engine.util.JRStyledText;
89 import net.sf.jasperreports.engine.util.Pair;
90
91
92 /**
93  * Exports a JasperReports document to HTML format. It has character output type and exports the document to a
94  * grid-based layout.
95  * <p>
96  * Since classic AWT fonts can be sometimes very different from HTML fonts, a font mapping feature was added.
97  * By using the {@link JRExporterParameter#FONT_MAP} parameter, a logical font like "sansserif" can be mapped to a
98  * list of HTML specific fonts, like "Arial, Verdana, Tahoma". Both map keys and values are strings.
99  * @author Teodor Danciu (teodord@users.sourceforge.net)
100  * @version $Id: JRHtmlExporter.java 1508 2006-11-28 19:09:17 +0200 (Tue, 28 Nov 2006) teodord $
101  */

102 public class JRHtmlExporter extends JRAbstractExporter
103 {
104
105     /**
106      *
107      */

108     protected static final String JavaDoc JR_PAGE_ANCHOR_PREFIX = "JR_PAGE_ANCHOR_";
109
110     /**
111      *
112      */

113     protected static final String JavaDoc CSS_TEXT_ALIGN_LEFT = "left";
114     protected static final String JavaDoc CSS_TEXT_ALIGN_RIGHT = "right";
115     protected static final String JavaDoc CSS_TEXT_ALIGN_CENTER = "center";
116     protected static final String JavaDoc CSS_TEXT_ALIGN_JUSTIFY = "justify";
117
118     /**
119      *
120      */

121     protected static final String JavaDoc HTML_VERTICAL_ALIGN_TOP = "top";
122     protected static final String JavaDoc HTML_VERTICAL_ALIGN_MIDDLE = "middle";
123     protected static final String JavaDoc HTML_VERTICAL_ALIGN_BOTTOM = "bottom";
124     
125     public static final String JavaDoc IMAGE_NAME_PREFIX = "img_";
126     protected static final int IMAGE_NAME_PREFIX_LEGTH = IMAGE_NAME_PREFIX.length();
127
128     /**
129      *
130      */

131     protected Writer JavaDoc writer = null;
132     protected JRExportProgressMonitor progressMonitor = null;
133     protected Map JavaDoc rendererToImagePathMap = null;
134     protected Map JavaDoc imageMaps;
135     protected Map JavaDoc imageNameToImageDataMap = null;
136     protected List JavaDoc imagesToProcess = null;
137     protected boolean isPxImageLoaded = false;
138
139     protected int reportIndex = 0;
140     protected int pageIndex = 0;
141
142     /**
143      *
144      */

145     protected File JavaDoc imagesDir = null;
146     protected String JavaDoc imagesURI = null;
147     protected boolean isOutputImagesToDir = false;
148     protected boolean isRemoveEmptySpace = false;
149     protected boolean isWhitePageBackground = true;
150     protected String JavaDoc encoding = null;
151     protected String JavaDoc sizeUnit = null;
152
153     /**
154      *
155      */

156     protected String JavaDoc htmlHeader = null;
157     protected String JavaDoc betweenPagesHtml = null;
158     protected String JavaDoc htmlFooter = null;
159
160     protected StringProvider emptyCellStringProvider = null;
161
162
163     /**
164      *
165      */

166     protected static final int colorMask = Integer.parseInt("FFFFFF", 16);
167
168     protected boolean isWrapBreakWord = false;
169
170     protected Map JavaDoc fontMap = null;
171
172     private LinkedList JavaDoc backcolorStack;
173     private Color JavaDoc backcolor;
174
175     protected JRHyperlinkProducerFactory hyperlinkProducerFactory;
176
177
178     public JRHtmlExporter()
179     {
180         backcolorStack = new LinkedList JavaDoc();
181         backcolor = null;
182     }
183
184
185     /**
186      *
187      */

188     public void exportReport() throws JRException
189     {
190         progressMonitor = (JRExportProgressMonitor)parameters.get(JRExporterParameter.PROGRESS_MONITOR);
191
192         /* */
193         setOffset();
194
195         try
196         {
197             /* */
198             setExportContext();
199     
200             /* */
201             setInput();
202     
203             /* */
204             if (!isModeBatch)
205             {
206                 setPageRange();
207             }
208     
209             htmlHeader = (String JavaDoc)parameters.get(JRHtmlExporterParameter.HTML_HEADER);
210             betweenPagesHtml = (String JavaDoc)parameters.get(JRHtmlExporterParameter.BETWEEN_PAGES_HTML);
211             htmlFooter = (String JavaDoc)parameters.get(JRHtmlExporterParameter.HTML_FOOTER);
212     
213             imagesDir = (File JavaDoc)parameters.get(JRHtmlExporterParameter.IMAGES_DIR);
214             if (imagesDir == null)
215             {
216                 String JavaDoc dir = (String JavaDoc)parameters.get(JRHtmlExporterParameter.IMAGES_DIR_NAME);
217                 if (dir != null)
218                 {
219                     imagesDir = new File JavaDoc(dir);
220                 }
221             }
222     
223             Boolean JavaDoc isRemoveEmptySpaceParameter = (Boolean JavaDoc)parameters.get(JRHtmlExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS);
224             if (isRemoveEmptySpaceParameter != null)
225             {
226                 isRemoveEmptySpace = isRemoveEmptySpaceParameter.booleanValue();
227             }
228     
229             Boolean JavaDoc isWhitePageBackgroundParameter = (Boolean JavaDoc)parameters.get(JRHtmlExporterParameter.IS_WHITE_PAGE_BACKGROUND);
230             if (isWhitePageBackgroundParameter != null)
231             {
232                 isWhitePageBackground = isWhitePageBackgroundParameter.booleanValue();
233             }
234     
235             Boolean JavaDoc isOutputImagesToDirParameter = (Boolean JavaDoc)parameters.get(JRHtmlExporterParameter.IS_OUTPUT_IMAGES_TO_DIR);
236             if (isOutputImagesToDirParameter != null)
237             {
238                 isOutputImagesToDir = isOutputImagesToDirParameter.booleanValue();
239             }
240     
241             String JavaDoc uri = (String JavaDoc)parameters.get(JRHtmlExporterParameter.IMAGES_URI);
242             if (uri != null)
243             {
244                 imagesURI = uri;
245             }
246     
247             encoding = (String JavaDoc)parameters.get(JRExporterParameter.CHARACTER_ENCODING);
248             if (encoding == null)
249             {
250                 encoding = "UTF-8";
251             }
252     
253             rendererToImagePathMap = new HashMap JavaDoc();
254             imageMaps = new HashMap JavaDoc();
255             imagesToProcess = new ArrayList JavaDoc();
256             isPxImageLoaded = false;
257     
258             //backward compatibility with the IMAGE_MAP parameter
259
imageNameToImageDataMap = (Map JavaDoc)parameters.get(JRHtmlExporterParameter.IMAGES_MAP);
260     // if (imageNameToImageDataMap == null)
261
// {
262
// imageNameToImageDataMap = new HashMap();
263
// }
264
//END - backward compatibility with the IMAGE_MAP parameter
265

266             Boolean JavaDoc isWrapBreakWordParameter = (Boolean JavaDoc)parameters.get(JRHtmlExporterParameter.IS_WRAP_BREAK_WORD);
267             if (isWrapBreakWordParameter != null)
268             {
269                 isWrapBreakWord = isWrapBreakWordParameter.booleanValue();
270             }
271     
272             sizeUnit = (String JavaDoc)parameters.get(JRHtmlExporterParameter.SIZE_UNIT);
273             if (sizeUnit == null)
274             {
275                 sizeUnit = JRHtmlExporterParameter.SIZE_UNIT_PIXEL;
276             }
277     
278             Boolean JavaDoc isUsingImagesToAlignParameter = (Boolean JavaDoc)parameters.get(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN);
279             if (isUsingImagesToAlignParameter == null)
280             {
281                 isUsingImagesToAlignParameter = Boolean.TRUE;
282             }
283     
284             if (isUsingImagesToAlignParameter.booleanValue())
285             {
286                 emptyCellStringProvider =
287                     new StringProvider()
288                     {
289                         public String JavaDoc getStringForCollapsedTD(Object JavaDoc value, int width, int height, String JavaDoc sizeUnit)
290                         {
291                             return "><img alt=\"\" SRC=\"" + value + "px\" style=\"width: " + width + sizeUnit + "; height: " + height + sizeUnit + ";\"/>";
292                         }
293                         public String JavaDoc getStringForEmptyTD(Object JavaDoc value)
294                         {
295                             return "<img alt=\"\" SRC=\"" + value + "px\" border=\"0\"/>";
296                         }
297                     };
298     
299                 loadPxImage();
300             }
301             else
302             {
303                 emptyCellStringProvider =
304                     new StringProvider()
305                     {
306                         public String JavaDoc getStringForCollapsedTD(Object JavaDoc value, int width, int height, String JavaDoc sizeUnit)
307                         {
308                             return " style=\"width: " + width + sizeUnit + "; height: " + height + sizeUnit + ";\">";
309                         }
310                         public String JavaDoc getStringForEmptyTD(Object JavaDoc value)
311                         {
312                             return "";
313                         }
314                     };
315             }
316     
317     
318             fontMap = (Map JavaDoc) parameters.get(JRExporterParameter.FONT_MAP);
319                         
320             setHyperlinkProducerFactory();
321     
322             StringBuffer JavaDoc sb = (StringBuffer JavaDoc)parameters.get(JRExporterParameter.OUTPUT_STRING_BUFFER);
323             if (sb != null)
324             {
325                 try
326                 {
327                     writer = new StringWriter JavaDoc();
328                     exportReportToWriter();
329                     sb.append(writer.toString());
330                 }
331                 catch (IOException JavaDoc e)
332                 {
333                     throw new JRException("Error writing to StringBuffer writer : " + jasperPrint.getName(), e);
334                 }
335                 finally
336                 {
337                     if (writer != null)
338                     {
339                         try
340                         {
341                             writer.close();
342                         }
343                         catch(IOException JavaDoc e)
344                         {
345                         }
346                     }
347                 }
348             }
349             else
350             {
351                 writer = (Writer JavaDoc)parameters.get(JRExporterParameter.OUTPUT_WRITER);
352                 if (writer != null)
353                 {
354                     try
355                     {
356                         exportReportToWriter();
357                     }
358                     catch (IOException JavaDoc e)
359                     {
360                         throw new JRException("Error writing to writer : " + jasperPrint.getName(), e);
361                     }
362                 }
363                 else
364                 {
365                     OutputStream JavaDoc os = (OutputStream JavaDoc)parameters.get(JRExporterParameter.OUTPUT_STREAM);
366                     if (os != null)
367                     {
368                         try
369                         {
370                             writer = new OutputStreamWriter JavaDoc(os, encoding);
371                             exportReportToWriter();
372                         }
373                         catch (IOException JavaDoc e)
374                         {
375                             throw new JRException("Error writing to OutputStream writer : " + jasperPrint.getName(), e);
376                         }
377                     }
378                     else
379                     {
380                         File JavaDoc destFile = (File JavaDoc)parameters.get(JRExporterParameter.OUTPUT_FILE);
381                         if (destFile == null)
382                         {
383                             String JavaDoc fileName = (String JavaDoc)parameters.get(JRExporterParameter.OUTPUT_FILE_NAME);
384                             if (fileName != null)
385                             {
386                                 destFile = new File JavaDoc(fileName);
387                             }
388                             else
389                             {
390                                 throw new JRException("No output specified for the exporter.");
391                             }
392                         }
393     
394                         try
395                         {
396                             os = new FileOutputStream JavaDoc(destFile);
397                             writer = new OutputStreamWriter JavaDoc(os, encoding);
398                         }
399                         catch (IOException JavaDoc e)
400                         {
401                             throw new JRException("Error creating to file writer : " + jasperPrint.getName(), e);
402                         }
403     
404                         if (imagesDir == null)
405                         {
406                             imagesDir = new File JavaDoc(destFile.getParent(), destFile.getName() + "_files");
407                         }
408     
409                         if (isOutputImagesToDirParameter == null)
410                         {
411                             isOutputImagesToDir = true;
412                         }
413     
414                         if (imagesURI == null)
415                         {
416                             imagesURI = imagesDir.getName() + "/";
417                         }
418     
419                         try
420                         {
421                             exportReportToWriter();
422                         }
423                         catch (IOException JavaDoc e)
424                         {
425                             throw new JRException("Error writing to file writer : " + jasperPrint.getName(), e);
426                         }
427                         finally
428                         {
429                             if (writer != null)
430                             {
431                                 try
432                                 {
433                                     writer.close();
434                                 }
435                                 catch(IOException JavaDoc e)
436                                 {
437                                 }
438                             }
439                         }
440                     }
441                 }
442             }
443     
444             if (isOutputImagesToDir)
445             {
446                 if (imagesDir == null)
447                 {
448                     throw new JRException("The images directory was not specified for the exporter.");
449                 }
450     
451                 if (isPxImageLoaded || (imagesToProcess != null && imagesToProcess.size() > 0))
452                 {
453                     if (!imagesDir.exists())
454                     {
455                         imagesDir.mkdir();
456                     }
457     
458                     if (isPxImageLoaded)
459                     {
460                         JRRenderable pxRenderer =
461                             JRImageRenderer.getInstance(
462                                 "net/sf/jasperreports/engine/images/pixel.GIF",
463                                 JRImage.ON_ERROR_TYPE_ERROR
464                                 );
465                         byte[] imageData = pxRenderer.getImageData();
466     
467                         File JavaDoc imageFile = new File JavaDoc(imagesDir, "px");
468                         FileOutputStream JavaDoc fos = null;
469     
470                         try
471                         {
472                             fos = new FileOutputStream JavaDoc(imageFile);
473                             fos.write(imageData, 0, imageData.length);
474                         }
475                         catch (IOException JavaDoc e)
476                         {
477                             throw new JRException("Error writing to image file : " + imageFile, e);
478                         }
479                         finally
480                         {
481                             if (fos != null)
482                             {
483                                 try
484                                 {
485                                     fos.close();
486                                 }
487                                 catch(IOException JavaDoc e)
488                                 {
489                                 }
490                             }
491                         }
492                     }
493     
494                     for(Iterator JavaDoc it = imagesToProcess.iterator(); it.hasNext();)
495                     {
496                         JRPrintElementIndex imageIndex = (JRPrintElementIndex)it.next();
497     
498                         JRPrintImage image = getImage(jasperPrintList, imageIndex);
499                         JRRenderable renderer = image.getRenderer();
500                         if (renderer.getType() == JRRenderable.TYPE_SVG)
501                         {
502                             renderer =
503                                 new JRWrappingSvgRenderer(
504                                     renderer,
505                                     new Dimension JavaDoc(image.getWidth(), image.getHeight()),
506                                     JRElement.MODE_OPAQUE == image.getMode() ? image.getBackcolor() : null
507                                     );
508                         }
509     
510                         byte[] imageData = renderer.getImageData();
511     
512                         File JavaDoc imageFile = new File JavaDoc(imagesDir, getImageName(imageIndex));
513                         FileOutputStream JavaDoc fos = null;
514     
515                         try
516                         {
517                             fos = new FileOutputStream JavaDoc(imageFile);
518                             fos.write(imageData, 0, imageData.length);
519                         }
520                         catch (IOException JavaDoc e)
521                         {
522                             throw new JRException("Error writing to image file : " + imageFile, e);
523                         }
524                         finally
525                         {
526                             if (fos != null)
527                             {
528                                 try
529                                 {
530                                     fos.close();
531                                 }
532                                 catch(IOException JavaDoc e)
533                                 {
534                                 }
535                             }
536                         }
537                     }
538                 }
539             }
540         }
541         finally
542         {
543             resetExportContext();
544         }
545     }
546
547
548     protected void setHyperlinkProducerFactory()
549     {
550         hyperlinkProducerFactory = (JRHyperlinkProducerFactory) parameters.get(JRHtmlExporterParameter.HYPERLINK_PRODUCER_FACTORY);
551     }
552
553
554     public static JRPrintImage getImage(List JavaDoc jasperPrintList, String JavaDoc imageName)
555     {
556         return getImage(jasperPrintList, getPrintElementIndex(imageName));
557     }
558
559
560     public static JRPrintImage getImage(List JavaDoc jasperPrintList, JRPrintElementIndex imageIndex)
561     {
562         JasperPrint report = (JasperPrint)jasperPrintList.get(imageIndex.getReportIndex());
563         JRPrintPage page = (JRPrintPage)report.getPages().get(imageIndex.getPageIndex());
564
565         Integer JavaDoc[] elementIndexes = imageIndex.getElementIndexes();
566         Object JavaDoc element = page.getElements().get(elementIndexes[0].intValue());
567
568         for (int i = 1; i < elementIndexes.length; ++i)
569         {
570             JRPrintFrame frame = (JRPrintFrame) element;
571             element = frame.getElements().get(elementIndexes[i].intValue());
572         }
573
574         return (JRPrintImage) element;
575     }
576
577
578     /**
579      *
580      */

581     protected void exportReportToWriter() throws JRException, IOException JavaDoc
582     {
583         if (htmlHeader == null)
584         {
585             // no doctype because of bug 1430880
586
// writer.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n");
587
// writer.write("<html xmlns=\"http://www.w3.org/1999/xhtml\">\n");
588
writer.write("<html>\n");
589             writer.write("<head>\n");
590             writer.write(" <title></title>\n");
591             writer.write(" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=" + encoding + "\"/>\n");
592             writer.write(" <style type=\"text/css\">\n");
593             writer.write(" a {text-decoration: none}\n");
594             writer.write(" </style>\n");
595             writer.write("</head>\n");
596             writer.write("<body text=\"#000000\" link=\"#000000\" alink=\"#000000\" vlink=\"#000000\">\n");
597             writer.write("<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n");
598             writer.write("<tr><td width=\"50%\">&nbsp;</td><td align=\"center\">\n");
599             writer.write("\n");
600         }
601         else
602         {
603             writer.write(htmlHeader);
604         }
605
606         for(reportIndex = 0; reportIndex < jasperPrintList.size(); reportIndex++)
607         {
608             jasperPrint = (JasperPrint)jasperPrintList.get(reportIndex);
609
610             List JavaDoc pages = jasperPrint.getPages();
611             if (pages != null && pages.size() > 0)
612             {
613                 if (isModeBatch)
614                 {
615                     startPageIndex = 0;
616                     endPageIndex = pages.size() - 1;
617                 }
618
619                 JRPrintPage page = null;
620                 for(pageIndex = startPageIndex; pageIndex <= endPageIndex; pageIndex++)
621                 {
622                     if (Thread.currentThread().isInterrupted())
623                     {
624                         throw new JRException("Current thread interrupted.");
625                     }
626
627                     page = (JRPrintPage)pages.get(pageIndex);
628
629                     writer.write("<a name=\"" + JR_PAGE_ANCHOR_PREFIX + reportIndex + "_" + (pageIndex + 1) + "\"/>\n");
630
631                     /* */
632                     exportPage(page);
633