package org.jboss.seam.pdf.ui; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import javax.faces.component.UIComponent; import javax.faces.component.ValueHolder; import javax.faces.context.FacesContext; import org.jboss.seam.core.Manager; import org.jboss.seam.document.ByteArrayDocumentData; import org.jboss.seam.document.DocumentData; import org.jboss.seam.document.DocumentStore; import org.jboss.seam.document.DocumentData.DocumentType; import org.jboss.seam.navigation.Pages; import org.jboss.seam.pdf.ITextUtils; import com.lowagie.text.DocWriter; import com.lowagie.text.Document; import com.lowagie.text.DocumentException; import com.lowagie.text.Element; import com.lowagie.text.Rectangle; import com.lowagie.text.html.HtmlWriter; import com.lowagie.text.pdf.PdfContentByte; import com.lowagie.text.pdf.PdfTemplate; import com.lowagie.text.pdf.PdfWriter; import com.lowagie.text.rtf.RtfWriter2; public class UIDocument extends ITextComponent { public static final String COMPONENT_TYPE = "org.jboss.seam.pdf.ui.UIDocument"; public static DocumentType PDF = new DocumentType("pdf", "application/pdf"); public static DocumentType RTF = new DocumentType("rtf", "text/rtf"); public static DocumentType HTML = new DocumentType("html", "text/html"); DocWriter writer; Document document; ByteArrayOutputStream stream; DocumentType documentType; String type; String title; String subject; String keywords; String author; String creator; String orientation; String pageSize; String margins; Boolean marginMirroring; String disposition; String fileName; boolean sendRedirect = true; UISignature signatureField; public void setDisposition(String disposition) { this.disposition = disposition; } public void setFileName(String fileName) { this.fileName = fileName; } public void setType(String type) { this.type = type; } public void setMargins(String margins) { this.margins = margins; } public void setPageSize(String pageSize) { this.pageSize = pageSize; } public void setMarginMirroring(Boolean marginMirroring) { this.marginMirroring = marginMirroring; } public void setAuthor(String author) { this.author = author; } public void setCreator(String creator) { this.creator = creator; } public void setKeywords(String keywords) { this.keywords = keywords; } public void setSubject(String subject) { this.subject = subject; } public void setTitle(String title) { this.title = title; } public void setOrientation(String orientation) { this.orientation = orientation; } public void setSendRedirect(boolean sendRedirect) { this.sendRedirect = sendRedirect; } public boolean getSendRedirect() { return sendRedirect; } @Override public Object getITextObject() { return document; } @Override public void createITextObject(FacesContext context) { type = (String) valueBinding(context, "type", type); documentType = documentTypeForName(type); document = new Document(); // most of this needs to be done BEFORE document.open(); pageSize = (String) valueBinding(context, "pageSize", pageSize); if (pageSize != null) { document.setPageSize(ITextUtils.pageSizeValue(pageSize)); } orientation = (String) valueBinding(context, "orientation", orientation); if (orientation != null) { if (orientation.equalsIgnoreCase("portrait")) { // do nothing } else if (orientation.equalsIgnoreCase("landscape")) { Rectangle currentSize = document.getPageSize(); document.setPageSize(new Rectangle(currentSize.getHeight(), currentSize.getWidth())); } else { throw new RuntimeException("orientation value " + orientation + "unknown"); } } margins = (String) valueBinding(context, "margins", margins); if (margins != null) { float[] vals = ITextUtils.stringToFloatArray(margins); if (vals.length != 4) { throw new RuntimeException("margins must contain 4 float values"); } document.setMargins(vals[0], vals[1], vals[2], vals[3]); } marginMirroring = (Boolean) valueBinding(context, "marginMirroring", marginMirroring); if (marginMirroring != null) { document.setMarginMirroring(marginMirroring); } } protected void initMetaData(FacesContext context) { title = (String) valueBinding(context, "title", title); if (title != null) { document.addTitle(title); } subject = (String) valueBinding(context, "subject", subject); if (subject != null) { document.addSubject(subject); } keywords = (String) valueBinding(context, "keywords", keywords); if (keywords != null) { document.addKeywords(keywords); } author = (String) valueBinding(context, "author", author); if (author != null) { document.addAuthor(author); } creator = (String) valueBinding(context, "creator", creator); if (creator != null) { document.addCreator(creator); } } @Override public void removeITextObject() { document = null; } @Override public void handleAdd(Object o) { if (o instanceof Element) { try { document.add((Element) o); } catch (DocumentException e) { throw new RuntimeException(e); } } else { throw new IllegalArgumentException("cannot add " + o); } } public void addSignature(UISignature signatureField) { this.signatureField = signatureField; } @Override public void encodeBegin(FacesContext context) throws IOException { super.encodeBegin(context); stream = new ByteArrayOutputStream(); try { writer = createWriterForStream(stream); initMetaData(context); processHeaders(); document.open(); } catch (DocumentException e) { throw new RuntimeException(e); } } protected void processHeaders() { UIComponent facet = getFacet("header"); if (facet == null) { return; } try { encode(FacesContext.getCurrentInstance(), facet); } catch (Exception e) { throw new RuntimeException(e); } } @Override public void encodeEnd(FacesContext context) throws IOException { document.resetHeader(); document.resetFooter(); document.close(); byte[] bytes = stream.toByteArray(); if (signatureField != null) { bytes = signatureField.sign(bytes); } String viewId = Pages.getViewId(context); String baseName = Pages.getCurrentBaseName(); DocumentData documentData = new ByteArrayDocumentData(baseName, documentType, bytes); String dispositionValue = (String) valueBinding(context, "disposition", disposition); if (dispositionValue != null) { documentData.setDisposition(dispositionValue); } String fileNameValue = (String) valueBinding(context, "fileName", fileName); if (fileNameValue != null) { documentData.setFilename(fileNameValue); } if (sendRedirect) { DocumentStore store = DocumentStore.instance(); String id = store.newId(); String url = store.preferredUrlForContent(baseName, documentType.getExtension(), id); url = Manager.instance().encodeConversationId(url, viewId); store.saveData(id, documentData); removeITextObject(); context.getExternalContext().redirect(url); } else { UIComponent parent = getParent(); if (parent instanceof ValueHolder) { ValueHolder holder = (ValueHolder) parent; holder.setValue(documentData); } } } public DocWriter getWriter() { return writer; } public PdfContentByte getPdfContent() { PdfWriter writer = (PdfWriter) getWriter(); return writer.getDirectContent(); } public PdfTemplate createPdfTemplate(float width, float height) { return getPdfContent().createTemplate(width, height); } private DocumentType documentTypeForName(String typeName) { if (typeName != null) { if (typeName.equalsIgnoreCase("pdf")) { return PDF; } else if (typeName.equalsIgnoreCase("rtf")) { return RTF; } else if (typeName.equalsIgnoreCase("html")) { return HTML; } } return PDF; } protected DocWriter createWriterForStream(OutputStream stream) throws DocumentException { if (documentType == PDF) { return PdfWriter.getInstance(document, stream); } else if (documentType == RTF) { return RtfWriter2.getInstance(document, stream); } else if (documentType == HTML) { return HtmlWriter.getInstance(document, stream); } throw new IllegalArgumentException("unknown document type"); } }