package org.krakenapps.docxcod; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.util.Map; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MagicNodeUnwrapper implements OOXMLProcessor { private Logger logger = LoggerFactory.getLogger(getClass().getName()); private static Pattern MAGICNODE_PTRN_DRCTV = Pattern.compile("<KMagicNode><!\\[CDATA\\[(#(.*)|\\/#(.*)|@(.*))\\]\\]><\\/KMagicNode>"); private static Pattern MAGICNODE_PTRN_EXPR = Pattern.compile("<KMagicNode><!\\[CDATA\\[(.*)\\]\\]><\\/KMagicNode>"); @Override public void process(OOXMLPackage pkg, Map<String, Object> rootMap) { /* * augmented directive is processed with standard XML API. Because * Freemarker directive is not legal XML element, contents of augmented * directive should be wrapped to legal XML element, "KMagicNode", in * extractMergeField method. * * In this method, all KMagicNode element will be translated into * Freemarker directive without XML API. */ BufferedInputStream bis = null; BufferedOutputStream bos = null; FileInputStream fis = null; try { File docXml = new File(pkg.getDataDir(), "word/document.xml"); File newDocXml = new File(docXml + ".new"); fis = new FileInputStream(docXml); String xmlString = new Scanner(fis, "UTF-8").useDelimiter("\\A").next(); fis.close(); Matcher matcher = MAGICNODE_PTRN_DRCTV.matcher(xmlString); xmlString = matcher.replaceAll("<$1>"); matcher = MAGICNODE_PTRN_EXPR.matcher(xmlString); xmlString = matcher.replaceAll("$1"); InputStream in = new ByteArrayInputStream(xmlString.getBytes("UTF-8")); FileOutputStream fos = new FileOutputStream(newDocXml); bis = new BufferedInputStream(in); bos = new BufferedOutputStream(fos); int len = 0; byte[] buf = new byte[1024]; while ((len = bis.read(buf, 0, 1024)) != -1) { bos.write(buf, 0, len); } bis.close(); bos.close(); bis = null; bos = null; logger.trace("unwrapMagicNode: rename {} to {}", newDocXml, docXml); boolean deleteResult = docXml.delete(); if (deleteResult) { logger.trace("unwrapMagicNode: deleting old file success: {}", docXml); newDocXml.renameTo(docXml); } else { logger.error("unwrapMagicNode: deleting old file failed: {}", docXml); } } catch (Exception e) { logger.warn("Exception in unwrapMagicNode", e); } finally { safeClose(fis); safeClose(bis); safeClose(bos); } } private void safeClose(Closeable f) { if (f == null) return; try { f.close(); } catch (Exception e) { // ignore } } }