From c5601292f85bc02ca277c04ef6bbae938d07a335 Mon Sep 17 00:00:00 2001 From: Tobias Kellner Date: Thu, 27 Nov 2014 21:00:57 +0100 Subject: Backup old PDF-AS configuration, create new --- .../main/java/at/asit/pdfover/gui/Constants.java | 9 + .../java/at/asit/pdfover/gui/utils/Zipper.java | 128 ++++++++ .../workflow/states/PrepareConfigurationState.java | 338 ++++++++++++++------- 3 files changed, 357 insertions(+), 118 deletions(-) create mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/utils/Zipper.java (limited to 'pdf-over-gui/src/main/java/at') diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/Constants.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/Constants.java index 060329c9..67d30f01 100644 --- a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/Constants.java +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/Constants.java @@ -59,6 +59,15 @@ public class Constants { /** The default log4j file name */ public static final String DEFAULT_LOG4J_FILENAME = "log4j.properties"; //$NON-NLS-1$ + /** The configuration version file name */ + public static final String CONFIG_VERSION_FILENAME = ".version"; //$NON-NLS-1$ + + /** The minimum PDF-AS configuration version (older ones will be backed up and updated */ + public static final String MIN_PDF_AS_CONFIG_VERSION = "4.1.0"; //$NON-NLS-1$ + + /** The configuration backup filename */ + public static final String PDF_AS_CONFIG_BACKUP_FILENAME = "cfg_backup"; //$NON-NLS-1$ + /** File suffix for the signed document */ public final static String SIGNED_SUFFIX = "_signed"; //$NON-NLS-1$ diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/utils/Zipper.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/utils/Zipper.java new file mode 100644 index 00000000..b3e07d60 --- /dev/null +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/utils/Zipper.java @@ -0,0 +1,128 @@ +/* + * Copyright 2012 by A-SIT, Secure Information Technology Center Austria + * + * 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://joinup.ec.europa.eu/software/page/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. + */ +package at.asit.pdfover.gui.utils; + +// Imports +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Zipper/unzipper to backup/extract configuration + */ +public class Zipper { + /** + * SLF4J Logger instance + **/ + private static final Logger log = LoggerFactory.getLogger(Zipper.class); + + /** + * Compresses the source path to Zip File output stream + * @param sourcePath + * @param os + * @throws IOException + */ + public static void zip(String sourcePath, OutputStream os) throws IOException { + zip(sourcePath, os, false); + } + + /** + * Compresses the source path to Zip File output stream + * @param sourcePath + * @param os + * @param doDelete whether to delete content after compression + * @throws IOException + */ + public static void zip(String sourcePath, OutputStream os, boolean doDelete) throws IOException { + ZipOutputStream zos = new ZipOutputStream(os); + File dir = new File(sourcePath); + zip(dir, dir.toURI(), zos, doDelete); + zos.close(); + } + + private static void zip(File f, URI root, ZipOutputStream zos, boolean doDelete) throws IOException { + if (f.isDirectory()) { + File[] subDirs = f.listFiles(); + for (File subDir : subDirs) { + zip(subDir, root, zos, doDelete); + if (doDelete && !f.toURI().equals(root)) + subDir.delete(); + } + } else { + URI path = root.relativize(f.toURI()); + ZipEntry entry = new ZipEntry(path.toString()); + zos.putNextEntry(entry); + byte[] buffer = new byte[1024]; + int len; + BufferedInputStream is = new BufferedInputStream(new FileInputStream(f)); + while ((len = is.read(buffer)) >= 0) + zos.write(buffer, 0, len); + is.close(); + zos.closeEntry(); + if (doDelete) + f.delete(); + } + } + + /** + * Extracts Zip File input stream to target path + * @param is + * @param targetPath + * @throws IOException + */ + public static void unzip(InputStream is, String targetPath) throws IOException { + ZipInputStream zis = new ZipInputStream(is); + ZipEntry entry; + // while there are entries I process them + while ((entry = zis.getNextEntry()) != null) { + log.debug("entry: " + entry.getName() + ", " //$NON-NLS-1$//$NON-NLS-2$ + + entry.getSize()); + // consume all the data from this entry + + if (entry.isDirectory()) { + log.debug("Extracting directory: " + entry.getName()); //$NON-NLS-1$ + + File nDir = new File(targetPath + File.separator + entry.getName()); + if(!nDir.exists()) { + if(!nDir.mkdir()) { + throw new IOException("Failed to create dir: " + entry.getName()); //$NON-NLS-1$ + } + } + continue; + } + byte[] buffer = new byte[1024]; + int len; + BufferedOutputStream out = new BufferedOutputStream( + new FileOutputStream(targetPath + File.separator + entry.getName())); + while ((len = zis.read(buffer)) >= 0) + out.write(buffer, 0, len); + + out.close(); + } + } +} diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/states/PrepareConfigurationState.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/states/PrepareConfigurationState.java index 70895bfb..3e5e7a2c 100644 --- a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/states/PrepareConfigurationState.java +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/states/PrepareConfigurationState.java @@ -17,12 +17,17 @@ package at.asit.pdfover.gui.workflow.states; //Imports import java.awt.Desktop; +import java.io.BufferedReader; +import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.net.URI; import org.apache.commons.httpclient.HttpClient; @@ -56,14 +61,14 @@ import at.asit.pdfover.gui.controls.Dialog.ICON; import at.asit.pdfover.gui.controls.ErrorDialog; import at.asit.pdfover.gui.exceptions.InitializationException; import at.asit.pdfover.gui.utils.Messages; -import at.asit.pdfover.gui.utils.Unzipper; import at.asit.pdfover.gui.utils.VersionComparator; +import at.asit.pdfover.gui.utils.Zipper; import at.asit.pdfover.gui.workflow.StateMachine; import at.asit.pdfover.signator.Signator; /** * Starting state of workflow proccess - * + * * Reads configuration, command arguments and initializes configured variables */ public class PrepareConfigurationState extends State { @@ -148,128 +153,158 @@ public class PrepareConfigurationState extends State { } } - private void createConfiguration(File configDir) throws InitializationException { - boolean allOK = false; - - log.info("Creating configuration directory"); //$NON-NLS-1$ + private void copyPdfOverConfig() throws InitializationException { + // 1Kb buffer + byte[] buffer = new byte[1024]; + int byteCount = 0; + InputStream inputStream = null; + FileOutputStream pdfOverConfig = null; try { - if (!configDir.exists()) { - configDir.mkdir(); + inputStream = this.getClass().getResourceAsStream( + Constants.RES_PKG_PATH + Constants.DEFAULT_CONFIG_FILENAME); + pdfOverConfig = new FileOutputStream( + getStateMachine().getConfigProvider().getConfigurationDirectory() + + FILE_SEPARATOR + Constants.DEFAULT_CONFIG_FILENAME); + + while ((byteCount = inputStream.read(buffer)) >= 0) { + pdfOverConfig.write(buffer, 0, byteCount); } - // Copy PDFOver config to config Dir - - // 1Kb buffer - byte[] buffer = new byte[1024]; - int byteCount = 0; - - InputStream inputStream = null; - FileOutputStream pdfOverConfig = null; - try { - inputStream = this.getClass().getResourceAsStream( - Constants.RES_PKG_PATH + Constants.DEFAULT_CONFIG_FILENAME); - pdfOverConfig = new FileOutputStream( - getStateMachine().getConfigProvider().getConfigurationDirectory() + - FILE_SEPARATOR + Constants.DEFAULT_CONFIG_FILENAME); - - while ((byteCount = inputStream.read(buffer)) >= 0) { - pdfOverConfig.write(buffer, 0, byteCount); - } - } catch (Exception e) { - log.error( - "Failed to write PDF Over config file to config directory", e); //$NON-NLS-1$ - throw new InitializationException( - "Failed to write PDF Over config file to config directory", //$NON-NLS-1$ - e); - } finally { - if (pdfOverConfig != null) { - try { - pdfOverConfig.close(); - } catch (IOException e) { - log.warn( - "Failed to close File stream for PDFOver config", e); //$NON-NLS-1$ - } + } catch (Exception e) { + log.error( + "Failed to write PDF Over config file to config directory", e); //$NON-NLS-1$ + throw new InitializationException( + "Failed to write PDF Over config file to config directory", //$NON-NLS-1$ + e); + } finally { + if (pdfOverConfig != null) { + try { + pdfOverConfig.close(); + } catch (IOException e) { + log.warn( + "Failed to close File stream for PDFOver config", e); //$NON-NLS-1$ } + } - if (inputStream != null) { - try { - inputStream.close(); - } catch (IOException e) { - log.warn( - "Failed to close Resource stream for PDFOver config", e); //$NON-NLS-1$ - } + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + log.warn( + "Failed to close Resource stream for PDFOver config", e); //$NON-NLS-1$ } } + } + } - inputStream = null; - pdfOverConfig = null; - try { - inputStream = this.getClass().getResourceAsStream( - Constants.RES_PKG_PATH + Constants.DEFAULT_LOG4J_FILENAME); - String filename = getStateMachine().getConfigProvider().getConfigurationDirectory() - + FILE_SEPARATOR + Constants.DEFAULT_LOG4J_FILENAME; - pdfOverConfig = new FileOutputStream(filename); - - while ((byteCount = inputStream.read(buffer)) >= 0) { - pdfOverConfig.write(buffer, 0, byteCount); - } + private void copyLog4jConfig() throws InitializationException { + // 1Kb buffer + byte[] buffer = new byte[1024]; + int byteCount = 0; - PropertyConfigurator.configureAndWatch(filename); - } catch (Exception e) { - log.error( - "Failed to write log4j config file to config directory", e); //$NON-NLS-1$ - throw new InitializationException( - "Failed to write log4j config file to config directory", //$NON-NLS-1$ - e); - } finally { - if (pdfOverConfig != null) { - try { - pdfOverConfig.close(); - } catch (IOException e) { - log.warn( - "Failed to close File stream for log4j config", e); //$NON-NLS-1$ - } + InputStream inputStream = null; + FileOutputStream pdfOverConfig = null; + try { + inputStream = this.getClass().getResourceAsStream( + Constants.RES_PKG_PATH + Constants.DEFAULT_LOG4J_FILENAME); + String filename = getStateMachine().getConfigProvider().getConfigurationDirectory() + + FILE_SEPARATOR + Constants.DEFAULT_LOG4J_FILENAME; + pdfOverConfig = new FileOutputStream(filename); + + while ((byteCount = inputStream.read(buffer)) >= 0) { + pdfOverConfig.write(buffer, 0, byteCount); + } + + PropertyConfigurator.configureAndWatch(filename); + } catch (Exception e) { + log.error( + "Failed to write log4j config file to config directory", e); //$NON-NLS-1$ + throw new InitializationException( + "Failed to write log4j config file to config directory", //$NON-NLS-1$ + e); + } finally { + if (pdfOverConfig != null) { + try { + pdfOverConfig.close(); + } catch (IOException e) { + log.warn( + "Failed to close File stream for log4j config", e); //$NON-NLS-1$ } - - if (inputStream != null) { - try { - inputStream.close(); - } catch (IOException e) { - log.warn( - "Failed to close Resource stream for log4j config", e); //$NON-NLS-1$ - } + } + + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + log.warn( + "Failed to close Resource stream for log4j config", e); //$NON-NLS-1$ } } - - InputStream is = this.getClass().getResourceAsStream( - Constants.RES_CFG_ZIP); + } + } + + private void unzipPdfAsConfig(File configDir) throws InitializationException { + InputStream is = this.getClass().getResourceAsStream(Constants.RES_CFG_ZIP); + + try { + Zipper.unzip(is, configDir.getAbsolutePath()); + } catch (IOException e) { + log.error( + "Failed to create local configuration directory!", e); //$NON-NLS-1$ + throw new InitializationException( + "Failed to create local configuration directory!", //$NON-NLS-1$ + e); + } + } + + private static void updateVersionFile(File configDir) throws InitializationException { + File versionFile = new File(configDir, Constants.CONFIG_VERSION_FILENAME); + try { + BufferedWriter versionWriter = new BufferedWriter(new FileWriter(versionFile)); + String version = Constants.APP_VERSION == null ? "Unknown" : Constants.APP_VERSION; //$NON-NLS-1$ + versionWriter.write(version); + versionWriter.close(); + } catch (IOException e) { + log.error( + "Failed to create configuration version file!", e); //$NON-NLS-1$ + throw new InitializationException( + "Failed to create configuration version file!", //$NON-NLS-1$ + e); + } + } + + private void initializeConfig() throws InitializationException { + this.initializeFromConfigurationFile(getStateMachine() + .getConfigProvider().getConfigurationFile()); + + getStateMachine().getConfigManipulator().setSignatureNote(Messages.getString("simple_config.Note_Default")); //$NON-NLS-1$ + + try { + getStateMachine().getConfigManipulator().saveCurrentConfiguration(); + } catch (IOException e) { + log.error( + "Failed to set local configuration signature note!", e); //$NON-NLS-1$ + throw new InitializationException( + "Failed to set local configuration signature note!", //$NON-NLS-1$ + e); + } + } + + private void createConfiguration(File configDir) throws InitializationException { + boolean allOK = false; + + log.info("Creating configuration directory"); //$NON-NLS-1$ + if (!configDir.exists()) { + configDir.mkdir(); + } + + try { + copyPdfOverConfig(); + copyLog4jConfig(); + unzipPdfAsConfig(configDir); + updateVersionFile(configDir); + initializeConfig(); - try { - Unzipper.unzip(is, configDir.getAbsolutePath()); - } catch (IOException e) { - log.error( - "Failed to create local configuration directory!", e); //$NON-NLS-1$ - throw new InitializationException( - "Failed to create local configuration directory!", //$NON-NLS-1$ - e); - } - - // initialize from config file - this.initializeFromConfigurationFile(getStateMachine() - .getConfigProvider().getConfigurationFile()); - - getStateMachine().getConfigManipulator().setSignatureNote(Messages.getString("simple_config.Note_Default")); //$NON-NLS-1$ - - try { - getStateMachine().getConfigManipulator().saveCurrentConfiguration(); - } catch (IOException e) { - log.error( - "Failed to set local configuration signature note!", e); //$NON-NLS-1$ - throw new InitializationException( - "Failed to set local configuration signature note!", //$NON-NLS-1$ - e); - } - allOK = true; } finally { if (!allOK) { @@ -278,21 +313,88 @@ public class PrepareConfigurationState extends State { } } + /** + * @return The first valid (not empty, non comment) line of the version file + * or null if version file cannot be read or does not contain + * such a line. + */ + private static String getVersion(File versionFile) { + if (versionFile.exists() && versionFile.canRead()) { + BufferedReader versionReader = null; + try { + versionReader = new BufferedReader(new FileReader(versionFile)); + String version; + while ((version = versionReader.readLine()) != null) { + version = version.trim(); + if (version.length() > 0 && !version.startsWith("#")) { //$NON-NLS-1$ + log.trace("configuration version from " + versionFile //$NON-NLS-1$ + + ": " + version); //$NON-NLS-1$ + return version; + } + } + } catch (IOException ex) { + log.error("failed to read configuration version from " //$NON-NLS-1$ + + versionFile, ex); + } finally { + try { + versionReader.close(); + } catch (IOException ex) { + // ignore + } + } + } + log.debug("unknown configuration version"); //$NON-NLS-1$ + return null; + } + + /** + * Backup old configuration, create new + * @param configDir + * @throws InitializationException + */ + private void backupAndCreatePdfAsConfiguration(File configDir) throws InitializationException { + try { + File backup = File.createTempFile(Constants.PDF_AS_CONFIG_BACKUP_FILENAME, ".zip"); //$NON-NLS-1$ + OutputStream os = new FileOutputStream(backup); + Zipper.zip(configDir + FILE_SEPARATOR + "cfg", os, true); //$NON-NLS-1$ + os.close(); + unzipPdfAsConfig(configDir); + File b = new File(configDir, Constants.PDF_AS_CONFIG_BACKUP_FILENAME + ".zip"); //$NON-NLS-1$ + int i = 1; + while (b.exists()) { + b = new File(configDir, Constants.PDF_AS_CONFIG_BACKUP_FILENAME + i++ + ".zip"); //$NON-NLS-1$ + } + backup.renameTo(b); + updateVersionFile(configDir); + } catch (FileNotFoundException e) { + log.error("Backup file not found", e); //$NON-NLS-1$ + throw new InitializationException("Backup file not found", e); //$NON-NLS-1$ + } catch (IOException e) { + log.error("Error creating configuration backup", e); //$NON-NLS-1$ + throw new InitializationException("Error creating configuration backup", e); //$NON-NLS-1$ + } + } + @Override public void run() { // Read config file try { - - File configDir = new File(getStateMachine().getConfigProvider().getConfigurationDirectory()); - File configFile = new File(getStateMachine().getConfigProvider().getConfigurationDirectory() - + FILE_SEPARATOR + Constants.DEFAULT_CONFIG_FILENAME); + String cDir = getStateMachine().getConfigProvider().getConfigurationDirectory(); + File configDir = new File(cDir); + File configFile = new File(configDir, Constants.DEFAULT_CONFIG_FILENAME); if (!configDir.exists() || !configFile.exists()) { log.debug("Creating configuration file"); //$NON-NLS-1$ createConfiguration(configDir); } else { log.debug("Configuration directory exists!"); //$NON-NLS-1$ + // Check PDF-AS config version + File versionFile = new File(configDir, Constants.CONFIG_VERSION_FILENAME); + String configVersion = getVersion(versionFile); + if (configVersion == null || VersionComparator.before(configVersion, Constants.MIN_PDF_AS_CONFIG_VERSION)) + backupAndCreatePdfAsConfiguration(configDir); } + // Read cli arguments for config file first try { this.initializeFromArguments(getStateMachine().getCmdArgs(), @@ -385,7 +487,7 @@ public class PrepareConfigurationState extends State { } catch (InitializationException e) { log.error("Failed to initialize: ", e); //$NON-NLS-1$ ErrorDialog error = new ErrorDialog(getStateMachine() - .getGUIProvider().getMainShell(), + .getGUIProvider().getMainShell(), Messages.getString("error.Initialization"), //$NON-NLS-1$ BUTTONS.OK); // error.setException(e); @@ -397,7 +499,7 @@ public class PrepareConfigurationState extends State { /* * (non-Javadoc) - * + * * @see at.asit.pdfover.gui.workflow.states.State#cleanUp() */ @Override @@ -407,7 +509,7 @@ public class PrepareConfigurationState extends State { /* * (non-Javadoc) - * + * * @see at.asit.pdfover.gui.workflow.states.State#setMainWindowBehavior() */ @Override -- cgit v1.2.3