aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils
diff options
context:
space:
mode:
Diffstat (limited to 'pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils')
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/ConfigUtils.java318
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/DataHashUtils.java156
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/OgnlUtil.java209
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java92
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PdfAUtil.java66
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/StreamUtils.java66
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/TempDirHelper.java377
7 files changed, 1284 insertions, 0 deletions
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/ConfigUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/ConfigUtils.java
new file mode 100644
index 0000000..bbc64b1
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/ConfigUtils.java
@@ -0,0 +1,318 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.utils;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.SystemUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.log4j.PropertyConfigurator;
+
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.api.exceptions.ConfigUtilsException;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.pdf.Utils;
+
+/**
+ * @author <a href="mailto:thomas.knall@egiz.gv.at">Thomas Knall</a>
+ */
+public final class ConfigUtils {
+
+ private ConfigUtils() {
+ }
+
+ /**
+ * The log.
+ */
+ private static final Log logger_ = LogFactory.getLog(ConfigUtils.class);
+
+ /**
+ * Deploys the default configuration with apache commons vfs.
+ *
+ * @param destination The destination folder.
+ * @param overwriteExisting If set <code>true</code> an already existing configuration is overwritten. If <code>false</code> nothing is being copied if the destination folder already exists.
+ * @return <code>true</code> if the configuration has been deployed, <code>false</code> if not.
+ * @throws ConfigUtilsException Thrown if there was an error during the deployment of the configuration.
+ */
+ /*
+ private static boolean deployWithCommonsVFS(String destination, boolean overwriteExisting) throws ConfigUtilsException {
+ try {
+ FileSystemManager fsManager = VFS.getManager();
+ FileObject defaultConfigurationFile = fsManager.resolveFile("res:DefaultConfiguration");
+ FileObject destinationFile = fsManager.resolveFile(destination);
+
+ if (destinationFile.exists() && !overwriteExisting) {
+ return false;
+ }
+
+ destinationFile.copyFrom(defaultConfigurationFile, new AllFileSelector());
+ return true;
+ } catch (FileSystemException e) {
+ throw new ConfigUtilsException(e);
+ }
+ }
+ */
+
+
+ /**
+ * Deploys the default configuration from an included zip file.
+ *
+ * @param destination The destination folder.
+ * @param overwriteExisting If set <code>true</code> an already existing configuration is overwritten. If <code>false</code> nothing is being copied if the destination folder already exists.
+ * @return <code>true</code> if the configuration has been deployed, <code>false</code> if not.
+ * @throws ConfigUtilsException Thrown if there was an error during the deployment of the configuration.
+ */
+ private static boolean deployFromZIP(String destination, boolean overwriteExisting) throws ConfigUtilsException {
+ try {
+ if (!overwriteExisting) {
+ if (configurationAlreadyExists(destination)) {
+ logger_.debug("There is at least one file or folder that would be overwritten at destination path \"" + destination + "\". Skipping extraction.");
+ return false;
+ }
+ }
+ InputStream in = ConfigUtils.class.getClassLoader().getResourceAsStream(Constants.DEFAULT_CONFIGURATION_ZIP_RESOURCE);
+ if (in == null) {
+ throw new ConfigUtilsException("Unable to find default configuration resource \"" + Constants.DEFAULT_CONFIGURATION_ZIP_RESOURCE + "\".");
+ }
+ return deployFromZIP(in, destination, overwriteExisting);
+ } catch (IOException e) {
+ throw new ConfigUtilsException(e);
+ }
+ }
+
+ /**
+ * Deploys the contents of a ZIP file to a certain location.
+ *
+ * @param inputStream The inputStream of a ZIP container.
+ * @param destination The destination folder.
+ * @param overwriteExisting If set <code>true</code> an already existing configuration is overwritten. If <code>false</code> nothing is being copied if the destination folder already exists.
+ * @return <code>true</code> if the configuration has been deployed, <code>false</code> if not.
+ * @throws ConfigUtilsException Thrown if there was an error during the deployment of the configuration.
+ */
+ public static boolean deployFromZIP(InputStream inputStream, String destination, boolean overwriteExisting) throws ConfigUtilsException {
+ try {
+ if (!overwriteExisting) {
+ if (configurationAlreadyExists(destination)) {
+ logger_.debug("There is at least one file or folder that would be overwritten at destination path \"" + destination + "\". Skipping extraction.");
+ return false;
+ }
+ }
+ if (inputStream == null) {
+ throw new ConfigUtilsException("Unable to deploy ZIP file. InputStream is null.");
+ }
+ ZipInputStream zis = new ZipInputStream(inputStream);
+ ZipEntry ze;
+ File destinationFolder = new File(destination);
+ destinationFolder.mkdirs();
+ logger_.debug("Extracting ZIP contents to folder \"" + destinationFolder.getCanonicalPath() + "\".");
+ while ((ze = zis.getNextEntry()) != null) {
+ if (ze.isDirectory()) {
+ File newFolder = new File(destinationFolder, ze.getName());
+ logger_.debug("Extracting folder \"" + newFolder.getPath() + "\".");
+ newFolder.mkdirs();
+ } else {
+ File destFile = new File(destinationFolder, ze.getName());
+ logger_.trace("Extracting file \"" + destFile.getName() + "\".");
+ PDFASUtils.toFile(zis, destFile);
+ }
+ zis.closeEntry();
+ }
+ zis.close();
+ return true;
+ } catch (IOException e) {
+ throw new ConfigUtilsException(e);
+ }
+ }
+
+ private static boolean configurationAlreadyExists(String destination) throws ConfigUtilsException, IOException {
+ logger_.debug("Checking configuration \"" + destination + "\" already exists (resp. if there are any directories or files that would be overwritten).");
+ File destinationFolder = new File(destination);
+ if (destinationFolder == null || !destinationFolder.exists()) {
+ return false;
+ }
+ InputStream in = ConfigUtils.class.getClassLoader().getResourceAsStream(Constants.DEFAULT_CONFIGURATION_ZIP_RESOURCE);
+ if (in == null) {
+ throw new ConfigUtilsException("Unable to find default configuration resource \"" + Constants.DEFAULT_CONFIGURATION_ZIP_RESOURCE + "\".");
+ }
+ ZipInputStream zis = new ZipInputStream(in);
+ ZipEntry ze;
+ while ((ze = zis.getNextEntry()) != null) {
+ if (ze.isDirectory()) {
+ File newFolder = new File(destinationFolder, ze.getName());
+ logger_.debug("Checking if folder \"" + newFolder.getPath() + "\" already exists.");
+ if (newFolder.exists()) {
+ logger_.debug("YES !");
+ return true;
+ } else {
+ logger_.debug("no");
+ }
+ } else {
+ File destFile = new File(destinationFolder, ze.getName());
+ logger_.trace("Checking if file \"" + destFile.getName() + "\" already exists.");
+ if (destFile.exists()) {
+ logger_.trace("YES !");
+ return true;
+ } else {
+ logger_.trace("no");
+ }
+ }
+ zis.closeEntry();
+ }
+ zis.close();
+ return false;
+ }
+
+ /**
+ * Deploys the default configuration to the given destination folder.
+ *
+ * @param destination The destination folder.
+ * @param overwriteExisting If set <code>true</code> an already existing configuration is overwritten. If <code>false</code> nothing is being copied if the destination folder already exists.
+ * @return The folder the configuration has been extracted to or <code>null</code> if the configuration has NOT been deployed.
+ * @throws ConfigUtilsException Thrown if there was an error during the deployment of the configuration.
+ */
+ public static String deployDefaultConfiguration(String destination, boolean overwriteExisting) throws ConfigUtilsException {
+ if (destination == null) {
+ throw new NullPointerException("Destination must not be null.");
+ }
+ if (destination.length() == 0) {
+ throw new IllegalArgumentException("Destination must not be empty.");
+ }
+ return deployFromZIP(destination, overwriteExisting) ? destination : null;
+ }
+
+ /**
+ * Deploys the default configuration to the user's home directory to the subdirectory specified by
+ * <code>Constants.Constants.USERHOME_CONFIG_FOLDER</code>.
+ *
+ * @param overwriteExisting If set <code>true</code> an already existing configuration is overwritten. If <code>false</code> nothing is being copied if the destination folder already exists.
+ * @return The folder the configuration has been extracted to or <code>null</code> if the configuration has NOT been deployed.
+ * @throws ConfigUtilsException Thrown if there was an error during the deployment of the configuration.
+ * @see Constants#USERHOME_CONFIG_FOLDER
+ */
+ public static String deployDefaultConfiguration(boolean overwriteExisting) throws ConfigUtilsException {
+ String configdir = System.getProperty(Constants.CONFIG_DIR_SYSTEM_PROPERTY);
+ if (configdir == null) {
+ configdir = System.getProperty("user.home");
+ if (configdir != null) {
+ configdir = configdir + File.separator + Constants.USERHOME_CONFIG_FOLDER;
+ }
+ }
+ if (configdir == null || configdir.length() == 0) {
+ return null;
+ }
+ return deployDefaultConfiguration(configdir, overwriteExisting);
+ }
+
+ /**
+ * Deploys the default configuration to the user's home directory to the subdirectory specified by
+ * <code>Constants.Constants.USERHOME_CONFIG_FOLDER</code>.
+ *
+ * @return The folder the configuration has been extracted to or <code>null</code> if the configuration has NOT been deployed.
+ * @throws ConfigUtilsException Thrown if there was an error during the deployment of the configuration.
+ * @see Constants#USERHOME_CONFIG_FOLDER
+ */
+ public static String deployDefaultConfiguration() throws ConfigUtilsException {
+ return deployDefaultConfiguration(false);
+ }
+
+ public static void writeInputStreamToOutputStream(InputStream inputStream, OutputStream outputStream) throws IOException {
+ final int bufferSize = 1024;
+ byte[] buffer = new byte[bufferSize];
+ int len = -1;
+ while ((len = inputStream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, len);
+ }
+ outputStream.flush();
+ }
+
+ public static String assertFileSeparator(String path) {
+ if (path == null) {
+ throw new NullPointerException("Path must not be null.");
+ }
+ if (path.endsWith(File.separator) || path.endsWith("/") || path.endsWith("\\")) {
+ return path;
+ } else {
+ return (path + File.separator);
+ }
+ }
+
+ public static void initializeLogger() {
+ String loggerConfiguration = System.getProperty("log4j.configuration");
+ if (loggerConfiguration != null) {
+ logger_.info("No PDF-AS logger configured because a configuration has already been set via system property \"log4j.configuration\" (=\"" + loggerConfiguration + "\").");
+ return;
+ }
+ loggerConfiguration = assertFileSeparator(SettingsReader.CONFIG_PATH) + "log4j.properties";
+ File loggerConfigFile = new File(loggerConfiguration);
+ if (!loggerConfigFile.exists()) {
+ logger_.info("No PDF-AS logger configured because there is no log4j.properties within the pdf-as work dir. Maybe the logger configuration is handled by an outside application (e.g. a web application).");
+ return;
+ }
+ logger_.info("Initializing PDF-AS logger (configuration = \"" + loggerConfiguration + "\").");
+ PropertyConfigurator.configure(loggerConfiguration);
+ }
+
+ public static void printConfigInfo(Log logger) {
+ int length = Utils.max(new int[] { SettingsReader.RESOURCES_PATH.length(), SettingsReader.TMP_PATH.length(), SettingsReader.CONFIG_PATH.length(), SettingsReader.CERT_PATH.length() });
+
+ String separator = StringUtils.repeat("*", length + 25);
+ String infoResources = " resources path = \"" + SettingsReader.RESOURCES_PATH + "\"";
+ String infoConfiguration = " configuration path = \"" + SettingsReader.CONFIG_PATH + "\"";
+ String infoCertStore = " certstore path = \"" + SettingsReader.CERT_PATH + "\"";
+ String infoTempPath = " temporary path = \"" + SettingsReader.TMP_PATH + "\"";
+ String encoding = " file.encoding = \"" + System.getProperty("file.encoding") + "\"";
+
+ if (logger != null) {
+ logger.info(separator);
+ logger.info(infoResources);
+ logger.info(infoConfiguration);
+ logger.info(infoCertStore);
+ logger.info(infoTempPath);
+ logger.info(encoding);
+ logger.info(separator);
+ } else {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(separator).append(SystemUtils.LINE_SEPARATOR);
+ buffer.append(infoResources).append(SystemUtils.LINE_SEPARATOR);
+ buffer.append(infoConfiguration).append(SystemUtils.LINE_SEPARATOR);
+ buffer.append(infoCertStore).append(SystemUtils.LINE_SEPARATOR);
+ buffer.append(infoTempPath).append(SystemUtils.LINE_SEPARATOR);
+ buffer.append(encoding).append(SystemUtils.LINE_SEPARATOR);
+ buffer.append(separator);
+ System.out.println(buffer.toString());
+ }
+ }
+
+ public static void printConfigInfo() {
+ printConfigInfo(null);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/DataHashUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/DataHashUtils.java
new file mode 100644
index 0000000..4b26ada
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/DataHashUtils.java
@@ -0,0 +1,156 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.security.DigestInputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import org.apache.commons.codec.binary.Base64;
+
+import at.knowcenter.wag.egov.egiz.pdf.BinarySignatureHolder;
+import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder;
+import at.knowcenter.wag.egov.egiz.pdf.TextualSignatureHolder;
+
+/**
+ * Contains helpful methods for building data hashed.
+ *
+ * <p>
+ * Data hashes are useful for summarizing the signed data of signatures for
+ * debugging and testing purposes. Do not use these hashes for signatures.
+ * </p>
+ * <p>
+ * A data hash is always a Base64 encoded String.
+ * </p>
+ *
+ * @author wprinz
+ *
+ */
+public final class DataHashUtils
+{
+
+ /**
+ *
+ * @param text
+ * @return
+ */
+ public static String buildDataHash(String text)
+ {
+ try
+ {
+ MessageDigest md = getMessageDigest();
+ // probable performance leak for very large texts
+ md.update(text.getBytes("UTF-8"));
+ byte[] rawDigest = md.digest();
+
+ return encodeDigest(rawDigest);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static String buildDataHash(byte[] data)
+ {
+ MessageDigest md = getMessageDigest();
+ md.update(data);
+ byte[] rawDigest = md.digest();
+
+ return encodeDigest(rawDigest);
+ }
+
+ public static String buildDataHash(InputStream is)
+ {
+ try
+ {
+ MessageDigest md = getMessageDigest();
+
+ DigestInputStream dis = new DigestInputStream(is, md);
+
+ byte[] temp = new byte[1024];
+ int i = 0;
+ while (dis.read(temp) >= 0)
+ {
+ // this just keeps the compiler from optimizing this loop away
+ i++;
+ }
+ dis.close();
+
+ byte[] rawDigest = md.digest();
+
+ return encodeDigest(rawDigest);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static String buildDataHash(SignatureHolder sh)
+ {
+ if (sh instanceof TextualSignatureHolder)
+ {
+ TextualSignatureHolder tsh = (TextualSignatureHolder) sh;
+ String signedText = tsh.getSignedText();
+ return buildDataHash(signedText);
+ }
+
+ {
+ BinarySignatureHolder bsh = (BinarySignatureHolder) sh;
+ InputStream is = bsh.getSignedPdf().createInputStream();
+ return buildDataHash(is);
+ }
+ }
+
+ protected static MessageDigest getMessageDigest()
+ {
+ try
+ {
+ MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
+ return sha1;
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected static String encodeDigest(byte[] rawDigest)
+ {
+ try
+ {
+ byte[] encoded = Base64.encodeBase64(rawDigest);
+ String str = new String(encoded, "US-ASCII");
+ return str;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/OgnlUtil.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/OgnlUtil.java
new file mode 100644
index 0000000..69b30f8
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/OgnlUtil.java
@@ -0,0 +1,209 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.utils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import ognl.Ognl;
+import ognl.OgnlException;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+
+/**
+ * Utility class for ognl evaluation.
+ * <a href="http://www.opensymphony.com/ognl/">ognl website</a>
+ * @author dferbas
+ * @author mhiess
+ *
+ */
+public class OgnlUtil {
+
+ private static final String EXP_END = "}";
+
+ private static final String EXP_START = "${";
+
+ private static final Logger log = Logger.getLogger(OgnlUtil.class);
+
+ private Map context = new HashMap();
+ private Object root = null;
+
+ public OgnlUtil() {
+ this.init(null);
+ }
+
+ public OgnlUtil(Map context) {
+ this.init(context);
+ }
+
+ public OgnlUtil(Object root) {
+ this.root = root;
+ this.init(null);
+ }
+
+ /**
+ * Adds the default utils to the context
+ *
+ * @param context1
+ */
+ private void init(Map context1) {
+ if (context1 != null) {
+ this.context = context1;
+ }
+ }
+
+ private List extractExpressions(String text) {
+
+ List expressions = new ArrayList();
+
+ int indexStart = 0;
+ int indexEnd = 0;
+ String exp;
+
+ while (indexStart != -1) {
+ indexStart = text.indexOf(EXP_START, indexStart);
+ indexEnd = text.indexOf(EXP_END, indexStart);
+
+ if (indexStart != -1 && indexEnd != -1) {
+
+ exp = text.substring(indexStart + 2, indexEnd);
+ log.debug("Found expression in template: " + exp);
+ if (!exp.equals("") && exp != null) {
+ if (!expressions.contains(exp)) {
+ expressions.add(exp);
+ } else {
+ log.debug("Duplicated expression '" + exp + "' found");
+ }
+ }
+
+ indexStart = indexEnd;
+ }
+ }
+
+ return expressions;
+ }
+
+ public boolean containsExpression(String template) {
+ return template != null && StringUtils.contains(template,"${") && StringUtils.contains(template, "}");
+ }
+
+ /**
+ * Compile/evaluate a message with ognl expressions marked with <tt>${expression}</tt>
+ *
+ * @param template
+ * @return
+ */
+ public String compileMessage(String template) {
+
+ if (this.context != null) {
+ String compiledMsg = template;
+ List expressions = this.extractExpressions(template);
+
+ String value;
+ for (Iterator it = expressions.iterator(); it.hasNext();) {
+ String expr = (String) it.next();
+
+ try {
+ if (this.root != null) {
+ value = String.valueOf(Ognl.getValue(expr, this.root));
+ } else {
+ value = String.valueOf(Ognl.getValue(expr, this.context));
+ }
+ log.debug("Found value: '" + value + "' for expression: '" + expr + "'");
+
+ if (value == null) {
+ value = "";
+ log.debug("Set value for expression to: empty string");
+ }
+
+ compiledMsg = StringUtils.replace(compiledMsg, EXP_START + expr + EXP_END, value);
+ } catch (OgnlException e) {
+ log.error(e.getMessage(), e);
+ }
+ }
+ log.debug("Returning compiled message: " + compiledMsg);
+ return compiledMsg;
+ }
+ return null;
+ }
+
+ /**
+ * Evaluate an expression as ognl, returning result as object. No placeholders ${ } allowed.
+ * @param ognlExp
+ * @return
+ */
+ public Object evaluate(String ognlExp) {
+
+ if (this.context != null) {
+
+ Object value = null;
+ try {
+ value = Ognl.getValue(ognlExp, this.context);
+ log.debug("Found value: '" + value + "' for expression: '" + ognlExp + "'");
+
+ } catch (OgnlException e) {
+ log.error(e.getMessage(), e);
+ }
+ return value;
+ } else return null;
+ }
+
+ /**
+ * This method compiles a map of ognl expression to a map with entries
+ *
+ * @param toCompile
+ * @return
+ */
+ public Map compileExpressions(Map toCompile) {
+ if (this.context != null) {
+ Map result = new HashMap();
+
+ for (Iterator it = result.entrySet().iterator(); it.hasNext();) {
+ Entry entry = (Entry) it.next();
+ try {
+ result.put(entry.getKey(), Ognl.getValue(entry.getValue(), this.context));
+ } catch (OgnlException e) {
+ result.put(entry.getKey(), null);
+ log.warn(e.getMessage(), e);
+ }
+ }
+ return result;
+
+ }
+ return null;
+ }
+
+ public Map getContext() {
+ return this.context;
+ }
+
+ public void mergeOgnlContext(OgnlUtil ognlUtil) {
+ this.context.putAll(ognlUtil.getContext());
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java
new file mode 100644
index 0000000..4cd3bd5
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java
@@ -0,0 +1,92 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.utils;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.pdfbox.pdmodel.PDDocument;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
+
+import com.lowagie.text.pdf.PdfReader;
+
+/**
+ * @author tknall
+ */
+public class PDFASUtils {
+//23.11.2010 changed by exthex - added checkDocumentPermissions(PDDocument doc)
+
+ private PDFASUtils() {
+ }
+
+ /**
+ * Verifies that a document could be opened with full permissions.
+ * @param pdfReader The PdfReader
+ * @throws PDFDocumentException Thrown if document has not been opened with full permissions.
+ */
+ public static void checkReaderPermissions(PdfReader pdfReader) throws PDFDocumentException {
+ if (pdfReader.isEncrypted()) {
+ throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is encrypted.");
+ }
+ if (!pdfReader.isOpenedWithFullPermissions()) {
+ throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is protected.");
+ }
+ }
+
+ public static boolean toFile(byte[] data, File file) throws IOException {
+ return PDFASUtils.toFile(new ByteArrayInputStream(data), file);
+ }
+
+ public static boolean toFile(InputStream inputStream, File file) throws IOException {
+ boolean result = false;
+ BufferedOutputStream bufferedOutputStream = null;
+ try {
+ bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
+ ConfigUtils.writeInputStreamToOutputStream(inputStream, bufferedOutputStream);
+ } finally {
+ if (bufferedOutputStream != null) {
+ try {
+ bufferedOutputStream.close();
+ result = true;
+ } catch (IOException e) {
+ result = false;
+ }
+ }
+ }
+ return result;
+ }
+
+ public static void checkDocumentPermissions(PDDocument doc) throws PDFDocumentException {
+ if (doc.isEncrypted()) {
+ throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is encrypted.");
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PdfAUtil.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PdfAUtil.java
new file mode 100644
index 0000000..e741bca
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PdfAUtil.java
@@ -0,0 +1,66 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.utils;
+
+/**
+ * PDF/A utility class
+ * @author dferbas
+ *
+ */
+public class PdfAUtil {
+ /**
+ * dferbas: Text representation of pdfa version string
+ */
+ private static final String PDFA_PREFIX = "ISO 19005-1:2005 PDF/A-";
+ /**
+ * Extract pdfa version from pdf metadata
+ * @param pdfMetadata
+ * @return
+ */
+ public static String findPdfAVersion(String pdfMetadata) {
+
+ String inf = pdfMetadata;
+ String pdfaNsMark = "http://www.aiim.org/pdfa/ns/id/";
+ String partMark = "<pdfaid:part>";
+ String confMark = "<pdfaid:conformance>";
+ int pdfaI = inf.indexOf(pdfaNsMark);
+
+ if (pdfaI > -1) {
+ int part = inf.indexOf(partMark);
+ StringBuffer version = new StringBuffer(PDFA_PREFIX);
+ part = part + partMark.length();
+ version.append(inf.substring(part, part + 1));
+ int conf = inf.indexOf(confMark);
+
+ conf = conf + confMark.length();
+ version.append(inf.substring(conf, conf + 1).toLowerCase());
+
+ return version.toString();
+ } else {
+ return null;
+
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/StreamUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/StreamUtils.java
new file mode 100644
index 0000000..3dce5b1
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/StreamUtils.java
@@ -0,0 +1,66 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class StreamUtils
+{
+
+ public static void writeInputStreamToOutputStream (InputStream is, OutputStream os) throws IOException
+ {
+ byte [] buffer = new byte [2048];
+
+ int read = -1;
+ while ((read = is.read(buffer)) > 0)
+ {
+ os.write(buffer, 0, read);
+ }
+ os.flush();
+ is.close();
+ os.close();
+ }
+
+ // The InputStream should be self- delimited.
+// public static void writeInputStreamToOutputStream(InputStream is, OutputStream os, int length) throws IOException
+// {
+// byte [] buffer = new byte [2048];
+//
+// int bytes_to_write = length;
+//
+// int read = -1;
+// while ((read = is.read(buffer, 0, (bytes_to_write >= buffer.length) ? buffer.length : bytes_to_write)) > 0)
+// {
+// os.write(buffer, 0, read);
+// bytes_to_write -= read;
+// }
+// is.close();
+// os.close();
+//
+// assert bytes_to_write == 0;
+// }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/TempDirHelper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/TempDirHelper.java
new file mode 100644
index 0000000..bccc67b
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/TempDirHelper.java
@@ -0,0 +1,377 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.utils;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.framework.input.DataSource;
+import at.gv.egiz.pdfas.framework.input.PdfDataSource;
+import at.gv.egiz.pdfas.framework.input.TextDataSource;
+import at.gv.egiz.pdfas.framework.output.DataSink;
+import at.gv.egiz.pdfas.impl.input.ByteArrayPdfDataSourceImpl;
+import at.gv.egiz.pdfas.impl.input.FileBased;
+import at.gv.egiz.pdfas.impl.input.FileBasedTextDataSourceImpl;
+import at.gv.egiz.pdfas.impl.input.TextDataSourceImpl;
+import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper;
+import at.gv.egiz.pdfas.impl.output.ByteArrayDataSink;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder;
+import at.knowcenter.wag.egov.egiz.pdf.TextualSignatureHolder;
+
+/**
+ * @author wprinz
+ *
+ */
+public class TempDirHelper
+{
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(TempDirHelper.class);
+
+ protected static long runningIndex = 0;
+
+ /**
+ * Assembles the File of the temporary directory without checking if it really
+ * exists.
+ */
+ public static File assembleTemporaryDirectoryFile()
+ {
+ File temp_dir = new File(SettingsReader.TMP_PATH);
+ return temp_dir;
+ }
+
+ /**
+ * Returns the directory where temporary files should be stored.
+ *
+ * <p>
+ * If the directory doesn't exist, it is created.
+ * </p>
+ *
+ * @return Returns the directory where temporary files should be stored.
+ */
+ public static File getTemporaryDirectory()
+ {
+ File temp_dir = assembleTemporaryDirectoryFile();
+ if (!temp_dir.exists())
+ {
+ temp_dir.mkdirs();
+ }
+ return temp_dir;
+ }
+
+ /**
+ * Deletes all files in the temporary directory, if it exists.
+ *
+ * <p>
+ * This should be used to clear temporary files when the application shuts
+ * down.
+ * </p>
+ */
+ public static void clearTemporaryDirectory()
+ {
+ File temp_dir = assembleTemporaryDirectoryFile();
+ log.debug("Clearing temporary directory: " + temp_dir);
+
+ if (!temp_dir.exists())
+ {
+ return;
+ }
+
+ File[] files = temp_dir.listFiles();
+ for (int i = 0; i < files.length; i++)
+ {
+ // added by tknall: do not try to remove svn-metadata
+ if (files[i].getName().endsWith(".svn")) {
+ continue;
+ }
+ log.debug(" Clearing temporary file: " + files[i]);
+ boolean delete_success = files[i].delete();
+ if (!delete_success)
+ {
+ log.error("Couldn't delete the temporary file: " + files[i]);
+ }
+ }
+ }
+
+ public static void storeTextSignatureHoldersIfApplicable(List shs, String fileNameSuffix) throws IOException
+ {
+ Iterator it = shs.iterator();
+ while (it.hasNext())
+ {
+ SignatureHolder sh = (SignatureHolder) it.next();
+ if (sh instanceof TextualSignatureHolder)
+ {
+ TextualSignatureHolder tsh = (TextualSignatureHolder) sh;
+ if (!(tsh.getDataSource() instanceof FileBased))
+ {
+ TextDataSource tds = (TextDataSource) tsh.getDataSource();
+ if (isReasonableToStore(tds.getText().length()))
+ {
+ TextDataSource fbtds = placeTextIntoTempDir(tds.getText(), fileNameSuffix);
+ tsh.exchangeDataSource(fbtds);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Places the text into the temp dir if reasonable.
+ *
+ * <p>
+ * Reasonable means that the text is longer than a certain threshold.
+ * Otherwise a short text is simply held in memory.
+ * </p>
+ *
+ * @param text
+ * The text to be stored.
+ * @param fileNameSuffix
+ * A file name suffix so that the temp file gets a more "readable"
+ * name.
+ * @return Returns the TextDataSource.
+ * @throws IOException
+ * F.e.
+ */
+ public static TextDataSource placeTextIntoTempDir(String text, String fileNameSuffix) throws IOException
+ {
+ if (isReasonableToStore(text.length()))
+ {
+ String fileName = formatFileName(fileNameSuffix);
+
+ File tmpFile = createTempFileInDir(fileName);
+
+ FileOutputStream fos = new FileOutputStream(tmpFile);
+ OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
+ osw.write(text);
+ osw.close();
+
+ FileBasedTextDataSourceImpl textDataSource = new FileBasedTextDataSourceImpl(tmpFile, "UTF-8");
+ return textDataSource;
+ }
+ else
+ {
+ return new TextDataSourceImpl(text);
+ }
+ }
+
+ /**
+ * Tells, if it is reasonable to store the text of the given length onto the
+ * disk.
+ *
+ * @param textLength
+ * The length of the text under question.
+ * @return Returns true if the text should be stored on the disk.
+ */
+ public static boolean isReasonableToStore(int textLength)
+ {
+ return false;
+// return textLength >= 10000;
+ }
+
+ public static PdfDataSource placePdfIntoTempDir(InputStream pdfInput, String fileNameSuffix) throws IOException
+ {
+ log.debug("PERF: placing pdf into memory cache");
+
+ byte [] pdfData = DataSourceHelper.convertInputStreamToByteArray(pdfInput);
+ PdfDataSource pdfDataSource = new ByteArrayPdfDataSourceImpl(pdfData);
+
+// File pdfFile = placeInputIntoTempDirFile(pdfInput, fileNameSuffix);
+//
+// FileBasedPdfDataSourceImpl pdfDataSource = new FileBasedPdfDataSourceImpl(pdfFile, (int) pdfFile.length());
+ return pdfDataSource;
+ }
+
+ public static File placeInputIntoTempDirFile(InputStream input, String fileNameSuffix) throws IOException
+ {
+ String fileName = formatFileName(fileNameSuffix);
+
+ File tmpFile = createTempFileInDir(fileName);
+
+ FileOutputStream fos = new FileOutputStream(tmpFile);
+
+ byte[] buffer = new byte[2048];
+ int read = -1;
+ while ((read = input.read(buffer)) > 0)
+ {
+ fos.write(buffer, 0, read);
+ }
+ fos.close();
+ input.close();
+
+ return tmpFile;
+ }
+
+ public static File formTempFile(String fileNameSuffix)
+ {
+ String fileName = formatFileName(fileNameSuffix);
+ File tmpFile = getFileInTempDir(fileName);
+
+ return tmpFile;
+ }
+
+ protected static File getFileInTempDir (String fileName)
+ {
+// File tempDir = new File(new File(SettingsReader.RESOURCES_PATH), "pdfastmp");
+ File tempDir = assembleTemporaryDirectoryFile();
+
+ File tmpFile = new File(tempDir, fileName);
+
+ return tmpFile;
+ }
+
+ protected static String formatFileName(String fileNameSuffix)
+ {
+ // double check so that file name is always correct.
+ fileNameSuffix = extractFileNameSuffix(fileNameSuffix);
+ String fileName = "tmp" + formatIndex(runningIndex) + "_" + fileNameSuffix;
+ runningIndex++;
+
+ return fileName;
+ }
+
+ protected static String formatIndex(long index)
+ {
+ NumberFormat nf = new DecimalFormat("00000000");
+
+ return nf.format(index);
+ }
+
+ protected static File createTempFileInDir(String fileName) throws IOException
+ {
+ File tmpFile = getFileInTempDir(fileName);
+
+ tmpFile.createNewFile();
+
+ tmpFile.deleteOnExit();
+
+ return tmpFile;
+ }
+
+ public static DataSink createTempDataSink(String fileNameSuffix) throws IOException
+ {
+ log.debug("PERF: placing pdf into memory cache");
+
+ DataSink ds = new ByteArrayDataSink();
+
+// String fileName = formatFileName(fileNameSuffix);
+//
+// File tmpFile = createTempFileInDir(fileName);
+//
+// FileBasedDataSink ds = new FileBasedDataSink(tmpFile);
+
+ return ds;
+ }
+
+// public static void writeDataSinkToHttpResponse(DataSink ds, HttpServletResponse response) throws IOException
+// {
+//
+// response.setContentType(ds.getMimeType());
+// response.setCharacterEncoding(ds.getCharacterEncoding());
+//
+// OutputStream os = response.getOutputStream();
+//
+// if (ds instanceof FileBasedDataSink)
+// {
+// FileBasedDataSink fbds = (FileBasedDataSink)ds;
+// byte[] buffer = new byte[2048];
+// FileInputStream fis = new FileInputStream(fbds.getFile());
+// int n = -1;
+// while ((n = fis.read(buffer)) > 0)
+// {
+// os.write(buffer, 0, n);
+// }
+// fis.close();
+// }
+// else
+// {
+// ByteArrayDataSink bads = (ByteArrayDataSink)ds;
+// os.write(bads.getByteArray());
+// os.flush();
+//
+// }
+//
+// os.close();
+//}
+
+ /**
+ * Deletes the underlying file of the FileBased DataSource.
+ *
+ * <p>
+ * If the DataSource is not FileBased, nothing is done.
+ * </p>
+ * <p>
+ * This is usually used by the application to delete temporary files.
+ * </p>
+ *
+ * @param dataSource
+ */
+ public static void deleteDataSourceIfFileBased(DataSource dataSource)
+ {
+ if (dataSource instanceof FileBased)
+ {
+ FileBased fb = (FileBased) dataSource;
+ log.debug("Deleting temp file " + fb.getFile());
+ boolean deleted = fb.getFile().delete();
+ log.debug("deleted = " + deleted);
+ }
+ }
+
+ public static void deleteDataSinkIfFileBased(DataSink dataSink)
+ {
+ if (dataSink instanceof FileBased)
+ {
+ FileBased fb = (FileBased) dataSink;
+ log.debug("Deleting temp file " + fb.getFile());
+ boolean deleted = fb.getFile().delete();
+ log.debug("deleted = " + deleted);
+ }
+ }
+
+ /**
+ * Given a file (maybe with path), extracts the file name suffix.
+ * @param file The file and maybe path.
+ * @return Returns the file name.
+ */
+ public static String extractFileNameSuffix (String file)
+ {
+ if (file == null || file.trim().length() == 0)
+ {
+ return "nofilename";
+ }
+ File f = new File(file);
+ return f.getName();
+ }
+}