Source Code Cross Referenced for HtmlPrinter.java in  » Report » pentaho-report » org » jfree » report » modules » output » table » html » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Report » pentaho report » org.jfree.report.modules.output.table.html 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         * ===========================================
0003:         * JFreeReport : a free Java reporting library
0004:         * ===========================================
0005:         *
0006:         * Project Info:  http://reporting.pentaho.org/
0007:         *
0008:         * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
0009:         *
0010:         * This library is free software; you can redistribute it and/or modify it under the terms
0011:         * of the GNU Lesser General Public License as published by the Free Software Foundation;
0012:         * either version 2.1 of the License, or (at your option) any later version.
0013:         *
0014:         * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
0015:         * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
0016:         * See the GNU Lesser General Public License for more details.
0017:         *
0018:         * You should have received a copy of the GNU Lesser General Public License along with this
0019:         * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
0020:         * Boston, MA 02111-1307, USA.
0021:         *
0022:         * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
0023:         * in the United States and other countries.]
0024:         *
0025:         * ------------
0026:         * HtmlPrinter.java
0027:         * ------------
0028:         * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
0029:         */package org.jfree.report.modules.output.table.html;
0030:
0031:        import java.awt.Color;
0032:        import java.awt.Image;
0033:        import java.io.BufferedInputStream;
0034:        import java.io.BufferedOutputStream;
0035:        import java.io.BufferedWriter;
0036:        import java.io.ByteArrayInputStream;
0037:        import java.io.IOException;
0038:        import java.io.InputStream;
0039:        import java.io.OutputStream;
0040:        import java.io.OutputStreamWriter;
0041:        import java.io.Writer;
0042:        import java.net.URL;
0043:        import java.text.NumberFormat;
0044:        import java.util.HashMap;
0045:        import java.util.HashSet;
0046:
0047:        import org.jfree.fonts.encoding.EncodingRegistry;
0048:        import org.jfree.io.IOUtils;
0049:        import org.jfree.report.ElementAlignment;
0050:        import org.jfree.report.ImageContainer;
0051:        import org.jfree.report.InvalidReportStateException;
0052:        import org.jfree.report.JFreeReportInfo;
0053:        import org.jfree.report.LocalImageContainer;
0054:        import org.jfree.report.URLImageContainer;
0055:        import org.jfree.report.layout.model.Border;
0056:        import org.jfree.report.layout.model.BorderEdge;
0057:        import org.jfree.report.layout.model.LogicalPageBox;
0058:        import org.jfree.report.layout.model.RenderBox;
0059:        import org.jfree.report.layout.model.context.BoxDefinition;
0060:        import org.jfree.report.layout.output.ContentProcessingException;
0061:        import org.jfree.report.layout.output.LogicalPageKey;
0062:        import org.jfree.report.layout.output.OutputProcessorMetaData;
0063:        import org.jfree.report.layout.output.RenderUtility;
0064:        import org.jfree.report.modules.output.table.base.SheetLayout;
0065:        import org.jfree.report.modules.output.table.base.TableCellDefinition;
0066:        import org.jfree.report.modules.output.table.base.TableContentProducer;
0067:        import org.jfree.report.modules.output.table.base.TableRectangle;
0068:        import org.jfree.report.modules.output.table.html.helper.GlobalStyleManager;
0069:        import org.jfree.report.modules.output.table.html.helper.InlineStyleManager;
0070:        import org.jfree.report.modules.output.table.html.helper.StyleBuilder;
0071:        import org.jfree.report.modules.output.table.html.helper.StyleManager;
0072:        import org.jfree.report.modules.output.table.html.util.HtmlColors;
0073:        import org.jfree.report.resourceloader.ImageFactory;
0074:        import org.jfree.report.style.ElementStyleKeys;
0075:        import org.jfree.report.style.StyleSheet;
0076:        import org.jfree.report.style.TextStyleKeys;
0077:        import org.jfree.report.style.WhitespaceCollapse;
0078:        import org.jfree.report.util.MemoryByteArrayOutputStream;
0079:        import org.jfree.report.util.MemoryStringWriter;
0080:        import org.jfree.report.util.geom.StrictGeomUtility;
0081:        import org.jfree.repository.ContentCreationException;
0082:        import org.jfree.repository.ContentIOException;
0083:        import org.jfree.repository.ContentItem;
0084:        import org.jfree.repository.ContentLocation;
0085:        import org.jfree.repository.LibRepositoryBoot;
0086:        import org.jfree.repository.NameGenerator;
0087:        import org.jfree.resourceloader.ResourceData;
0088:        import org.jfree.resourceloader.ResourceKey;
0089:        import org.jfree.resourceloader.ResourceLoadingException;
0090:        import org.jfree.resourceloader.ResourceManager;
0091:        import org.jfree.util.Configuration;
0092:        import org.jfree.util.Log;
0093:        import org.jfree.util.ObjectUtilities;
0094:        import org.jfree.util.StackableRuntimeException;
0095:        import org.jfree.util.StringUtils;
0096:        import org.jfree.xmlns.common.AttributeList;
0097:        import org.jfree.xmlns.writer.DefaultTagDescription;
0098:        import org.jfree.xmlns.writer.XmlWriter;
0099:        import org.jfree.xmlns.writer.XmlWriterSupport;
0100:
0101:        /**
0102:         * This class is the actual HTML-emitter.
0103:         *
0104:         * @author Thomas Morgner
0105:         */
0106:        public abstract class HtmlPrinter implements  HtmlContentGenerator {
0107:
0108:            private static class ImageData {
0109:                private byte[] imageData;
0110:                private String mimeType;
0111:                private String originalFileName;
0112:
0113:                private ImageData(final byte[] imageData,
0114:                        final String mimeType, final String originalFileName) {
0115:                    if (imageData == null) {
0116:                        throw new NullPointerException();
0117:                    }
0118:                    if (mimeType == null) {
0119:                        throw new NullPointerException();
0120:                    }
0121:                    if (originalFileName == null) {
0122:                        throw new NullPointerException();
0123:                    }
0124:
0125:                    this .imageData = imageData;
0126:                    this .mimeType = mimeType;
0127:                    this .originalFileName = originalFileName;
0128:                }
0129:
0130:                public byte[] getImageData() {
0131:                    return imageData;
0132:                }
0133:
0134:                public String getMimeType() {
0135:                    return mimeType;
0136:                }
0137:
0138:                public String getOriginalFileName() {
0139:                    return originalFileName;
0140:                }
0141:            }
0142:
0143:            private static final String GENERATOR = JFreeReportInfo
0144:                    .getInstance().getName()
0145:                    + " version " + JFreeReportInfo.getInstance().getVersion();
0146:
0147:            public static final String XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
0148:
0149:            private static final String[] XHTML_HEADER = { "<!DOCTYPE html",
0150:                    "     PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"",
0151:                    "     \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" };
0152:
0153:            private Configuration configuration;
0154:            //private OutputProcessorMetaData metaData;
0155:
0156:            private XmlWriter xmlWriter;
0157:            private boolean assumeZeroMargins;
0158:            private boolean assumeZeroBorders;
0159:            private boolean assumeZeroPaddings;
0160:
0161:            private ContentLocation contentLocation;
0162:            private NameGenerator contentNameGenerator;
0163:            private ContentLocation dataLocation;
0164:            private NameGenerator dataNameGenerator;
0165:
0166:            private ResourceManager resourceManager;
0167:            private HashMap knownImages;
0168:            private HashMap knownResources;
0169:            private HashSet validRawTypes;
0170:
0171:            private URLRewriter urlRewriter;
0172:            private ContentItem documentContentItem;
0173:            private StyleManager styleManager;
0174:            private boolean allowRawLinkTargets;
0175:            private boolean copyExternalImages;
0176:            private StyleBuilder styleBuilder;
0177:            private static final String[] EMPTY_CELL_ATTRNAMES = new String[] { "font-size" };
0178:            private static final String[] EMPTY_CELL_ATTRVALS = new String[] { "1pt" };
0179:
0180:            private MemoryStringWriter bufferWriter;
0181:            private BufferedWriter writer;
0182:            private ContentItem styleFile;
0183:            private String styleFileUrl;
0184:
0185:            protected HtmlPrinter(final ResourceManager resourceManager) {
0186:                if (resourceManager == null) {
0187:                    throw new NullPointerException(
0188:                            "A resource-manager must be given.");
0189:                }
0190:
0191:                this .resourceManager = resourceManager;
0192:                this .knownResources = new HashMap();
0193:                this .knownImages = new HashMap();
0194:                this .styleBuilder = new StyleBuilder();
0195:
0196:                this .validRawTypes = new HashSet();
0197:                this .validRawTypes.add("image/gif");
0198:                this .validRawTypes.add("image/x-xbitmap");
0199:                this .validRawTypes.add("image/gi_");
0200:                this .validRawTypes.add("image/jpeg");
0201:                this .validRawTypes.add("image/jpg");
0202:                this .validRawTypes.add("image/jp_");
0203:                this .validRawTypes.add("application/jpg");
0204:                this .validRawTypes.add("application/x-jpg");
0205:                this .validRawTypes.add("image/pjpeg");
0206:                this .validRawTypes.add("image/pipeg");
0207:                this .validRawTypes.add("image/vnd.swiftview-jpeg");
0208:                this .validRawTypes.add("image/x-xbitmap");
0209:                this .validRawTypes.add("image/png");
0210:                this .validRawTypes.add("application/png");
0211:                this .validRawTypes.add("application/x-png");
0212:
0213:                assumeZeroMargins = true;
0214:                assumeZeroBorders = true;
0215:                assumeZeroPaddings = true;
0216:
0217:                // this primitive implementation assumes that the both repositories are
0218:                // the same ..
0219:                urlRewriter = new FileSystemURLRewriter();
0220:            }
0221:
0222:            protected boolean isAllowRawLinkTargets() {
0223:                return allowRawLinkTargets;
0224:            }
0225:
0226:            protected Configuration getConfiguration() {
0227:                return configuration;
0228:            }
0229:
0230:            protected boolean isAssumeZeroMargins() {
0231:                return assumeZeroMargins;
0232:            }
0233:
0234:            protected void setAssumeZeroMargins(final boolean assumeZeroMargins) {
0235:                this .assumeZeroMargins = assumeZeroMargins;
0236:            }
0237:
0238:            protected boolean isAssumeZeroBorders() {
0239:                return assumeZeroBorders;
0240:            }
0241:
0242:            protected void setAssumeZeroBorders(final boolean assumeZeroBorders) {
0243:                this .assumeZeroBorders = assumeZeroBorders;
0244:            }
0245:
0246:            protected boolean isAssumeZeroPaddings() {
0247:                return assumeZeroPaddings;
0248:            }
0249:
0250:            protected void setAssumeZeroPaddings(
0251:                    final boolean assumeZeroPaddings) {
0252:                this .assumeZeroPaddings = assumeZeroPaddings;
0253:            }
0254:
0255:            public ContentLocation getContentLocation() {
0256:                return contentLocation;
0257:            }
0258:
0259:            public NameGenerator getContentNameGenerator() {
0260:                return contentNameGenerator;
0261:            }
0262:
0263:            public ContentLocation getDataLocation() {
0264:                return dataLocation;
0265:            }
0266:
0267:            public NameGenerator getDataNameGenerator() {
0268:                return dataNameGenerator;
0269:            }
0270:
0271:            public void setDataWriter(final ContentLocation dataLocation,
0272:                    final NameGenerator dataNameGenerator) {
0273:                this .dataNameGenerator = dataNameGenerator;
0274:                this .dataLocation = dataLocation;
0275:            }
0276:
0277:            public void setContentWriter(final ContentLocation contentLocation,
0278:                    final NameGenerator contentNameGenerator) {
0279:                this .contentNameGenerator = contentNameGenerator;
0280:                this .contentLocation = contentLocation;
0281:            }
0282:
0283:            public ResourceManager getResourceManager() {
0284:                return resourceManager;
0285:            }
0286:
0287:            public URLRewriter getUrlRewriter() {
0288:                return urlRewriter;
0289:            }
0290:
0291:            public void setUrlRewriter(final URLRewriter urlRewriter) {
0292:                if (urlRewriter == null) {
0293:                    throw new NullPointerException();
0294:                }
0295:                this .urlRewriter = urlRewriter;
0296:            }
0297:
0298:            public ContentItem getDocumentContentItem() {
0299:                return documentContentItem;
0300:            }
0301:
0302:            public void setDocumentContentItem(
0303:                    final ContentItem documentContentItem) {
0304:                this .documentContentItem = documentContentItem;
0305:            }
0306:
0307:            public String writeRaw(final ResourceKey source) throws IOException {
0308:                if (copyExternalImages == false) {
0309:                    final Object identifier = source.getIdentifier();
0310:                    if (identifier instanceof  URL) {
0311:                        final URL url = (URL) identifier;
0312:                        final String protocol = url.getProtocol();
0313:                        if ("http".equalsIgnoreCase(protocol)
0314:                                || "https".equalsIgnoreCase(protocol)
0315:                                || "ftp".equalsIgnoreCase(protocol)) {
0316:                            return url.toExternalForm();
0317:                        }
0318:                    }
0319:                }
0320:
0321:                if (dataLocation == null) {
0322:                    return null;
0323:                }
0324:
0325:                try {
0326:                    final ResourceData resourceData = resourceManager
0327:                            .load(source);
0328:                    final String mimeType = queryMimeType(resourceData);
0329:                    if (isValidImage(mimeType)) {
0330:                        // lets do some voodo ..
0331:                        final ContentItem item = dataLocation
0332:                                .createItem(dataNameGenerator
0333:                                        .generateName(
0334:                                                extractFilename(resourceData),
0335:                                                mimeType));
0336:                        if (item.isWriteable()) {
0337:                            item.setAttribute(
0338:                                    LibRepositoryBoot.REPOSITORY_DOMAIN,
0339:                                    LibRepositoryBoot.CONTENT_TYPE, mimeType);
0340:
0341:                            // write it out ..
0342:                            final InputStream stream = new BufferedInputStream(
0343:                                    resourceData
0344:                                            .getResourceAsStream(resourceManager));
0345:                            try {
0346:                                final OutputStream outputStream = new BufferedOutputStream(
0347:                                        item.getOutputStream());
0348:                                try {
0349:                                    IOUtils.getInstance().copyStreams(stream,
0350:                                            outputStream);
0351:                                } finally {
0352:                                    outputStream.close();
0353:                                }
0354:                            } finally {
0355:                                stream.close();
0356:                            }
0357:
0358:                            return urlRewriter.rewrite(documentContentItem,
0359:                                    item);
0360:                        }
0361:                    }
0362:                } catch (ResourceLoadingException e) {
0363:                    // Ok, loading the resource failed. Not a problem, so we will
0364:                    // recode the raw-object instead ..
0365:                } catch (ContentIOException e) {
0366:                    // ignore it ..
0367:                } catch (URLRewriteException e) {
0368:                    Log.warn("Rewriting the URL failed.", e);
0369:                    throw new StackableRuntimeException("Failed", e);
0370:                }
0371:                return null;
0372:            }
0373:
0374:            /**
0375:             * Tests, whether the given URL points to a supported file format for common browsers. Returns true if the URL
0376:             * references a JPEG, PNG or GIF image, false otherwise.
0377:             * <p/>
0378:             * The checked filetypes are the ones recommended by the W3C.
0379:             *
0380:             * @param url the url that should be tested.
0381:             * @return true, if the content type is supported by the browsers, false otherwise.
0382:             */
0383:            protected boolean isSupportedImageFormat(final URL url) {
0384:                final String file = url.getFile();
0385:                if (StringUtils.endsWithIgnoreCase(file, ".jpg")) {
0386:                    return true;
0387:                }
0388:                if (StringUtils.endsWithIgnoreCase(file, ".jpeg")) {
0389:                    return true;
0390:                }
0391:                if (StringUtils.endsWithIgnoreCase(file, ".png")) {
0392:                    return true;
0393:                }
0394:                if (StringUtils.endsWithIgnoreCase(file, ".gif")) {
0395:                    return true;
0396:                }
0397:                return false;
0398:            }
0399:
0400:            private ImageData getImageData(final ImageContainer image)
0401:                    throws IOException {
0402:                URL url = null;
0403:                // The image has an assigned URL ...
0404:                if (image instanceof  URLImageContainer) {
0405:                    final URLImageContainer urlImage = (URLImageContainer) image;
0406:
0407:                    url = urlImage.getSourceURL();
0408:                    // if we have an source to load the image data from ..
0409:                    if (url != null) {
0410:                        if (urlImage.isLoadable()
0411:                                && isSupportedImageFormat(url)) {
0412:                            final MemoryByteArrayOutputStream bout = new MemoryByteArrayOutputStream();
0413:                            final InputStream urlIn = new BufferedInputStream(
0414:                                    urlImage.getSourceURL().openStream());
0415:                            try {
0416:                                IOUtils.getInstance().copyStreams(urlIn, bout);
0417:                            } finally {
0418:                                urlIn.close();
0419:                                bout.close();
0420:                            }
0421:                            final byte[] imageData = bout.toByteArray();
0422:                            final String mimeType = queryMimeType(imageData);
0423:                            final String originalFileName = IOUtils
0424:                                    .getInstance().getFileName(url);
0425:                            return new ImageData(imageData, mimeType,
0426:                                    originalFileName);
0427:                        }
0428:                    }
0429:                }
0430:
0431:                if (image instanceof  LocalImageContainer) {
0432:                    // Check, whether the imagereference contains an AWT image.
0433:                    // if so, then we can use that image instance for the recoding
0434:                    final LocalImageContainer li = (LocalImageContainer) image;
0435:                    Image awtImage = li.getImage();
0436:                    if (awtImage == null) {
0437:                        if (url != null) {
0438:                            awtImage = ImageFactory.getInstance().createImage(
0439:                                    url);
0440:                        }
0441:                    }
0442:                    if (awtImage != null) {
0443:                        // now encode the image. We don't need to create digest data
0444:                        // for the image contents, as the image is perfectly identifyable
0445:                        // by its URL
0446:                        final byte[] imageData = RenderUtility
0447:                                .encodeImage(awtImage);
0448:                        final String mimeType = "image/png";
0449:                        final String originalFileName;
0450:                        if (url != null) {
0451:                            originalFileName = IOUtils.getInstance()
0452:                                    .getFileName(url);
0453:                        } else {
0454:                            originalFileName = "picture.png";
0455:                        }
0456:                        return new ImageData(imageData, mimeType,
0457:                                originalFileName);
0458:                    }
0459:                }
0460:                return null;
0461:            }
0462:
0463:            public String writeImage(final ImageContainer image)
0464:                    throws ContentIOException, IOException {
0465:                if (dataLocation == null) {
0466:                    return null;
0467:                }
0468:
0469:                final String cacheKey;
0470:                if (image instanceof  URLImageContainer) {
0471:                    final URLImageContainer uic = (URLImageContainer) image;
0472:                    cacheKey = uic.getSourceURLString();
0473:                    final String retval = (String) knownImages.get(cacheKey);
0474:                    if (retval != null) {
0475:                        return retval;
0476:                    }
0477:
0478:                    final String sourceURLString = uic.getSourceURLString();
0479:                    if (uic.isLoadable() == false && sourceURLString != null) {
0480:                        knownImages.put(cacheKey, sourceURLString);
0481:                        return sourceURLString;
0482:                    }
0483:                } else {
0484:                    cacheKey = null;
0485:                }
0486:
0487:                final ImageData data = getImageData(image);
0488:                if (data == null) {
0489:                    return null;
0490:                }
0491:
0492:                try {
0493:                    // write the encoded picture ...
0494:                    final String filename = IOUtils.getInstance()
0495:                            .stripFileExtension(data.getOriginalFileName());
0496:                    final ContentItem dataFile = dataLocation
0497:                            .createItem(dataNameGenerator.generateName(
0498:                                    filename, data.getMimeType()));
0499:                    final String contentURL = urlRewriter.rewrite(
0500:                            documentContentItem, dataFile);
0501:
0502:                    // a png encoder is included in JCommon ...
0503:                    final OutputStream out = new BufferedOutputStream(dataFile
0504:                            .getOutputStream());
0505:                    try {
0506:                        out.write(data.getImageData());
0507:                        out.flush();
0508:                    } finally {
0509:                        out.close();
0510:                    }
0511:                    if (cacheKey != null) {
0512:                        knownImages.put(cacheKey, contentURL);
0513:                    }
0514:
0515:                    return contentURL;
0516:                } catch (ContentCreationException cce) {
0517:                    // Can't create the content
0518:                    Log
0519:                            .warn("Failed to create the content image: Reason given was: "
0520:                                    + cce.getMessage());
0521:                    return null;
0522:                } catch (URLRewriteException re) {
0523:                    // cannot handle this ..
0524:                    Log.warn("Failed to write the URL: Reason given was: "
0525:                            + re.getMessage());
0526:                    return null;
0527:                }
0528:            }
0529:
0530:            private String extractFilename(final ResourceData resourceData) {
0531:                final String filename = (String) resourceData
0532:                        .getAttribute(ResourceData.FILENAME);
0533:                if (filename == null) {
0534:                    return "image";
0535:                }
0536:
0537:                return IOUtils.getInstance().stripFileExtension(filename);
0538:            }
0539:
0540:            private String queryMimeType(final ResourceData resourceData)
0541:                    throws ResourceLoadingException, IOException {
0542:                final Object contentType = resourceData
0543:                        .getAttribute(ResourceData.CONTENT_TYPE);
0544:                if (contentType instanceof  String) {
0545:                    return (String) contentType;
0546:                }
0547:
0548:                // now we are getting very primitive .. (Kids, dont do this at home)
0549:                final byte[] data = new byte[12];
0550:                resourceData.getResource(resourceManager, data, 0, data.length);
0551:                return queryMimeType(data);
0552:            }
0553:
0554:            private String queryMimeType(final byte[] data) throws IOException {
0555:                final ByteArrayInputStream stream = new ByteArrayInputStream(
0556:                        data);
0557:                if (isGIF(stream)) {
0558:                    return "image/gif";
0559:                }
0560:                stream.reset();
0561:                if (isJPEG(stream)) {
0562:                    return "image/jpeg";
0563:                }
0564:                stream.reset();
0565:                if (isPNG(stream)) {
0566:                    return "image/png";
0567:                }
0568:                return null;
0569:            }
0570:
0571:            private boolean isPNG(final ByteArrayInputStream data) {
0572:                final int[] PNF_FINGERPRINT = { 137, 80, 78, 71, 13, 10, 26, 10 };
0573:                for (int i = 0; i < PNF_FINGERPRINT.length; i++) {
0574:                    if (PNF_FINGERPRINT[i] != data.read()) {
0575:                        return false;
0576:                    }
0577:                }
0578:                return true;
0579:            }
0580:
0581:            private boolean isJPEG(final InputStream data) throws IOException {
0582:                final int[] JPG_FINGERPRINT_1 = { 0xFF, 0xD8, 0xFF, 0xE0 };
0583:                for (int i = 0; i < JPG_FINGERPRINT_1.length; i++) {
0584:                    if (JPG_FINGERPRINT_1[i] != data.read()) {
0585:                        return false;
0586:                    }
0587:                }
0588:                // then skip two bytes ..
0589:                if (data.read() == -1) {
0590:                    return false;
0591:                }
0592:                if (data.read() == -1) {
0593:                    return false;
0594:                }
0595:
0596:                final int[] JPG_FINGERPRINT_2 = { 0x4A, 0x46, 0x49, 0x46, 0x00 };
0597:                for (int i = 0; i < JPG_FINGERPRINT_2.length; i++) {
0598:                    if (JPG_FINGERPRINT_2[i] != data.read()) {
0599:                        return false;
0600:                    }
0601:                }
0602:                return true;
0603:            }
0604:
0605:            private boolean isGIF(final InputStream data) throws IOException {
0606:                final int[] GIF_FINGERPRINT = { 'G', 'I', 'F', '8' };
0607:                for (int i = 0; i < GIF_FINGERPRINT.length; i++) {
0608:                    if (GIF_FINGERPRINT[i] != data.read()) {
0609:                        return false;
0610:                    }
0611:                }
0612:                return true;
0613:            }
0614:
0615:            private boolean isValidImage(final String mimeType) {
0616:                return validRawTypes.contains(mimeType);
0617:            }
0618:
0619:            private boolean isCreateBodyFragment() {
0620:                return "true".equals(getConfiguration().getConfigProperty(
0621:                        HtmlTableModule.BODY_FRAGMENT, "false"));
0622:            }
0623:
0624:            private boolean isEmptyCellsUseCSS() {
0625:                return "true".equals(getConfiguration().getConfigProperty(
0626:                        HtmlTableModule.EMPTY_CELLS_USE_CSS, "false"));
0627:            }
0628:
0629:            private boolean isTableRowBorderDefinition() {
0630:                return "true".equals(getConfiguration().getConfigProperty(
0631:                        HtmlTableModule.TABLE_ROW_BORDER_DEFINITION, "false"));
0632:            }
0633:
0634:            private boolean isProportionalColumnWidths() {
0635:                return "true".equals(getConfiguration().getConfigProperty(
0636:                        HtmlTableModule.PROPORTIONAL_COLUMN_WIDTHS, "false"));
0637:            }
0638:
0639:            private AttributeList createCellAttributes(
0640:                    final TableRectangle rect, final RenderBox content,
0641:                    final TableCellDefinition background,
0642:                    final String[] extraStyleKeys,
0643:                    final String[] extraStyleValues) {
0644:                if (content == null) {
0645:                    styleBuilder.clear();
0646:                } else {
0647:                    styleBuilder = produceTextStyle(styleBuilder, content,
0648:                            true, false);
0649:                }
0650:
0651:                // Add the extra styles
0652:                if (extraStyleKeys != null && extraStyleValues != null
0653:                        && extraStyleKeys.length == extraStyleValues.length) {
0654:                    for (int i = 0; i < extraStyleKeys.length; ++i) {
0655:                        styleBuilder.append(extraStyleKeys[i],
0656:                                extraStyleValues[i], false);
0657:                    }
0658:                }
0659:
0660:                if (background != null) {
0661:                    final Color colorValue = (background.getBackgroundColor());
0662:                    if (colorValue != null) {
0663:                        styleBuilder.append("background-color", HtmlColors
0664:                                .getColorString(colorValue));
0665:                    }
0666:
0667:                    styleBuilder.append("border-top", styleBuilder
0668:                            .printEdgeAsCSS(background.getTop()));
0669:                    styleBuilder.append("border-left", styleBuilder
0670:                            .printEdgeAsCSS(background.getLeft()));
0671:                    styleBuilder.append("border-bottom", styleBuilder
0672:                            .printEdgeAsCSS(background.getBottom()));
0673:                    styleBuilder.append("border-right", styleBuilder
0674:                            .printEdgeAsCSS(background.getRight()));
0675:                }
0676:
0677:                final AttributeList attrList = new AttributeList();
0678:                if (content != null) {
0679:                    // ignore for now ..
0680:                    final int rowSpan = rect.getRowSpan();
0681:                    if (rowSpan > 1) {
0682:                        attrList.setAttribute(XHTML_NAMESPACE, "rowspan",
0683:                                String.valueOf(rowSpan));
0684:                    }
0685:                    final int colSpan = rect.getColumnSpan();
0686:                    if (colSpan > 1) {
0687:                        attrList.setAttribute(XHTML_NAMESPACE, "colspan",
0688:                                String.valueOf(colSpan));
0689:                    }
0690:
0691:                    final ElementAlignment verticalAlignment = content
0692:                            .getNodeLayoutProperties().getVerticalAlignment();
0693:                    attrList.setAttribute(HtmlPrinter.XHTML_NAMESPACE,
0694:                            "valign",
0695:                            translateVerticalAlignment(verticalAlignment));
0696:                }
0697:
0698:                styleManager.updateStyle(styleBuilder, attrList);
0699:                return attrList;
0700:            }
0701:
0702:            /**
0703:             * Translates the JFreeReport horizontal element alignment into a HTML alignment constant.
0704:             *
0705:             * @param ea the element alignment
0706:             * @return the translated alignment name.
0707:             */
0708:            private String translateVerticalAlignment(final ElementAlignment ea) {
0709:                if (ea == ElementAlignment.BOTTOM) {
0710:                    return "bottom";
0711:                }
0712:                if (ea == ElementAlignment.MIDDLE) {
0713:                    return "middle";
0714:                }
0715:                return "top";
0716:            }
0717:
0718:            private AttributeList createRowAttributes(
0719:                    final SheetLayout sheetLayout, final int row) {
0720:                // todo: Check for common backgrounds and top/bottom borders
0721:                // todo: Check for global style ..
0722:                final AttributeList attrList = new AttributeList();
0723:                final int rowHeight = (int) StrictGeomUtility
0724:                        .toExternalValue(sheetLayout.getRowHeight(row));
0725:
0726:                if (isTableRowBorderDefinition()) {
0727:                    styleBuilder.clear();
0728:                    final Color commonBackgroundColor = getCommonBackgroundColor(
0729:                            sheetLayout, row);
0730:                    final BorderEdge top = getCommonTopBorderEdge(sheetLayout,
0731:                            row);
0732:                    final BorderEdge bottom = getCommonBottomBorderEdge(
0733:                            sheetLayout, row);
0734:                    if (commonBackgroundColor != null) {
0735:                        styleBuilder.append("background-color", HtmlColors
0736:                                .getColorString(commonBackgroundColor));
0737:                    }
0738:                    styleBuilder.append("border-top", styleBuilder
0739:                            .printEdgeAsCSS(top));
0740:                    styleBuilder.append("border-bottom", styleBuilder
0741:                            .printEdgeAsCSS(bottom));
0742:                    styleBuilder.append("height", styleBuilder
0743:                            .getPointConverter().format(rowHeight), "pt");
0744:                    styleManager.updateStyle(styleBuilder, attrList);
0745:                } else {
0746:                    // equally expensive and makes text more readable (helps with debugging)
0747:                    attrList.setAttribute(HtmlPrinter.XHTML_NAMESPACE, "style",
0748:                            "height: " + rowHeight + "pt");
0749:                }
0750:                return attrList;
0751:            }
0752:
0753:            private BorderEdge getCommonTopBorderEdge(
0754:                    final SheetLayout sheetLayout, final int row) {
0755:                BorderEdge bg = BorderEdge.EMPTY;
0756:                final int columnCount = sheetLayout.getColumnCount();
0757:                for (int col = 0; col < columnCount; col += 1) {
0758:                    final TableCellDefinition backgroundAt = sheetLayout
0759:                            .getBackgroundAt(row, col);
0760:                    if (backgroundAt == null) {
0761:                        return BorderEdge.EMPTY;
0762:                    }
0763:                    if (col == 0) {
0764:                        bg = backgroundAt.getTop();
0765:                    } else if (ObjectUtilities.equal(bg, backgroundAt.getTop()) == false) {
0766:                        return BorderEdge.EMPTY;
0767:                    }
0768:                }
0769:                return bg;
0770:            }
0771:
0772:            private BorderEdge getCommonBottomBorderEdge(
0773:                    final SheetLayout sheetLayout, final int row) {
0774:                BorderEdge bg = BorderEdge.EMPTY;
0775:                final int columnCount = sheetLayout.getColumnCount();
0776:                for (int col = 0; col < columnCount; col += 1) {
0777:                    final TableCellDefinition backgroundAt = sheetLayout
0778:                            .getBackgroundAt(row, col);
0779:                    if (backgroundAt == null) {
0780:                        return BorderEdge.EMPTY;
0781:                    }
0782:                    if (col == 0) {
0783:                        bg = backgroundAt.getBottom();
0784:                    } else if (ObjectUtilities.equal(bg, backgroundAt
0785:                            .getBottom()) == false) {
0786:                        return BorderEdge.EMPTY;
0787:                    }
0788:                }
0789:                return bg;
0790:            }
0791:
0792:            private Color getCommonBackgroundColor(
0793:                    final SheetLayout sheetLayout, final int row) {
0794:                Color bg = null;
0795:                final int columnCount = sheetLayout.getColumnCount();
0796:                for (int col = 0; col < columnCount; col += 1) {
0797:                    final TableCellDefinition backgroundAt = sheetLayout
0798:                            .getBackgroundAt(row, col);
0799:                    if (backgroundAt == null) {
0800:                        return null;
0801:                    }
0802:
0803:                    if (col == 0) {
0804:                        bg = backgroundAt.getBackgroundColor();
0805:                    } else {
0806:                        if (ObjectUtilities.equal(bg, backgroundAt
0807:                                .getBackgroundColor()) == false) {
0808:                            return null;
0809:                        }
0810:                    }
0811:                }
0812:                return bg;
0813:            }
0814:
0815:            private AttributeList createSheetNameAttributes() {
0816:                final AttributeList tableAttrList = new AttributeList();
0817:
0818:                final String additionalStyleClass = getConfiguration()
0819:                        .getConfigProperty(
0820:                                "org.jfree.report.modules.output.table.html.SheetNameClass");
0821:                if (additionalStyleClass != null) {
0822:                    tableAttrList.setAttribute(XHTML_NAMESPACE, "class",
0823:                            additionalStyleClass);
0824:                }
0825:
0826:                return tableAttrList;
0827:            }
0828:
0829:            private AttributeList createTableAttributes(
0830:                    final SheetLayout sheetLayout) {
0831:                final int noc = sheetLayout.getColumnCount();
0832:                styleBuilder.clear();
0833:                if ((noc > 0) && (isProportionalColumnWidths() == false)) {
0834:                    final int width = (int) StrictGeomUtility
0835:                            .toExternalValue(sheetLayout.getCellWidth(0, noc));
0836:                    styleBuilder.append("width", width + "pt");
0837:                } else {
0838:                    // Consume the complete width for proportional column widths
0839:                    styleBuilder.append("width", "100%");
0840:                }
0841:
0842:                // style += "table-layout: fixed;";
0843:                if (isTableRowBorderDefinition()) {
0844:                    styleBuilder.append("border-collapse", "collapse");
0845:                }
0846:                if (isEmptyCellsUseCSS()) {
0847:                    styleBuilder.append("empty-cells", "show");
0848:                }
0849:
0850:                final String additionalStyleClass = getConfiguration()
0851:                        .getConfigProperty(
0852:                                "org.jfree.report.modules.output.table.html.StyleClass");
0853:
0854:                final AttributeList tableAttrList = new AttributeList();
0855:                if (additionalStyleClass != null) {
0856:                    tableAttrList.setAttribute(XHTML_NAMESPACE, "class",
0857:                            additionalStyleClass);
0858:                }
0859:                tableAttrList.setAttribute(XHTML_NAMESPACE, "cellspacing", "0");
0860:                tableAttrList.setAttribute(XHTML_NAMESPACE, "cellpadding", "0");
0861:
0862:                styleManager.updateStyle(styleBuilder, tableAttrList);
0863:                return tableAttrList;
0864:            }
0865:
0866:            private void writeColumnDeclaration(final SheetLayout sheetLayout)
0867:                    throws IOException {
0868:                final int colCount = sheetLayout.getColumnCount();
0869:                final int fullWidth = (int) StrictGeomUtility
0870:                        .toExternalValue(sheetLayout.getMaxWidth());
0871:                final boolean proportionalColumnWidths = isProportionalColumnWidths();
0872:
0873:                final NumberFormat pointConverter = styleBuilder
0874:                        .getPointConverter();
0875:                final NumberFormat pointIntConverter = styleBuilder
0876:                        .getPointIntConverter();
0877:                for (int col = 0; col < colCount; col++) {
0878:                    // Print the table.
0879:                    final int width = (int) StrictGeomUtility
0880:                            .toExternalValue(sheetLayout.getCellWidth(col,
0881:                                    col + 1));
0882:                    styleBuilder.clear();
0883:                    if (proportionalColumnWidths) {
0884:                        final double colWidth = width * 100.0d / fullWidth;
0885:                        styleBuilder.append("width", pointConverter
0886:                                .format(colWidth) + '%');
0887:                    } else {
0888:                        styleBuilder.append("width", pointIntConverter
0889:                                .format(width)
0890:                                + "pt");
0891:                    }
0892:
0893:                    xmlWriter.writeTag(null, "col", "style", styleBuilder
0894:                            .toString(), XmlWriterSupport.CLOSE);
0895:                }
0896:            }
0897:
0898:            public void print(final LogicalPageKey logicalPageKey,
0899:                    final LogicalPageBox logicalPage,
0900:                    final TableContentProducer contentProducer,
0901:                    final OutputProcessorMetaData metaData,
0902:                    final boolean incremental)
0903:                    throws ContentProcessingException {
0904:                this .configuration = metaData.getConfiguration();
0905:                this .allowRawLinkTargets = "true"
0906:                        .equals(configuration
0907:                                .getConfigProperty(HtmlTableModule.ALLOW_RAW_LINK_TARGETS));
0908:                this .copyExternalImages = "true"
0909:                        .equals(configuration
0910:                                .getConfigProperty(HtmlTableModule.COPY_EXTERNAL_IMAGES));
0911:
0912:                try {
0913:                    final SheetLayout sheetLayout = contentProducer
0914:                            .getSheetLayout();
0915:
0916:                    if (documentContentItem == null) {
0917:                        documentContentItem = contentLocation
0918:                                .createItem(contentNameGenerator.generateName(
0919:                                        null, "text/html"));
0920:
0921:                        final OutputStream out = documentContentItem
0922:                                .getOutputStream();
0923:                        final String encoding = configuration
0924:                                .getConfigProperty(HtmlTableModule.ENCODING,
0925:                                        EncodingRegistry
0926:                                                .getPlatformDefaultEncoding());
0927:                        writer = new BufferedWriter(new OutputStreamWriter(out,
0928:                                encoding));
0929:
0930:                        final DefaultTagDescription td = new DefaultTagDescription();
0931:                        td.configure(getConfiguration(),
0932:                                "org.jfree.report.modules.output.table.html.");
0933:
0934:                        if (isCreateBodyFragment() == false) {
0935:                            if (isInlineStylesRequested()) {
0936:                                this .styleManager = new InlineStyleManager();
0937:                                this .xmlWriter = new XmlWriter(writer, td);
0938:                                this .xmlWriter.addImpliedNamespace(
0939:                                        HtmlPrinter.XHTML_NAMESPACE, "");
0940:                                this .xmlWriter.setHtmlCompatiblityMode(true);
0941:                                writeCompleteHeader(xmlWriter, contentProducer,
0942:                                        null, null);
0943:                            } else {
0944:                                if (isExternalStyleSheetRequested()) {
0945:                                    this .styleFile = dataLocation
0946:                                            .createItem(dataNameGenerator
0947:                                                    .generateName("style",
0948:                                                            "text/css"));
0949:                                    this .styleFileUrl = urlRewriter.rewrite(
0950:                                            documentContentItem, styleFile);
0951:                                }
0952:
0953:                                this .styleManager = new GlobalStyleManager();
0954:                                if (isForceBufferedWriting() == false
0955:                                        && styleFile != null) {
0956:                                    this .xmlWriter = new XmlWriter(writer, td);
0957:                                    this .xmlWriter.addImpliedNamespace(
0958:                                            HtmlPrinter.XHTML_NAMESPACE, "");
0959:                                    this .xmlWriter
0960:                                            .setHtmlCompatiblityMode(true);
0961:                                    writeCompleteHeader(xmlWriter,
0962:                                            contentProducer, styleFileUrl, null);
0963:                                } else {
0964:                                    this .bufferWriter = new MemoryStringWriter(
0965:                                            1024 * 512);
0966:                                    this .xmlWriter = new XmlWriter(
0967:                                            bufferWriter, td);
0968:                                    this .xmlWriter.setAdditionalIndent(1);
0969:                                    this .xmlWriter.addImpliedNamespace(
0970:                                            HtmlPrinter.XHTML_NAMESPACE, "");
0971:                                    this .xmlWriter
0972:                                            .setHtmlCompatiblityMode(true);
0973:                                }
0974:                            }
0975:
0976:                            this .xmlWriter.writeTag(
0977:                                    HtmlPrinter.XHTML_NAMESPACE, "body",
0978:                                    XmlWriterSupport.OPEN);
0979:                        } else {
0980:                            this .styleManager = new InlineStyleManager();
0981:                            this .xmlWriter = new XmlWriter(writer, td);
0982:                            this .xmlWriter.addImpliedNamespace(
0983:                                    HtmlPrinter.XHTML_NAMESPACE, "");
0984:                            this .xmlWriter.setHtmlCompatiblityMode(true);
0985:                        }
0986:
0987:                        // table name
0988:                        final String sheetName = contentProducer.getSheetName();
0989:                        if (sheetName != null) {
0990:                            xmlWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE,
0991:                                    "h1", createSheetNameAttributes(),
0992:                                    XmlWriterSupport.OPEN);
0993:                            xmlWriter.writeText(xmlWriter.normalizeLocal(
0994:                                    sheetName, true));
0995:                            xmlWriter.writeCloseTag();
0996:                        }
0997:
0998:                        // table
0999:                        xmlWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE,
1000:                                "table", createTableAttributes(sheetLayout),
1001:                                XmlWriterSupport.OPEN);
1002:                        writeColumnDeclaration(sheetLayout);
1003:                    }
1004:
1005:                    final int colCount = sheetLayout.getColumnCount();
1006:                    //      final int rowCount = sheetLayout.getRowCount();
1007:                    final boolean emptyCellsUseCSS = isEmptyCellsUseCSS();
1008:
1009:                    final int startRow = contentProducer.getFinishedRows();
1010:                    final int finishRow = contentProducer.getFilledRows();
1011:                    // Log.debug ("Processing: " + startRow + " " + finishRow + " " + incremental);
1012:                    final HtmlTextExtractor textExtractor = new HtmlTextExtractor(
1013:                            metaData, xmlWriter, styleManager, this );
1014:
1015:                    for (int row = startRow; row < finishRow; row++) {
1016:                        xmlWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE, "tr",
1017:                                createRowAttributes(sheetLayout, row),
1018:                                XmlWriterSupport.OPEN);
1019:                        for (int col = 0; col < colCount; col++) {
1020:                            final RenderBox content = contentProducer
1021:                                    .getContent(row, col);
1022:                            final TableCellDefinition background = sheetLayout
1023:                                    .getBackgroundAt(row, col);
1024:
1025:                            if (content == null && background == null) {
1026:                                if (emptyCellsUseCSS) {
1027:                                    xmlWriter.writeTag(
1028:                                            HtmlPrinter.XHTML_NAMESPACE, "td",
1029:                                            XmlWriterSupport.CLOSE);
1030:                                } else {
1031:                                    final AttributeList attrs = new AttributeList();
1032:                                    attrs.setAttribute(
1033:                                            HtmlPrinter.XHTML_NAMESPACE,
1034:                                            "style", "font-size: 1pt");
1035:                                    xmlWriter.writeTag(
1036:                                            HtmlPrinter.XHTML_NAMESPACE, "td",
1037:                                            attrs, XmlWriterSupport.OPEN);
1038:                                    xmlWriter.writeText("&nbsp;");
1039:                                    xmlWriter.writeCloseTag();
1040:                                }
1041:
1042:                                continue;
1043:                            }
1044:
1045:                            if (content != null) {
1046:                                if (content.isCommited() == false) {
1047:                                    throw new InvalidReportStateException(
1048:                                            "Uncommited content encountered: "
1049:                                                    + row + ", " + col + ' '
1050:                                                    + content);
1051:                                }
1052:
1053:                                final long contentOffset = contentProducer
1054:                                        .getContentOffset(row, col);
1055:                                final TableRectangle rectangle = sheetLayout
1056:                                        .getTableBounds(content.getX(), content
1057:                                                .getY()
1058:                                                + contentOffset, content
1059:                                                .getWidth(), content
1060:                                                .getHeight(), null);
1061:                                if (rectangle.isOrigin(col, row) == false) {
1062:                                    // A spanned cell ..
1063:                                    continue;
1064:                                }
1065:
1066:                                final TableCellDefinition realBackground;
1067:                                if (background == null
1068:                                        || (rectangle.getColumnSpan() == 1 && rectangle
1069:                                                .getRowSpan() == 1)) {
1070:                                    realBackground = background;
1071:                                } else {
1072:                                    realBackground = sheetLayout
1073:                                            .getBackgroundAt(rectangle.getX1(),
1074:                                                    rectangle.getY1(),
1075:                                                    rectangle.getColumnSpan(),
1076:                                                    rectangle.getRowSpan());
1077:                                }
1078:
1079:                                final AttributeList cellAttributes = createCellAttributes(
1080:                                        rectangle, content, realBackground,
1081:                                        null, null);
1082:                                xmlWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE,
1083:                                        "td", cellAttributes,
1084:                                        XmlWriterSupport.OPEN);
1085:                                if (background != null) {
1086:                                    final String anchor = background
1087:                                            .getAnchor();
1088:                                    if (anchor != null) {
1089:                                        xmlWriter.writeTag(
1090:                                                HtmlPrinter.XHTML_NAMESPACE,
1091:                                                "a", "name", normalize(anchor,
1092:                                                        xmlWriter),
1093:                                                XmlWriterSupport.CLOSE);
1094:                                    }
1095:                                }
1096:                                // the style of the content-box itself is already contained in the <td> tag. So there is no need
1097:                                // to duplicate the style here
1098:                                textExtractor.performOutput(content);
1099:
1100:                                xmlWriter.writeCloseTag();
1101:                                content.setFinished(true);
1102:                            } else {
1103:                                // Background cannot be null at this point ..
1104:                                final String anchor = background.getAnchor();
1105:                                if (anchor == null && emptyCellsUseCSS) {
1106:                                    final AttributeList cellAttributes = createCellAttributes(
1107:                                            null, null, background, null, null);
1108:                                    xmlWriter.writeTag(
1109:                                            HtmlPrinter.XHTML_NAMESPACE, "td",
1110:                                            cellAttributes,
1111:                                            XmlWriterSupport.CLOSE);
1112:                                } else {
1113:                                    final AttributeList cellAttributes = createCellAttributes(
1114:                                            null, null, background,
1115:                                            EMPTY_CELL_ATTRNAMES,
1116:                                            EMPTY_CELL_ATTRVALS);
1117:                                    xmlWriter.writeTag(
1118:                                            HtmlPrinter.XHTML_NAMESPACE, "td",
1119:                                            cellAttributes,
1120:                                            XmlWriterSupport.OPEN);
1121:                                    if (anchor != null) {
1122:                                        xmlWriter.writeTag(
1123:                                                HtmlPrinter.XHTML_NAMESPACE,
1124:                                                "a", "name", normalize(anchor,
1125:                                                        xmlWriter),
1126:                                                XmlWriterSupport.CLOSE);
1127:                                    }
1128:                                    xmlWriter.writeText("&nbsp;");
1129:                                    xmlWriter.writeCloseTag();
1130:
1131:                                }
1132:                            }
1133:                        }
1134:                        xmlWriter.writeCloseTag();
1135:                    }
1136:
1137:                    if (incremental == false) {
1138:                        performCloseFile(contentProducer);
1139:
1140:                        xmlWriter = null;
1141:                        try {
1142:                            writer.close();
1143:                        } catch (IOException e) {
1144:                            // ignored ..
1145:                        }
1146:                        writer = null;
1147:                        bufferWriter = null;
1148:                        documentContentItem = null;
1149:                    }
1150:                } catch (IOException ioe) {
1151:                    xmlWriter = null;
1152:                    try {
1153:                        if (writer != null) {
1154:                            writer.close();
1155:                        }
1156:                    } catch (IOException e) {
1157:                        // ignored ..
1158:                    }
1159:                    writer = null;
1160:                    bufferWriter = null;
1161:                    documentContentItem = null;
1162:                    styleFile = null;
1163:
1164:                    // ignore for now ..
1165:                    throw new ContentProcessingException(
1166:                            "IOError while creating content", ioe);
1167:                } catch (ContentIOException e) {
1168:                    xmlWriter = null;
1169:                    try {
1170:                        if (writer != null) {
1171:                            writer.close();
1172:                        }
1173:                    } catch (IOException ex) {
1174:                        // ignored ..
1175:                    }
1176:                    writer = null;
1177:                    bufferWriter = null;
1178:                    documentContentItem = null;
1179:                    styleFile = null;
1180:
1181:                    throw new ContentProcessingException(
1182:                            "Content-IOError while creating content", e);
1183:                } catch (URLRewriteException e) {
1184:                    xmlWriter = null;
1185:                    try {
1186:                        if (writer != null) {
1187:                            writer.close();
1188:                        }
1189:                    } catch (IOException ex) {
1190:                        // ignored ..
1191:                    }
1192:                    writer = null;
1193:                    bufferWriter = null;
1194:                    documentContentItem = null;
1195:                    styleFile = null;
1196:
1197:                    throw new ContentProcessingException(
1198:                            "Cannot create URL for external stylesheet", e);
1199:                }
1200:            }
1201:
1202:            private void writeCompleteHeader(final XmlWriter docWriter,
1203:                    final TableContentProducer contentProducer,
1204:                    final String url, final String inlineStyleSheet)
1205:                    throws IOException {
1206:                final String encoding = configuration.getConfigProperty(
1207:                        HtmlTableModule.ENCODING, EncodingRegistry
1208:                                .getPlatformDefaultEncoding());
1209:
1210:                docWriter.writeXmlDeclaration(encoding);
1211:                for (int i = 0; i < XHTML_HEADER.length; i++) {
1212:                    docWriter.writeText(HtmlPrinter.XHTML_HEADER[i]);
1213:                    docWriter.writeNewLine();
1214:                }
1215:                docWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE, "html",
1216:                        XmlWriterSupport.OPEN);
1217:                docWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE, "head",
1218:                        XmlWriterSupport.OPEN);
1219:
1220:                final String title = configuration
1221:                        .getConfigProperty(HtmlTableModule.TITLE);
1222:                if (title != null) {
1223:                    docWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE, "title",
1224:                            XmlWriterSupport.OPEN);
1225:                    docWriter.writeText(xmlWriter.normalizeLocal(title, false));
1226:                    docWriter.writeCloseTag();
1227:                }
1228:                // if no single title defined, use the sheetname function previously computed
1229:                else if (contentProducer.getSheetName() != null) {
1230:                    docWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE, "title",
1231:                            XmlWriterSupport.OPEN);
1232:                    docWriter.writeText(xmlWriter.normalizeLocal(
1233:                            contentProducer.getSheetName(), true));
1234:                    docWriter.writeCloseTag();
1235:                } else {
1236:                    docWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE, "title",
1237:                            XmlWriterSupport.OPEN);
1238:                    docWriter.writeText(" ");
1239:                    docWriter.writeCloseTag();
1240:                }
1241:
1242:                writeMeta(docWriter, "subject", configuration
1243:                        .getConfigProperty(HtmlTableModule.SUBJECT));
1244:                writeMeta(docWriter, "author", configuration
1245:                        .getConfigProperty(HtmlTableModule.AUTHOR));
1246:                writeMeta(docWriter, "keywords", configuration
1247:                        .getConfigProperty(HtmlTableModule.KEYWORDS));
1248:                writeMeta(docWriter, "generator", GENERATOR);
1249:
1250:                final AttributeList metaAttrs = new AttributeList();
1251:                metaAttrs.setAttribute(HtmlPrinter.XHTML_NAMESPACE,
1252:                        "http-equiv", "content-type");
1253:                metaAttrs.setAttribute(HtmlPrinter.XHTML_NAMESPACE, "content",
1254:                        "text/html; charset=" + encoding);
1255:                docWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE, "meta",
1256:                        metaAttrs, XmlWriterSupport.CLOSE);
1257:
1258:                if (url != null) {
1259:                    final AttributeList attrList = new AttributeList();
1260:                    attrList.setAttribute(HtmlPrinter.XHTML_NAMESPACE, "type",
1261:                            "text/css");
1262:                    attrList.setAttribute(HtmlPrinter.XHTML_NAMESPACE, "rel",
1263:                            "stylesheet");
1264:                    attrList.setAttribute(HtmlPrinter.XHTML_NAMESPACE, "href",
1265:                            url);
1266:
1267:                    docWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE, "link",
1268:                            attrList, XmlWriterSupport.CLOSE);
1269:                } else if (inlineStyleSheet != null) {
1270:                    docWriter.writeTag(HtmlPrinter.XHTML_NAMESPACE, "style",
1271:                            "type", "text/css", XmlWriterSupport.OPEN);
1272:                    docWriter.writeText(inlineStyleSheet);
1273:                    docWriter.writeCloseTag();
1274:                }
1275:                docWriter.writeCloseTag();
1276:            }
1277:
1278:            private void performCloseFile(
1279:                    final TableContentProducer contentProducer)
1280:                    throws IOException, ContentIOException {
1281:                xmlWriter.writeCloseTag(); // for the opening table ..
1282:
1283:                if (isCreateBodyFragment() != false) {
1284:                    xmlWriter.close();
1285:                    return;
1286:                }
1287:
1288:                if (styleFile != null) {
1289:                    final String encoding = configuration.getConfigProperty(
1290:                            HtmlTableModule.ENCODING, EncodingRegistry
1291:                                    .getPlatformDefaultEncoding());
1292:                    final Writer styleOut = new OutputStreamWriter(
1293:                            new BufferedOutputStream(styleFile
1294:                                    .getOutputStream()), encoding);
1295:                    styleManager.write(styleOut);
1296:                    styleOut.flush();
1297:                    styleOut.close();
1298:
1299:                    if (isForceBufferedWriting() == false) {
1300:                        // A complete header had been written when the processing started ..
1301:                        this .xmlWriter.writeCloseTag(); // for the body tag
1302:                        this .xmlWriter.writeCloseTag(); // for the HTML tag
1303:                        this .xmlWriter.close();
1304:                        return;
1305:                    }
1306:                }
1307:                if (isInlineStylesRequested()) {
1308:                    this .xmlWriter.writeCloseTag(); // for the body tag
1309:                    this .xmlWriter.writeCloseTag(); // for the HTML tag
1310:                    this .xmlWriter.close();
1311:                    return;
1312:                }
1313:
1314:                final XmlWriter docWriter = new XmlWriter(writer, xmlWriter
1315:                        .getTagDescription());
1316:                docWriter.addImpliedNamespace(HtmlPrinter.XHTML_NAMESPACE, "");
1317:                docWriter.setHtmlCompatiblityMode(true);
1318:
1319:                if (styleFile != null) {
1320:                    // now its time to write the header with the link to the style-sheet-file
1321:                    writeCompleteHeader(docWriter, contentProducer,
1322:                            styleFileUrl, null);
1323:                } else {
1324:                    final String globalStyleSheet = styleManager
1325:                            .getGlobalStyleSheet();
1326:                    writeCompleteHeader(docWriter, contentProducer, null,
1327:                            globalStyleSheet);
1328:                }
1329:
1330:                xmlWriter.writeCloseTag(); // for the body ..
1331:                xmlWriter.flush();
1332:                docWriter.writeText(bufferWriter.toString());
1333:
1334:                docWriter.writeCloseTag(); // for the html ..
1335:                docWriter.close();
1336:            }
1337:
1338:            private boolean isForceBufferedWriting() {
1339:                return "true"
1340:                        .equals(configuration
1341:                                .getConfigProperty(HtmlTableModule.FORCE_BUFFER_WRITING));
1342:            }
1343:
1344:            protected static String normalize(final String anchor,
1345:                    final XmlWriter xmlWriter) {
1346:                if (anchor == null) {
1347:                    return null;
1348:                }
1349:
1350:                // raw values are ok, which means that we just have to check whether the anchor breaks anything.
1351:                if (anchor.indexOf('<') == -1 && anchor.indexOf('>') == -1
1352:                        && anchor.indexOf('"') == -1) {
1353:                    return anchor;
1354:                }
1355:
1356:                return xmlWriter.normalizeLocal(anchor, true);
1357:            }
1358:
1359:            private void writeMeta(final XmlWriter writer, final String name,
1360:                    final String value) throws IOException {
1361:                if (value == null) {
1362:                    return;
1363:                }
1364:                final AttributeList attrList = new AttributeList();
1365:                attrList
1366:                        .setAttribute(HtmlPrinter.XHTML_NAMESPACE, "name", name);
1367:                attrList.setAttribute(HtmlPrinter.XHTML_NAMESPACE, "content",
1368:                        value);
1369:                writer.writeTag(HtmlPrinter.XHTML_NAMESPACE, "meta", attrList,
1370:                        XmlWriterSupport.CLOSE);
1371:            }
1372:
1373:            //
1374:            //  /**
1375:            //   * Checks, whether the engine should generate a stylesheet that is directly inserted into the header of the
1376:            //   * generated file.
1377:            //   *
1378:            //   * This method will return false, if "createBodyFragment" is enabled, as a body-fragment has no header.
1379:            //   *
1380:            //   * This methos will also return false, if inline-styles are requested.
1381:            //   *
1382:            //   * @return true, if the engine generates an stylesheet that is contained in the header, false otherwise.
1383:            //   */
1384:            //  private boolean isInternalStyleSheetRequested ()
1385:            //  {
1386:            //    if (isCreateBodyFragment())
1387:            //    {
1388:            //      // body-fragments have no header ..
1389:            //      return false;
1390:            //    }
1391:            //
1392:            //    // We will add the style-declarations directly to the HTML elements ..
1393:            //    if (isInlineStylesRequested())
1394:            //    {
1395:            //      return false;
1396:            //    }
1397:            //
1398:            //    final boolean externalStyle = "true".equals
1399:            //        (configuration.getConfigProperty("org.jfree.report.modules.output.table.html.ExternalStyle", "true"));
1400:            //    // User explicitly requested internal styles by disabeling the external-style property.
1401:            //    return externalStyle == false;
1402:            //  }
1403:
1404:            private boolean isInlineStylesRequested() {
1405:                return "true".equals(configuration
1406:                        .getConfigProperty(HtmlTableModule.INLINE_STYLE));
1407:            }
1408:
1409:            private boolean isExternalStyleSheetRequested() {
1410:                if (isCreateBodyFragment()) {
1411:                    // body-fragments have no header ..
1412:                    return false;
1413:                }
1414:
1415:                // We will add the style-declarations directly to the HTML elements ..
1416:                if (isInlineStylesRequested()) {
1417:                    return false;
1418:                }
1419:
1420:                // Without the ability to create external files, we cannot create external stylesheet.
1421:                if (dataLocation == null) {
1422:                    return false;
1423:                }
1424:
1425:                final boolean externalStyle = "true".equals(configuration
1426:                        .getConfigProperty(HtmlTableModule.EXTERNALIZE_STYLE,
1427:                                "true"));
1428:                // User explicitly requested internal styles by disabeling the external-style property.
1429:                return externalStyle;
1430:
1431:            }
1432:
1433:            public static StyleBuilder produceTextStyle(
1434:                    StyleBuilder styleBuilder, final RenderBox box,
1435:                    final boolean includeBorder,
1436:                    final boolean includeWhitespaceCollapse) {
1437:                if (styleBuilder == null) {
1438:                    styleBuilder = new StyleBuilder();
1439:                }
1440:
1441:                final StyleSheet styleSheet = box.getStyleSheet();
1442:                final Color textColor = (Color) styleSheet
1443:                        .getStyleProperty(ElementStyleKeys.PAINT);
1444:                final Color backgroundColor = (Color) styleSheet
1445:                        .getStyleProperty(ElementStyleKeys.BACKGROUND_COLOR);
1446:
1447:                styleBuilder.clear();
1448:                if (includeBorder) {
1449:                    if (backgroundColor != null) {
1450:                        styleBuilder.append("background-color", HtmlColors
1451:                                .getColorString(backgroundColor));
1452:                    }
1453:
1454:                    final BoxDefinition boxDefinition = box.getBoxDefinition();
1455:                    final Border border = boxDefinition.getBorder();
1456:                    final BorderEdge top = border.getTop();
1457:                    if (top != null) {
1458:                        styleBuilder.append("border-top", styleBuilder
1459:                                .printEdgeAsCSS(top));
1460:                    }
1461:                    final BorderEdge left = border.getLeft();
1462:                    if (left != null) {
1463:                        styleBuilder.append("border-left", styleBuilder
1464:                                .printEdgeAsCSS(left));
1465:                    }
1466:                    final BorderEdge bottom = border.getBottom();
1467:                    if (bottom != null) {
1468:                        styleBuilder.append("border-bottom", styleBuilder
1469:                                .printEdgeAsCSS(bottom));
1470:                    }
1471:                    final BorderEdge right = border.getRight();
1472:                    if (right != null) {
1473:                        styleBuilder.append("border-right", styleBuilder
1474:                                .printEdgeAsCSS(right));
1475:                    }
1476:
1477:                    final long paddingTop = boxDefinition.getPaddingTop();
1478:                    final long paddingLeft = boxDefinition.getPaddingLeft();
1479:                    final long paddingBottom = boxDefinition.getPaddingBottom();
1480:                    final long paddingRight = boxDefinition.getPaddingRight();
1481:                    if (paddingTop > 0) {
1482:                        styleBuilder.append("padding-top", String
1483:                                .valueOf(StrictGeomUtility
1484:                                        .toExternalValue(paddingTop)), "pt");
1485:                    }
1486:                    if (paddingLeft > 0) {
1487:                        styleBuilder.append("padding-left", String
1488:                                .valueOf(StrictGeomUtility
1489:                                        .toExternalValue(paddingLeft)), "pt");
1490:                    }
1491:                    if (paddingBottom > 0) {
1492:                        styleBuilder.append("padding-bottom", String
1493:                                .valueOf(StrictGeomUtility
1494:                                        .toExternalValue(paddingBottom)), "pt");
1495:                    }
1496:                    if (paddingRight > 0) {
1497:                        styleBuilder.append("padding-right", String
1498:                                .valueOf(StrictGeomUtility
1499:                                        .toExternalValue(paddingRight)), "pt");
1500:                    }
1501:                }
1502:                if (textColor != null) {
1503:                    styleBuilder.append("color", HtmlColors
1504:                            .getColorString(textColor));
1505:                }
1506:                styleBuilder.append("font-family", box
1507:                        .getStaticBoxLayoutProperties().getFontFamily());
1508:                styleBuilder.append("font-size", String.valueOf(styleSheet
1509:                        .getDoubleStyleProperty(TextStyleKeys.FONTSIZE, 0)),
1510:                        "pt");
1511:                if (styleSheet.getBooleanStyleProperty(TextStyleKeys.BOLD)) {
1512:                    styleBuilder.append("font-weight", "bold");
1513:                } else {
1514:                    styleBuilder.append("font-weight", "normal");
1515:                }
1516:
1517:                if (styleSheet.getBooleanStyleProperty(TextStyleKeys.ITALIC)) {
1518:                    styleBuilder.append("font-style", "italic");
1519:                } else {
1520:                    styleBuilder.append("font-style", "normal");
1521:                }
1522:
1523:                final boolean underlined = styleSheet
1524:                        .getBooleanStyleProperty(TextStyleKeys.UNDERLINED);
1525:                final boolean strikeThrough = styleSheet
1526:                        .getBooleanStyleProperty(TextStyleKeys.STRIKETHROUGH);
1527:                if (underlined && strikeThrough) {
1528:                    styleBuilder.append("text-decoration",
1529:                            "underline line-through");
1530:                } else if (strikeThrough) {
1531:                    styleBuilder.append("text-decoration", "line-through");
1532:                }
1533:                if (underlined) {
1534:                    styleBuilder.append("text-decoration", "underline");
1535:                } else {
1536:                    styleBuilder.append("text-decoration", "none");
1537:                }
1538:
1539:                final ElementAlignment align = (ElementAlignment) styleSheet
1540:                        .getStyleProperty(ElementStyleKeys.ALIGNMENT);
1541:                styleBuilder.append("text-align",
1542:                        translateHorizontalAlignment(align));
1543:
1544:                final double wordSpacing = styleSheet.getDoubleStyleProperty(
1545:                        TextStyleKeys.WORD_SPACING, 0);
1546:                styleBuilder.append("word-spacing", styleBuilder
1547:                        .getPointConverter().format(wordSpacing), "pt");
1548:
1549:                final double minLetterSpacing = styleSheet
1550:                        .getDoubleStyleProperty(
1551:                                TextStyleKeys.X_MIN_LETTER_SPACING, 0);
1552:                final double maxLetterSpacing = styleSheet
1553:                        .getDoubleStyleProperty(
1554:                                TextStyleKeys.X_MAX_LETTER_SPACING, 0);
1555:                styleBuilder.append("letter-spacing", styleBuilder
1556:                        .getPointConverter().format(
1557:                                Math.min(minLetterSpacing, maxLetterSpacing)),
1558:                        "pt");
1559:
1560:                //    if (includeWhitespaceCollapse)
1561:                //    {
1562:                //      final WhitespaceCollapse wsCollapse = (WhitespaceCollapse)
1563:                //          styleSheet.getStyleProperty(TextStyleKeys.WHITE_SPACE_COLLAPSE);
1564:                //      if (WhitespaceCollapse.PRESERVE.equals(wsCollapse))
1565:                //      {
1566:                //        styleBuilder.append("white-space", "pre");
1567:                //      }
1568:                //      else if (WhitespaceCollapse.PRESERVE_BREAKS.equals(wsCollapse))
1569:                //      {
1570:                //        styleBuilder.append("white-space", "nowrap");
1571:                //      }
1572:                //      else
1573:                //      {
1574:                //        styleBuilder.append("white-space", "normal");
1575:                //      }
1576:                //    }
1577:
1578:                return styleBuilder;
1579:            }
1580:
1581:            /**
1582:             * Translates the JFreeReport horizontal element alignment into a HTML alignment constant.
1583:             *
1584:             * @param ea the element alignment
1585:             * @return the translated alignment name.
1586:             */
1587:            public static String translateHorizontalAlignment(
1588:                    final ElementAlignment ea) {
1589:                if (ea == ElementAlignment.RIGHT) {
1590:                    return "right";
1591:                }
1592:                if (ea == ElementAlignment.CENTER) {
1593:                    return "center";
1594:                }
1595:                return "left";
1596:            }
1597:
1598:            public void registerFailure(final ResourceKey source) {
1599:                knownResources.put(source, Boolean.FALSE);
1600:            }
1601:
1602:            public void registerContent(final ResourceKey source,
1603:                    final String name) {
1604:                knownResources.put(source, name);
1605:            }
1606:
1607:            public boolean isRegistered(final ResourceKey source) {
1608:                return knownResources.containsKey(source);
1609:            }
1610:
1611:            public String getRegisteredName(final ResourceKey source) {
1612:                final Object o = knownResources.get(source);
1613:                if (o instanceof  String) {
1614:                    return (String) o;
1615:                }
1616:                return null;
1617:            }
1618:        }
ww_w._j__a_v__a_2_s_.___c___o___m__ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.