/* * 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.composites; // Imports import java.awt.Desktop; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import org.apache.commons.io.FilenameUtils; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.program.Program; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Link; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import at.asit.pdfover.gui.Constants; import at.asit.pdfover.gui.controls.Dialog; import at.asit.pdfover.gui.controls.Dialog.BUTTONS; import at.asit.pdfover.gui.controls.Dialog.ICON; import at.asit.pdfover.gui.controls.ErrorDialog; import at.asit.pdfover.gui.utils.Messages; import at.asit.pdfover.gui.workflow.states.State; import at.asit.pdfover.signator.DocumentSource; /** * GUI component for Output State */ public class OutputComposite extends StateComposite { /** * SLF4J Logger instance **/ static final Logger log = LoggerFactory.getLogger(OutputComposite.class); private Link lnk_saved_file; private Button btn_save; private Label lbl_success_message; private DocumentSource signedDocument; private File inputFile; String outputDir = null; String tempDirectory = null; File outputFile = null; private boolean saveFailed = false; /** * Create the composite. * * @param parent * The parent composite * @param style * The swt style * @param state * The owning state */ public OutputComposite(Composite parent, int style, State state) { super(parent, style, state); this.setLayout(new FormLayout()); this.lbl_success_message = new Label(this, SWT.NATIVE | SWT.RESIZE); FormData fd_lbl_success_message = new FormData(); fd_lbl_success_message.top = new FormAttachment(40, 0); fd_lbl_success_message.left = new FormAttachment(0); fd_lbl_success_message.right = new FormAttachment(100); this.lbl_success_message.setLayoutData(fd_lbl_success_message); this.lbl_success_message.setAlignment(SWT.CENTER); FontData[] fD1 = this.lbl_success_message.getFont().getFontData(); fD1[0].setHeight(Constants.TEXT_SIZE_BIG); this.lbl_success_message.setFont(new Font(Display.getCurrent(), fD1[0])); this.lnk_saved_file = new Link(this, SWT.NATIVE | SWT.RESIZE); FormData fd_lnk_saved_file = new FormData(); fd_lnk_saved_file.top = new FormAttachment(this.lbl_success_message, 10); fd_lnk_saved_file.left = new FormAttachment(this.lbl_success_message, 0, SWT.CENTER); // fd_lnk_saved_file.right = new FormAttachment(100); this.lnk_saved_file.setLayoutData(fd_lnk_saved_file); this.lnk_saved_file.addSelectionListener(new OpenSelectionListener()); FontData[] fD2 = this.lnk_saved_file.getFont().getFontData(); fD2[0].setHeight(Constants.TEXT_SIZE_NORMAL); this.lnk_saved_file.setFont(new Font(Display.getCurrent(), fD2[0])); this.btn_save = new Button(this, SWT.NATIVE | SWT.RESIZE); FontData[] fD_btn_save = this.btn_save.getFont().getFontData(); fD_btn_save[0].setHeight(Constants.TEXT_SIZE_BUTTON); this.btn_save.setFont(new Font(Display.getCurrent(), fD_btn_save[0])); FormData fd_btn_save = new FormData(); fd_btn_save.top = new FormAttachment(this.lnk_saved_file, 10); fd_btn_save.left = new FormAttachment(this.lnk_saved_file, 0, SWT.CENTER); this.btn_save.setLayoutData(fd_btn_save); this.btn_save.addSelectionListener(new SaveSelectionListener()); enableSaveButton(false); reloadResources(); } /** * @param outputDir * the outputDir to set */ public void setOutputDir(String outputDir) { this.outputDir = outputDir; } /** * @return the outputDir */ public String getOutputDir() { return this.outputDir; } /** * Sets the input file * * @param inputFile * the input file */ public void setInputFile(File inputFile) { this.inputFile = inputFile; } /** * Gets the input file * * @return the input file */ public File getInputFile() { return this.inputFile; } /** * @param tempDirectory */ public void setTempDir(String tempDirectory) { this.tempDirectory = tempDirectory; } /** * Gets the signed document * * @return the signed document */ public DocumentSource getSignedDocument() { return this.signedDocument; } /** * Sets the signed document * * @param signedDocument * the signed document */ public void setSignedDocument(final DocumentSource signedDocument) { this.signedDocument = signedDocument; } /** * Return whether the last save was successful * @return whether the last save was successful */ public boolean getSaveSuccessful() { return !this.saveFailed; } private void enableSaveButton(boolean doEnable) { this.btn_save.setEnabled(doEnable); this.btn_save.setVisible(doEnable); } /** * Saves the signed document. * * If user has a default output directory set, try to save there. * If not (or if directory unavailable), ask user for location. */ public void saveDocument() { File inputFolder = getInputFile().getAbsoluteFile().getParentFile(); String fileName = getInputFile().getName(); String proposedName = getSignedFileName(fileName); String outputFileName; String outputFolder = getOutputDir(); if (!this.saveFailed && outputFolder != null && !outputFolder.trim().isEmpty()) { // Output folder configured, try to save there File f = new File(outputFolder); if (f.isDirectory()) { if (!outputFolder.endsWith(File.separator)) { outputFolder += File.separator; } outputFileName = outputFolder + proposedName; } else { outputFileName = outputFolder; } } else { // Ask user where to save FileDialog save = new FileDialog(this.getShell(), SWT.SAVE | SWT.NATIVE); save.setFilterExtensions(new String[] { "*.pdf", "*" }); //$NON-NLS-1$ //$NON-NLS-2$ save.setFilterNames(new String[] { Messages.getString("common.PDFExtension_Description"), //$NON-NLS-1$ Messages.getString("common.AllExtension_Description")}); //$NON-NLS-1$ save.setFilterPath(inputFolder.getAbsolutePath()); save.setFileName(proposedName); outputFileName = save.open(); inputFolder = null; } log.debug("Trying to save to '" + outputFileName + "'"); //$NON-NLS-1$ //$NON-NLS-2$ this.outputFile = saveResultAsFile(inputFolder, outputFileName); this.saveFailed = (this.outputFile == null); // If saving failed, enable save button enableSaveButton(this.saveFailed); reloadResources(); layout(true); } /** * Save the signed document under the given filename * @param inputFolder the Folder the original document is located at * @param target the filename to save the document as * * @return saved File (or null if unsuccessful) * @throws FileNotFoundException * @throws IOException */ private File saveResultAsFile(File inputFolder, String target) { if (target == null) return null; File targetFile = new File(target); if (!targetFile.isAbsolute()) targetFile = new File(inputFolder, target); if (targetFile.exists()) { Dialog dialog = new Dialog(getShell(), Messages.getString("common.warning"), //$NON-NLS-1$ String.format(Messages.getString("output.file_ask_overwrite"), targetFile.getName()), //$NON-NLS-1$ BUTTONS.OK_CANCEL, ICON.QUESTION); if (dialog.open() == SWT.CANCEL) { return null; } } DocumentSource source = this.getSignedDocument(); boolean retry; do { retry = false; try { FileOutputStream outstream = new FileOutputStream(targetFile); outstream.write(source.getByteArray(), 0, source.getByteArray().length); outstream.close(); } catch (FileNotFoundException e) { log.error("File not found", e); //$NON-NLS-1$ ErrorDialog dialog = new ErrorDialog(getShell(), String.format(Messages.getString("output.save_failed"), //$NON-NLS-1$ targetFile.getName(), e.getLocalizedMessage()), BUTTONS.RETRY_CANCEL); if (dialog.open() == SWT.CANCEL) return null; retry = true; } catch (IOException e) { log.error("IO Error", e); //$NON-NLS-1$ ErrorDialog dialog = new ErrorDialog(getShell(), String.format(Messages.getString("output.save_failed"), //$NON-NLS-1$ targetFile.getName(), e.getLocalizedMessage()), BUTTONS.RETRY_CANCEL); if (dialog.open() == SWT.CANCEL) return null; retry = true; } } while (retry); if (!targetFile.exists()) { log.error("Tried to save file " + targetFile.getName() + //$NON-NLS-1$ ", but it doesn't exist"); //$NON-NLS-1$ return null; } return targetFile; } /** * Get the proposed filename of a signed document for a given input filename * @param name input filename * @return proposed output filename */ private static String getSignedFileName(String name) { name = FilenameUtils.getName(name); String extension = FilenameUtils.getExtension(name); name = FilenameUtils.removeExtension(name); return name + Constants.SIGNED_SUFFIX + FilenameUtils.EXTENSION_SEPARATOR + extension; } /** * SelectionListener for save button */ private final class SaveSelectionListener extends SelectionAdapter { /** * Empty constructor */ public SaveSelectionListener() { } @Override public void widgetSelected(SelectionEvent e) { try { OutputComposite.this.saveDocument(); } catch (Exception ex) { log.error("SaveSelectionListener: ", ex); //$NON-NLS-1$ } } } /** * Selection Listener for open button */ private final class OpenSelectionListener extends SelectionAdapter { /** * Empty constructor */ public OpenSelectionListener() { } @Override public void widgetSelected(SelectionEvent e) { try { if (OutputComposite.this.outputFile == null) return; if (!OutputComposite.this.outputFile.exists()) return; // Normalize filename File f = new File(FilenameUtils.normalize( OutputComposite.this.outputFile.getAbsolutePath())); log.debug("Trying to open " + f.toString()); //$NON-NLS-1$ // work around for the case of Linux and Java version 8 if (isSpecialCase()) { reReloadResources(f.toString()); return; } else if (Desktop.isDesktopSupported()) { Desktop.getDesktop().open(f); } else { log.info("AWT Desktop is not supported on this platform"); //$NON-NLS-1$ Program.launch(f.getAbsolutePath()); } } catch (IOException ex) { log.error("OpenSelectionListener: ", ex); //$NON-NLS-1$ ErrorDialog error = new ErrorDialog(getShell(), String.format(Messages.getString("error.FailedToOpenDocument"), //$NON-NLS-1$ ex.getLocalizedMessage()), BUTTONS.RETRY_CANCEL); if (error.open() == SWT.RETRY) widgetSelected(e); } } } @Override protected void checkSubclass() { // Disable the check that prevents subclassing of SWT components } /* * (non-Javadoc) * * @see at.asit.pdfover.gui.composites.StateComposite#doLayout() */ @Override public void doLayout() { // Nothing to do this.layout(true); } /** * @return true when linux and java version <= 8 * */ public boolean isSpecialCase() { boolean isSCase = false; try { String os = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$ if (os.contains("linux")) { //$NON-NLS-1$ String version = System.getProperty("java.version"); //$NON-NLS-1$ if (version.contains(".")) { //$NON-NLS-1$ String[] parts = version.split("\\."); //$NON-NLS-1$ isSCase = Integer.valueOf(parts[0]) <= 8 ? true : false; } else { isSCase = Integer.valueOf(version) <= 8 ? true : false; } } } catch (Exception e) { log.debug("Error: " + e.getMessage()); //$NON-NLS-1$ isSCase = false; } return isSCase; } /* (non-Javadoc) * @see at.asit.pdfover.gui.composites.StateComposite#reloadResources() */ @Override public void reloadResources() { this.lbl_success_message.setText(Messages .getString("output.success_message")); //$NON-NLS-1$ if (this.outputFile == null) { this.lnk_saved_file.setText(Messages .getString("output.link_save_message")); //$NON-NLS-1$ } else { this.lnk_saved_file.setText(Messages .getString("output.link_open_message")); //$NON-NLS-1$ } this.btn_save.setText(Messages.getString("common.Save")); //$NON-NLS-1$ } public void reReloadResources(String str) { this.lbl_success_message.setText(Messages.getString("output.success_message")); //$NON-NLS-1$ if (this.outputFile == null) { this.lnk_saved_file.setText(Messages .getString("output.link_save_message")); //$NON-NLS-1$ } else { String str2 = "File location: " + str; //$NON-NLS-1$ this.lbl_success_message.setText(str2); this.lnk_saved_file.setText(""); //$NON-NLS-1$ } this.btn_save.setText(Messages.getString("common.Save")); //$NON-NLS-1$ } }