import java.awt.Color; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Enumeration; import java.util.Hashtable; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.lowagie.text.pdf.BaseFont; import com.lowagie.text.pdf.PdfContentByte; import com.lowagie.text.pdf.PdfGState; import com.lowagie.text.pdf.PdfReader; import com.lowagie.text.pdf.PdfStamper; import com.lowagie.text.pdf.PdfWriter; import com.zeus.ZXTMServlet.ZXTMHttpServletResponse; public class PdfWatermark extends HttpServlet { private static final long serialVersionUID = 1L; Hashtable defaults = new Hashtable(); public void init(ServletConfig config) throws ServletException { super.init(config); // Initialize defaults. These are 'commands' that are run before any commands // passed in to the extension through the args list defaults.put("x", "30"); defaults.put("y", "30"); defaults.put("textAngle", "auto"); defaults.put("textAlign", "L"); defaults.put("textAlpha", "75"); defaults.put("textSize", "20"); defaults.put("textColor", "0xAAAAAA"); // Read any values defined in the ZXTM configuration for this class // to override the defaults Enumeration e = defaults.keys(); while (e.hasMoreElements()) { String k = e.nextElement(); String v = config.getInitParameter(k); if (v != null) defaults.put(k, v); } } public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { try { ZXTMHttpServletResponse zres = (ZXTMHttpServletResponse) res; String ct = zres.getHeader("Content-Type"); if (ct == null || !ct.startsWith("application/pdf")) return; // process args String[] args = (String[]) req.getAttribute("args"); if (args == null) throw new Exception("Missing argument list"); if (args.length % 2 != 0) throw new Exception( "Malformed argument list (expected even number of args)"); ArrayList actions = new ArrayList(); Enumeration e = defaults.keys(); while (e.hasMoreElements()) { String k = e.nextElement(); actions.add(new String[] { k, defaults.get(k) }); } for (int i = 0; i < args.length; i += 2) { actions.add(new String[] { args[i], args[i + 1] }); } InputStream is = zres.getInputStream(); OutputStream os = zres.getOutputStream(); PdfReader reader = new PdfReader(is); int n = reader.getNumberOfPages(); PdfStamper stamp = new PdfStamper(reader, os); stamp.setEncryption( PdfWriter.STANDARD_ENCRYPTION_128 | PdfWriter.DO_NOT_ENCRYPT_METADATA, null, null, PdfWriter.ALLOW_PRINTING | PdfWriter.ALLOW_COPY | PdfWriter.ALLOW_FILL_IN | PdfWriter.ALLOW_SCREENREADERS | PdfWriter.ALLOW_DEGRADED_PRINTING); for (int i = 1; i <= n; i++) { PdfContentByte pageContent = stamp.getOverContent(i); com.lowagie.text.Rectangle pageSize = reader .getPageSizeWithRotation(i); watermarkPage(pageContent, actions, pageSize.getWidth(), pageSize.getHeight()); } stamp.close(); } catch (Exception e) { log(req.getRequestURI() + ": " + e.toString()); e.printStackTrace(); } } public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { doGet(req, res); } private void watermarkPage(PdfContentByte pageContent, ArrayList actions, float width, float height) throws Exception { float x = 0; float y = 0; double textAngle = 0; int textAlign = PdfContentByte.ALIGN_CENTER; int fontSize = 14; pageContent.beginText(); for (int i = 0; i < actions.size(); i++) { String action = actions.get(i)[0]; String value = actions.get(i)[1]; if (action.equals("x")) { x = Float.parseFloat(value) / 100 * width; continue; } if (action.equals("y")) { y = Float.parseFloat(value) / 100 * height; continue; } if (action.equals("textColor")) { pageContent.setColorFill(Color.decode(value)); continue; } if (action.equals("textAlpha")) { PdfGState gs1 = new PdfGState(); gs1.setFillOpacity(Float.parseFloat(value) / 100f); pageContent.setGState(gs1); continue; } if (action.equals("textAngle")) { if (value.equals("auto")) { textAngle = (float) Math.atan2(height, width); } else { textAngle = Math.toRadians( Double.parseDouble(value) ); } continue; } if (action.equals("textAlign")) { if (value.equals("L")) textAlign = PdfContentByte.ALIGN_LEFT; else if (value.equals("R")) textAlign = PdfContentByte.ALIGN_RIGHT; else textAlign = PdfContentByte.ALIGN_CENTER; continue; } if (action.equals("textSize")) { fontSize = Integer.parseInt(value); pageContent.setFontAndSize(BaseFont .createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED), fontSize); continue; } // x,y is top left/center/right of text, so that when we move the // cursor at the end of a line, we can cater for subsequent fontSize // changes if (action.equals("drawText")) { pageContent.showTextAligned(textAlign, value, (float) (x + fontSize * Math.sin(textAngle)), (float) (y - fontSize * Math.cos(textAngle)), (float) Math.toDegrees(textAngle)); x += fontSize * 1.2 * Math.sin(textAngle); y -= fontSize * 1.2 * Math.cos(textAngle); continue; } throw new Exception("Unknown command '" + action + "'"); } pageContent.endText(); } }