public void saveFile() {
        // Ensure we actually CAN save the document in the first place
        if (!havePermissionToModifyDocument()) {
            org.icepdf.ri.util.Resources.showMessageDialog(
                    viewer,
                    JOptionPane.INFORMATION_MESSAGE,
                    messageBundle,
                    "viewer.dialog.saveAs.noPermission.title",
                    "viewer.dialog.saveAs.noPermission.msg");
            return;
        }

        // Create and display a file saving dialog
        final JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle(messageBundle.getString("viewer.dialog.saveAs.title"));
        fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        fileChooser.addChoosableFileFilter(FileExtensionUtils.getPDFFileFilter());
        if (ViewModel.getDefaultFile() != null) {
            fileChooser.setCurrentDirectory(ViewModel.getDefaultFile());
        }

        // See if we can come up with a default file name
        // We want the bytes from whence, but the file name of origin
        String origin = document.getDocumentOrigin();
        String originalFileName = null;
        if (origin != null) {
            int lastSeparator = Math.max(
                    Math.max(
                            origin.lastIndexOf("/"),
                            origin.lastIndexOf("\\")),
                    origin.lastIndexOf(File.separator) // Might not be / or \
            );
            if (lastSeparator >= 0) {
                originalFileName = origin.substring(lastSeparator + 1);
                if (originalFileName != null && originalFileName.length() > 0) {
                    // Set the selected file to a slightly modified name of the original
                    fileChooser.setSelectedFile(new File(generateNewSaveName(originalFileName)));
                } else {
                    originalFileName = null;
                }
            }
        }

        // show the dialog
        int returnVal = fileChooser.showSaveDialog(viewer);

        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fileChooser.getSelectedFile();

            // make sure file path being saved to is valid
            String extension = FileExtensionUtils.getExtension(file);
            if (extension == null) {
                org.icepdf.ri.util.Resources.showMessageDialog(
                        viewer,
                        JOptionPane.INFORMATION_MESSAGE,
                        messageBundle,
                        "viewer.dialog.saveAs.noExtensionError.title",
                        "viewer.dialog.saveAs.noExtensionError.msg");
                saveFile();
            } else if (!extension.equals(FileExtensionUtils.pdf)) {
                org.icepdf.ri.util.Resources.showMessageDialog(
                        viewer,
                        JOptionPane.INFORMATION_MESSAGE,
                        messageBundle,
                        "viewer.dialog.saveAs.extensionError.title",
                        "viewer.dialog.saveAs.extensionError.msg",
                        file.getName());
                saveFile();
            } else if ((originalFileName != null) &&
                    (originalFileName.equalsIgnoreCase(file.getName()))) {
                // Ensure a unique filename
                org.icepdf.ri.util.Resources.showMessageDialog(
                        viewer,
                        JOptionPane.INFORMATION_MESSAGE,
                        messageBundle,
                        "viewer.dialog.saveAs.noneUniqueName.title",
                        "viewer.dialog.saveAs.noneUniqueName.msg",
                        file.getName());
                saveFile();
            } else {
                // save file stream
                try {
                    // If we don't know where the file came from, it's because we
                    //  used Document.setInputStream() or Document.setByteArray(),
                    //  or we used setUrl() with disk caching disabled.
                    //  with no path or URL as the origin.
                    // Note that we used to detect scenarios where we could access
                    //  the file directly, or re-download it, to avoid locking our
                    //  internal data structures for long periods for large PDFs,
                    //  but that could cause problems with slow network links too,
                    //  and would complicate the incremental update code, so we're
                    //  harmonising on this approach.
                    FileOutputStream fileOutputStream = new FileOutputStream(file);
                    BufferedOutputStream buf = new BufferedOutputStream(
                            fileOutputStream, 4096 * 2);

                    document.saveToOutputStream(buf);

                    buf.flush();
                    fileOutputStream.flush();
                    buf.close();
                    fileOutputStream.close();
                } catch (MalformedURLException e) {
                    logger.log(Level.FINE, "Malformed URL Exception ", e);
                } catch (IOException e) {
                    logger.log(Level.FINE, "IO Exception ", e);
                }
                // save the default directory
                ViewModel.setDefaultFile(file);
            }
        }
    }