You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2015/09/27 20:04:44 UTC

svn commit: r1705561 [1/6] - in /pdfbox/trunk: ./ debugger/ debugger/src/ debugger/src/main/ debugger/src/main/java/ debugger/src/main/java/org/ debugger/src/main/java/org/apache/ debugger/src/main/java/org/apache/pdfbox/ debugger/src/main/java/org/apa...

Author: lehmi
Date: Sun Sep 27 18:04:42 2015
New Revision: 1705561

URL: http://svn.apache.org/viewvc?rev=1705561&view=rev
Log:
PDFBOX-2905: create a new package for PDFDebugger

Added:
    pdfbox/trunk/debugger/   (with props)
    pdfbox/trunk/debugger/pom.xml   (with props)
    pdfbox/trunk/debugger/src/
    pdfbox/trunk/debugger/src/main/
    pdfbox/trunk/debugger/src/main/java/
    pdfbox/trunk/debugger/src/main/java/org/
    pdfbox/trunk/debugger/src/main/java/org/apache/
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/PDFDebugger.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/ArrayEntry.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/DocumentEntry.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/ErrorDialog.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/MapEntry.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/OSXAdapter.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/PDFTreeCellRenderer.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/PDFTreeModel.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/PageEntry.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/ReaderBottomPanel.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSArrayBased.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSDeviceN.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSIndexed.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/CSSeparation.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/ColorBarCellRenderer.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/DeviceNColorant.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/DeviceNTableModel.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/IndexedColorant.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/colorpane/IndexedTableModel.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/AnnotFlag.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FieldFlag.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/Flag.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FlagBitsPane.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FlagBitsPaneView.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FontFlag.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/PanoseFlag.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/FontEncodingPaneController.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/FontEncodingView.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/SimpleFont.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/Type0Font.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/ASCIIPane.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/AddressPane.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexChangeListener.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexChangedEvent.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexEditor.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexModel.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexModelChangeListener.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexModelChangedEvent.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexPane.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexView.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/SelectEvent.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/SelectionChangeListener.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/StatusPane.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/UpperPane.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/pagepane/
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/pagepane/PagePane.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/OperatorMarker.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/Stream.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamImageView.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPane.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamPaneView.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/StreamTextView.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/ColorToolTip.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/FontToolTip.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/GToolTip.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/KToolTip.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/RGToolTip.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/SCNToolTip.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/streampane/tooltip/ToolTipController.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/stringpane/
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/stringpane/StringPane.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/treestatus/
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/treestatus/TreeStatus.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/treestatus/TreeStatusPane.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/ui/
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/ui/MenuBase.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/ui/RotationMenu.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/ui/Tree.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/ui/ZoomMenu.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/ui/textsearcher/
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/ui/textsearcher/SearchEngine.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/ui/textsearcher/SearchPanel.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/ui/textsearcher/Searcher.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/util/
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/util/ExtensionFileFilter.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/util/FileOpenSaveDialog.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/util/ImageUtil.java   (with props)
    pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/util/RecentFiles.java   (with props)
    pdfbox/trunk/debugger/src/main/resources/
    pdfbox/trunk/debugger/src/main/resources/org/
    pdfbox/trunk/debugger/src/main/resources/org/apache/
    pdfbox/trunk/debugger/src/main/resources/org/apache/pdfbox/
    pdfbox/trunk/debugger/src/main/resources/org/apache/pdfbox/tools/
    pdfbox/trunk/debugger/src/main/resources/org/apache/pdfbox/tools/pdfdebugger/
    pdfbox/trunk/debugger/src/main/resources/org/apache/pdfbox/tools/pdfdebugger/array.png   (with props)
    pdfbox/trunk/debugger/src/main/resources/org/apache/pdfbox/tools/pdfdebugger/boolean.png   (with props)
    pdfbox/trunk/debugger/src/main/resources/org/apache/pdfbox/tools/pdfdebugger/dict.png   (with props)
    pdfbox/trunk/debugger/src/main/resources/org/apache/pdfbox/tools/pdfdebugger/hex.png   (with props)
    pdfbox/trunk/debugger/src/main/resources/org/apache/pdfbox/tools/pdfdebugger/indirect.png   (with props)
    pdfbox/trunk/debugger/src/main/resources/org/apache/pdfbox/tools/pdfdebugger/integer.png   (with props)
    pdfbox/trunk/debugger/src/main/resources/org/apache/pdfbox/tools/pdfdebugger/name.png   (with props)
    pdfbox/trunk/debugger/src/main/resources/org/apache/pdfbox/tools/pdfdebugger/null.png   (with props)
    pdfbox/trunk/debugger/src/main/resources/org/apache/pdfbox/tools/pdfdebugger/page.png   (with props)
    pdfbox/trunk/debugger/src/main/resources/org/apache/pdfbox/tools/pdfdebugger/pdf.png   (with props)
    pdfbox/trunk/debugger/src/main/resources/org/apache/pdfbox/tools/pdfdebugger/real.png   (with props)
    pdfbox/trunk/debugger/src/main/resources/org/apache/pdfbox/tools/pdfdebugger/stream-dict.png   (with props)
    pdfbox/trunk/debugger/src/main/resources/org/apache/pdfbox/tools/pdfdebugger/string.png   (with props)
Removed:
    pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/ExtensionFileFilter.java
    pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/PDFDebugger.java
    pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/gui/ArrayEntry.java
    pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/gui/DocumentEntry.java
    pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/gui/ErrorDialog.java
    pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/gui/MapEntry.java
    pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/gui/OSXAdapter.java
    pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/gui/PDFTreeCellRenderer.java
    pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/gui/PDFTreeModel.java
    pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/gui/PageEntry.java
    pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/gui/ReaderBottomPanel.java
    pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/pdfdebugger/
    pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/util/
    pdfbox/trunk/tools/src/main/resources/
Modified:
    pdfbox/trunk/pom.xml
    pdfbox/trunk/tools/pom.xml
    pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/PDFReader.java

Propchange: pdfbox/trunk/debugger/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Sun Sep 27 18:04:42 2015
@@ -0,0 +1,4 @@
+target
+.classpath
+.settings
+.project

Added: pdfbox/trunk/debugger/pom.xml
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/pom.xml?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/pom.xml (added)
+++ pdfbox/trunk/debugger/pom.xml Sun Sep 27 18:04:42 2015
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ! Licensed to the Apache Software Foundation (ASF) under one or more
+ ! contributor license agreements.  See the NOTICE file distributed with
+ ! this work for additional information regarding copyright ownership.
+ ! The ASF licenses this file to You under the Apache License, Version 2.0
+ ! (the "License"); you may not use this file except in compliance with
+ ! the License.  You may obtain a copy of the License at
+ !
+ !      http://www.apache.org/licenses/LICENSE-2.0
+ !
+ ! Unless required by applicable law or agreed to in writing, software
+ ! distributed under the License is distributed on an "AS IS" BASIS,
+ ! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ! See the License for the specific language governing permissions and
+ ! limitations under the License.
+ !-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.pdfbox</groupId>
+    <artifactId>pdfbox-parent</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+    <relativePath>../parent/pom.xml</relativePath>
+  </parent>
+
+  <artifactId>pdfbox-debugger</artifactId>
+
+  <packaging>jar</packaging>
+  <name>Apache PDFBox Debugger</name>
+  <description>
+    The Apache PDFBox library is an open source Java tool for working with PDF documents. 
+    This artefact contains the PDFDebugger.
+  </description>
+  <inceptionYear>2002</inceptionYear>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcmail-jdk15on</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>pdfbox</artifactId>
+        <version>${project.version}</version>
+    </dependency>
+    <!-- For legal reasons (incompatible license), these two dependencies 
+        are to be used only in the tests and may not be distributed. 
+        See also LEGAL-195 -->
+    <dependency>
+        <groupId>com.levigo.jbig2</groupId>
+        <artifactId>levigo-jbig2-imageio</artifactId>
+        <scope>test</scope>
+    </dependency>
+    <dependency>
+        <groupId>net.java.dev.jai-imageio</groupId>
+        <artifactId>jai-imageio-core-standalone</artifactId>
+        <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+        <filtering>true</filtering>
+      </resource>
+    </resources>
+  </build>
+
+</project>
+

Propchange: pdfbox/trunk/debugger/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: pdfbox/trunk/debugger/pom.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/PDFDebugger.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/PDFDebugger.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/PDFDebugger.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/PDFDebugger.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,1203 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pdfbox.tools;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.FileDialog;
+import java.awt.Toolkit;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowEvent;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.KeyStroke;
+import javax.swing.TransferHandler;
+import javax.swing.UIManager;
+import javax.swing.border.BevelBorder;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.filechooser.FileFilter;
+import javax.swing.tree.TreePath;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSBoolean;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSFloat;
+import org.apache.pdfbox.cos.COSInteger;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSNull;
+import org.apache.pdfbox.cos.COSObject;
+import org.apache.pdfbox.cos.COSStream;
+import org.apache.pdfbox.cos.COSString;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.tools.gui.ArrayEntry;
+import org.apache.pdfbox.tools.gui.DocumentEntry;
+import org.apache.pdfbox.tools.gui.ErrorDialog;
+import org.apache.pdfbox.tools.gui.MapEntry;
+import org.apache.pdfbox.tools.gui.OSXAdapter;
+import org.apache.pdfbox.tools.gui.PDFTreeCellRenderer;
+import org.apache.pdfbox.tools.gui.PDFTreeModel;
+import org.apache.pdfbox.tools.gui.PageEntry;
+import org.apache.pdfbox.tools.pdfdebugger.colorpane.CSArrayBased;
+import org.apache.pdfbox.tools.pdfdebugger.colorpane.CSDeviceN;
+import org.apache.pdfbox.tools.pdfdebugger.colorpane.CSIndexed;
+import org.apache.pdfbox.tools.pdfdebugger.colorpane.CSSeparation;
+import org.apache.pdfbox.tools.pdfdebugger.flagbitspane.FlagBitsPane;
+import org.apache.pdfbox.tools.pdfdebugger.fontencodingpane.FontEncodingPaneController;
+import org.apache.pdfbox.tools.pdfdebugger.pagepane.PagePane;
+import org.apache.pdfbox.tools.pdfdebugger.streampane.StreamPane;
+import org.apache.pdfbox.tools.pdfdebugger.stringpane.StringPane;
+import org.apache.pdfbox.tools.pdfdebugger.treestatus.TreeStatus;
+import org.apache.pdfbox.tools.pdfdebugger.treestatus.TreeStatusPane;
+import org.apache.pdfbox.tools.pdfdebugger.ui.RotationMenu;
+import org.apache.pdfbox.tools.pdfdebugger.ui.Tree;
+import org.apache.pdfbox.tools.pdfdebugger.ui.ZoomMenu;
+import org.apache.pdfbox.tools.util.ExtensionFileFilter;
+import org.apache.pdfbox.tools.util.FileOpenSaveDialog;
+import org.apache.pdfbox.tools.util.RecentFiles;
+
+/**
+ * PDF Debugger.
+ * 
+ * @author wurtz
+ * @author Ben Litchfield
+ * @author Khyrul Bashar
+ */
+public class PDFDebugger extends JFrame
+{
+    private static final Set<COSName> SPECIALCOLORSPACES =
+            new HashSet<COSName>(Arrays.asList(COSName.INDEXED, COSName.SEPARATION, COSName.DEVICEN));
+
+    private static final Set<COSName> OTHERCOLORSPACES =
+            new HashSet<COSName>(Arrays.asList(COSName.ICCBASED, COSName.PATTERN, COSName.CALGRAY,
+                                 COSName.CALRGB, COSName.LAB));
+
+    private static final String PASSWORD = "-password";
+
+    private static final int SHORCUT_KEY_MASK =
+            Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+    
+    private TreeStatusPane statusPane;
+    private RecentFiles recentFiles;
+    private boolean isPageMode;
+
+    private PDDocument document;
+    private String currentFilePath;
+    
+    private static final String OS_NAME = System.getProperty("os.name").toLowerCase();
+    private static final boolean IS_MAC_OS = OS_NAME.startsWith("mac os x");
+    
+    private JScrollPane jScrollPane1;
+    private JScrollPane jScrollPane2;
+    private javax.swing.JSplitPane jSplitPane1;
+    private javax.swing.JTextPane jTextPane1;
+    private Tree tree;
+    private final JPanel documentPanel = new JPanel();
+    
+    // file menu
+    private JMenuItem saveAsMenuItem;
+    private JMenuItem saveMenuItem;
+    private JMenu recentFilesMenu;
+    
+    // edit > find menu
+    private JMenu findMenu;
+    private JMenuItem findMenuItem;
+    private JMenuItem findNextMenuItem;
+    private JMenuItem findPreviousMenuItem;
+
+    // view menu
+    private JMenuItem viewModeItem;
+    
+    /**
+     * Constructor.
+     */
+    public PDFDebugger()
+    {
+        initComponents();
+    }
+
+    /**
+     * This method is called from within the constructor to initialize the form.
+     */
+    private void initComponents()
+    {
+        jSplitPane1 = new javax.swing.JSplitPane();
+        jScrollPane1 = new JScrollPane();
+        tree = new Tree(this);
+        jScrollPane2 = new JScrollPane();
+        jTextPane1 = new javax.swing.JTextPane();
+        
+        tree.setCellRenderer(new PDFTreeCellRenderer());
+        tree.setModel(null);
+
+        setTitle("PDFBox Debugger");
+
+        addWindowListener(new java.awt.event.WindowAdapter()
+        {
+            @Override
+            public void windowOpened(WindowEvent windowEvent)
+            {
+                tree.requestFocusInWindow();
+                super.windowOpened(windowEvent);
+            }
+
+            @Override
+            public void windowClosing(WindowEvent evt)
+            {
+                exitForm(evt);
+            }
+        });
+        
+        jScrollPane1.setBorder(new BevelBorder(BevelBorder.RAISED));
+        jScrollPane1.setPreferredSize(new Dimension(300, 500));
+        tree.addTreeSelectionListener(new TreeSelectionListener()
+        {
+            @Override
+            public void valueChanged(TreeSelectionEvent evt)
+            {
+                jTree1ValueChanged(evt);
+            }
+        });
+
+        jScrollPane1.setViewportView(tree);
+
+        jSplitPane1.setRightComponent(jScrollPane2);
+        jSplitPane1.setDividerSize(3);
+        
+        jScrollPane2.setPreferredSize(new Dimension(300, 500));
+        jScrollPane2.setViewportView(jTextPane1);
+
+        jSplitPane1.setLeftComponent(jScrollPane1);
+
+        JScrollPane documentScroller = new JScrollPane();
+        documentScroller.setViewportView(documentPanel);
+
+        statusPane = new TreeStatusPane(tree);
+        statusPane.getPanel().setBorder(new BevelBorder(BevelBorder.RAISED));
+        statusPane.getPanel().setPreferredSize(new Dimension(300, 25));
+        getContentPane().add(statusPane.getPanel(), BorderLayout.PAGE_START);
+
+        getContentPane().add(jSplitPane1, BorderLayout.CENTER);
+
+        // create menus
+        JMenuBar menuBar = new JMenuBar();
+        menuBar.add(createFileMenu());
+        menuBar.add(createEditMenu());
+        menuBar.add(createViewMenu());
+        setJMenuBar(menuBar);
+
+        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+        setBounds((screenSize.width-700)/2, (screenSize.height-600)/2, 700, 600);
+
+        // drag and drop to open files
+        setTransferHandler(new TransferHandler()
+        {
+            @Override
+            public boolean canImport(TransferSupport transferSupport)
+            {
+                return transferSupport.isDataFlavorSupported(DataFlavor.javaFileListFlavor);
+            }
+
+            @Override
+            @SuppressWarnings("unchecked")
+            public boolean importData(TransferSupport transferSupport)
+            {
+                try
+                {
+                    Transferable transferable = transferSupport.getTransferable();
+                    List<File> files = (List<File>) transferable.getTransferData(
+                            DataFlavor.javaFileListFlavor);
+                    readPDFFile(files.get(0), "");
+                    return true;
+                }
+                catch (IOException e)
+                {
+                    throw new RuntimeException(e);
+                }
+                catch (UnsupportedFlavorException e)
+                {
+                    throw new RuntimeException(e);
+                }
+            }
+        });
+
+        // Mac OS X file open/quit handler
+        if (IS_MAC_OS)
+        {
+            try
+            {
+                Method osxOpenFiles = getClass().getDeclaredMethod("osxOpenFiles", String.class);
+                osxOpenFiles.setAccessible(true);
+                OSXAdapter.setFileHandler(this, osxOpenFiles);
+
+                Method osxQuit = getClass().getDeclaredMethod("osxQuit");
+                osxQuit.setAccessible(true);
+                OSXAdapter.setQuitHandler(this, osxQuit);
+            }
+            catch (NoSuchMethodException e)
+            {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+    
+    private JMenu createFileMenu()
+    {
+        JMenuItem openMenuItem = new JMenuItem("Open...");
+        openMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, SHORCUT_KEY_MASK));
+        openMenuItem.addActionListener(new ActionListener()
+        {
+            @Override
+            public void actionPerformed(ActionEvent evt)
+            {
+                openMenuItemActionPerformed(evt);
+            }
+        });
+
+        JMenu fileMenu = new JMenu("File");
+        fileMenu.add(openMenuItem);
+
+        JMenuItem openUrlMenuItem = new JMenuItem("Open URL...");
+        openUrlMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_U, SHORCUT_KEY_MASK));
+        openUrlMenuItem.addActionListener(new ActionListener()
+        {
+            @Override
+            public void actionPerformed(ActionEvent evt)
+            {
+                String urlString = JOptionPane.showInputDialog("Enter an URL");
+                try
+                {
+                    readPDFurl(urlString, "");
+                }
+                catch (IOException e)
+                {
+                    throw new RuntimeException(e);
+                }
+            }
+        });
+        fileMenu.add(openUrlMenuItem);
+
+        try
+        {
+            recentFiles = new RecentFiles(this.getClass(), 5);
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException(e);
+        }
+
+        recentFilesMenu = new JMenu("Open Recent");
+        recentFilesMenu.setEnabled(false);
+        addRecentFileItems();
+        fileMenu.add(recentFilesMenu);
+
+        JMenuItem exitMenuItem = new JMenuItem("Exit");
+        exitMenuItem.setAccelerator(KeyStroke.getKeyStroke("alt F4"));
+        exitMenuItem.addActionListener(new ActionListener()
+        {
+            @Override
+            public void actionPerformed(ActionEvent evt)
+            {
+                exitMenuItemActionPerformed(evt);
+            }
+        });
+
+        if (!IS_MAC_OS)
+        {
+            fileMenu.addSeparator();
+            fileMenu.add(exitMenuItem);
+        }
+        
+        return fileMenu;
+    }
+    
+    private JMenu createEditMenu()
+    {
+        JMenu editMenu = new JMenu("Edit");
+        
+        JMenuItem cutMenuItem = new JMenuItem("Cut");
+        cutMenuItem.setEnabled(false);
+        editMenu.add(cutMenuItem);
+
+        JMenuItem copyMenuItem = new JMenuItem("Copy");
+        copyMenuItem.setEnabled(false);
+        editMenu.add(copyMenuItem);
+
+        JMenuItem pasteMenuItem = new JMenuItem("Paste");
+        pasteMenuItem.setEnabled(false);
+        editMenu.add(pasteMenuItem);
+
+        JMenuItem deleteMenuItem = new JMenuItem("Delete");
+        deleteMenuItem.setEnabled(false);
+        editMenu.add(deleteMenuItem);
+        editMenu.addSeparator();
+        editMenu.add(createFindMenu());
+        
+        return editMenu;
+    }
+    
+    private JMenu createViewMenu()
+    {
+        JMenu viewMenu = new JMenu("View");
+        viewModeItem = new JMenuItem("Show Pages");
+        viewModeItem.addActionListener(new ActionListener()
+        {
+            @Override
+            public void actionPerformed(ActionEvent actionEvent)
+            {
+                if (isPageMode)
+                {
+                    viewModeItem.setText("Show Pages");
+                    isPageMode = false;
+                }
+                else
+                {
+                    viewModeItem.setText("Show Internal Structure");
+                    isPageMode = true;
+                }
+                if (document != null)
+                {
+                    initTree();
+                }
+            }
+        });
+        viewMenu.add(viewModeItem);
+
+        ZoomMenu zoomMenu = ZoomMenu.getInstance();
+        zoomMenu.setEnableMenu(false);
+        viewMenu.add(zoomMenu.getMenu());
+
+        RotationMenu rotationMenu = RotationMenu.getInstance();
+        rotationMenu.setEnableMenu(false);
+        viewMenu.add(rotationMenu.getMenu());
+        
+        return viewMenu;
+    }
+    
+    private JMenu createFindMenu()
+    {
+        findMenu = new JMenu("Find");
+        findMenu.setEnabled(false);
+        
+        findMenuItem = new JMenuItem("Find...");
+        findMenuItem.setActionCommand("find");
+        findMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, SHORCUT_KEY_MASK));
+        
+        findNextMenuItem = new JMenuItem("Find Next");
+        if (IS_MAC_OS)
+        {
+            findNextMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G, SHORCUT_KEY_MASK));
+        }
+        else
+        {
+            findNextMenuItem.setAccelerator(KeyStroke.getKeyStroke("F3"));
+        }
+
+        findPreviousMenuItem = new JMenuItem("Find Previous");
+        if (IS_MAC_OS)
+        {
+            findPreviousMenuItem.setAccelerator(KeyStroke.getKeyStroke(
+                    KeyEvent.VK_G, SHORCUT_KEY_MASK | InputEvent.SHIFT_DOWN_MASK));
+        }
+        else
+        {
+            findPreviousMenuItem.setAccelerator(KeyStroke.getKeyStroke(
+                    KeyEvent.VK_F3, InputEvent.SHIFT_DOWN_MASK));
+        }
+        
+        findMenu.add(findMenuItem);
+        findMenu.add(findNextMenuItem);
+        findMenu.add(findPreviousMenuItem);
+        
+        return findMenu;
+    }
+
+    /**
+     * Returns the File menu.
+     */
+    public JMenu getFindMenu()
+    {
+        return findMenu;
+    }
+
+    /**
+     * Returns the Edit > Find > Find menu item.
+     */
+    public JMenuItem getFindMenuItem()
+    {
+        return findMenuItem;
+    }
+
+    /**
+     * Returns the Edit > Find > Find Next menu item.
+     */
+    public JMenuItem getFindNextMenuItem()
+    {
+        return findNextMenuItem;
+    }
+
+    /**
+     * Returns the Edit > Find > Find Previous menu item.
+     */
+    public JMenuItem getFindPreviousMenuItem()
+    {
+        return findPreviousMenuItem;
+    }
+    
+    /**
+     * This method is called via reflection on Mac OS X.
+     */
+    private void osxOpenFiles(String filename)
+    {
+        try
+        {
+            readPDFFile(filename, "");
+        }
+        catch (IOException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * This method is called via reflection on Mac OS X.
+     */
+    private void osxQuit()
+    {
+        exitMenuItemActionPerformed(null);
+    }
+
+    private void openMenuItemActionPerformed(ActionEvent evt)
+    {
+        try
+        {
+            if (IS_MAC_OS)
+            {
+                FileDialog openDialog = new FileDialog(this, "Open");
+                openDialog.setFilenameFilter(new FilenameFilter()
+                {
+                    @Override
+                    public boolean accept(File file, String s)
+                    {
+                        return file.getName().toLowerCase().endsWith(".pdf");
+                    }
+                });
+                openDialog.setVisible(true);
+                if (openDialog.getFile() != null)
+                {
+                    readPDFFile(openDialog.getFile(), "");
+                }
+            }
+            else
+            {
+                String[] extensions = new String[] {"pdf", "PDF"};
+                FileFilter pdfFilter = new ExtensionFileFilter(extensions, "PDF Files (*.pdf)");
+                FileOpenSaveDialog openDialog = new FileOpenSaveDialog(this, pdfFilter);
+
+                File file = openDialog.openFile();
+                if (file != null)
+                {
+                    readPDFFile(file, "");
+                }
+            }
+        }
+        catch (IOException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private void jTree1ValueChanged(TreeSelectionEvent evt)
+    {
+        TreePath path = tree.getSelectionPath();
+        if (path != null)
+        {
+            try
+            {
+                Object selectedNode = path.getLastPathComponent();
+                
+                if (isPage(selectedNode))
+                {
+                    showPage(selectedNode);
+                    return;
+                }
+                
+                if (isSpecialColorSpace(selectedNode) || isOtherColorSpace(selectedNode))
+                {
+                    showColorPane(selectedNode);
+                    return;
+                }
+                if (path.getParentPath() != null
+                        && isFlagNode(selectedNode, path.getParentPath().getLastPathComponent()))
+                {
+                    Object parentNode = path.getParentPath().getLastPathComponent();
+                    showFlagPane(parentNode, selectedNode);
+                    return;
+                }
+                if (isStream(selectedNode))
+                {
+                    showStream((COSStream) getUnderneathObject(selectedNode), path);
+                    return;
+                }
+                if (isFont(selectedNode))
+                {
+                    showFont(selectedNode, path);
+                    return;
+                }
+                if (isString(selectedNode))
+                {
+                    showString(selectedNode);
+                    return;
+                }
+                if (jSplitPane1.getRightComponent() == null
+                        || !jSplitPane1.getRightComponent().equals(jScrollPane2))
+                {
+                    replaceRightComponent(jScrollPane2);
+                }
+                jTextPane1.setText(convertToString(selectedNode));
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    private boolean isSpecialColorSpace(Object selectedNode)
+    {
+        selectedNode = getUnderneathObject(selectedNode);
+
+        if (selectedNode instanceof COSArray && ((COSArray) selectedNode).size() > 0)
+        {
+            COSBase arrayEntry = ((COSArray)selectedNode).get(0);
+            if (arrayEntry instanceof COSName)
+            {
+                COSName name = (COSName) arrayEntry;
+                return SPECIALCOLORSPACES.contains(name);
+            }
+        }
+        return false;
+    }
+
+    private boolean isOtherColorSpace(Object selectedNode)
+    {
+        selectedNode = getUnderneathObject(selectedNode);
+
+        if (selectedNode instanceof COSArray && ((COSArray) selectedNode).size() > 0)
+        {
+            COSBase arrayEntry = ((COSArray)selectedNode).get(0);
+            if (arrayEntry instanceof COSName)
+            {
+                COSName name = (COSName) arrayEntry;
+                return OTHERCOLORSPACES.contains(name);
+            }
+        }
+        return false;
+    }
+
+    private boolean isPage(Object selectedNode)
+    {
+        selectedNode = getUnderneathObject(selectedNode);
+
+        if (selectedNode instanceof COSDictionary)
+        {
+            COSDictionary dict = (COSDictionary) selectedNode;
+            COSBase typeItem = dict.getItem(COSName.TYPE);
+            if (COSName.PAGE.equals(typeItem))
+            {
+                return true;
+            }
+        }
+        else if (selectedNode instanceof PageEntry)
+        {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isFlagNode(Object selectedNode, Object parentNode)
+    {
+        if (selectedNode instanceof MapEntry)
+        {
+            Object key = ((MapEntry) selectedNode).getKey();
+            return (COSName.FLAGS.equals(key) && isFontDescriptor(parentNode))
+                    || (COSName.F.equals(key) && isAnnot(parentNode)) || COSName.FF.equals(key)
+                    || COSName.PANOSE.equals(key);
+        }
+        return false;
+    }
+
+    private boolean isFontDescriptor(Object obj)
+    {
+        Object underneathObject = getUnderneathObject(obj);
+        return underneathObject instanceof COSDictionary &&
+                ((COSDictionary) underneathObject).containsKey(COSName.TYPE) &&
+                ((COSDictionary) underneathObject).getCOSName(COSName.TYPE).equals(COSName.FONT_DESC);
+    }
+
+    private boolean isAnnot(Object obj)
+    {
+        Object underneathObject = getUnderneathObject(obj);
+        return underneathObject instanceof COSDictionary &&
+                ((COSDictionary) underneathObject).containsKey(COSName.TYPE) &&
+                ((COSDictionary) underneathObject).getCOSName(COSName.TYPE).equals(COSName.ANNOT);
+    }
+
+    private boolean isStream(Object selectedNode)
+    {
+        return getUnderneathObject(selectedNode) instanceof COSStream;
+    }
+
+    private boolean isString(Object selectedNode)
+    {
+        return getUnderneathObject(selectedNode) instanceof COSString;
+    }
+
+    private boolean isFont(Object selectedNode)
+    {
+        selectedNode = getUnderneathObject(selectedNode);
+        if (selectedNode instanceof COSDictionary)
+        {
+            COSDictionary dic = (COSDictionary)selectedNode;
+            return dic.containsKey(COSName.TYPE) &&
+                    dic.getCOSName(COSName.TYPE).equals(COSName.FONT) &&
+                    !isCIDFont(dic);
+        }
+        return false;
+    }
+
+    private boolean isCIDFont(COSDictionary dic)
+    {
+        return dic.containsKey(COSName.SUBTYPE) &&
+                (dic.getCOSName(COSName.SUBTYPE).equals(COSName.CID_FONT_TYPE0)
+                || dic.getCOSName(COSName.SUBTYPE).equals(COSName.CID_FONT_TYPE2));
+    }
+
+    /**
+     * Show a Panel describing color spaces in more detail and interactive way.
+     * @param csNode the special color space containing node.
+     */
+    private void showColorPane(Object csNode)
+    {
+        csNode = getUnderneathObject(csNode);
+
+        if (csNode instanceof COSArray && ((COSArray) csNode).size() > 0)
+        {
+            COSArray array = (COSArray)csNode;
+            COSBase arrayEntry = array.get(0);
+            if (arrayEntry instanceof COSName)
+            {
+                COSName csName = (COSName) arrayEntry;
+                if (csName.equals(COSName.SEPARATION))
+                {
+                    replaceRightComponent(new CSSeparation(array).getPanel());
+                }
+                else if (csName.equals(COSName.DEVICEN))
+                {
+                    replaceRightComponent(new CSDeviceN(array).getPanel());
+                }
+                else if (csName.equals(COSName.INDEXED))
+                {
+                    replaceRightComponent(new CSIndexed(array).getPanel());
+                }
+                else if (OTHERCOLORSPACES.contains(csName))
+                {
+                    replaceRightComponent(new CSArrayBased(array).getPanel());
+                }
+            }
+        }
+    }
+
+    private void showPage(Object selectedNode)
+    {
+        selectedNode = getUnderneathObject(selectedNode);
+
+        COSDictionary page;
+        if (selectedNode instanceof COSDictionary)
+        {
+            page = (COSDictionary) selectedNode;
+        }
+        else
+        {
+            page = ((PageEntry) selectedNode).getDict();
+        }
+
+        COSBase typeItem = page.getItem(COSName.TYPE);
+        if (COSName.PAGE.equals(typeItem))
+        {
+            PagePane pagePane = new PagePane(document, page);
+            replaceRightComponent(new JScrollPane(pagePane.getPanel()));
+        }
+    }
+
+    private void showFlagPane(Object parentNode, Object selectedNode)
+    {
+        parentNode = getUnderneathObject(parentNode);
+        if (parentNode instanceof COSDictionary)
+        {
+            selectedNode = ((MapEntry)selectedNode).getKey();
+            selectedNode = getUnderneathObject(selectedNode);
+            FlagBitsPane flagBitsPane = new FlagBitsPane((COSDictionary) parentNode, (COSName) selectedNode);
+            replaceRightComponent(flagBitsPane.getPane());
+        }
+    }
+
+    private void showStream(COSStream stream, TreePath path) throws IOException
+    {
+        boolean isContentStream = false;
+        boolean isThumb = false;
+
+        COSName key = getNodeKey(path.getLastPathComponent());
+        COSName parentKey = getNodeKey(path.getParentPath().getLastPathComponent());
+        COSDictionary resourcesDic = null;
+
+        if (COSName.CONTENTS.equals(key))
+        {
+            Object pageObj = path.getParentPath().getLastPathComponent();
+            COSDictionary page = (COSDictionary) getUnderneathObject(pageObj);
+            resourcesDic = (COSDictionary) page.getDictionaryObject(COSName.RESOURCES);
+            isContentStream = true;
+        }
+        else if (COSName.CONTENTS.equals(parentKey) || COSName.CHAR_PROCS.equals(parentKey))
+        {
+            Object pageObj = path.getParentPath().getParentPath().getLastPathComponent();
+            COSDictionary page = (COSDictionary) getUnderneathObject(pageObj);
+            resourcesDic = (COSDictionary) page.getDictionaryObject(COSName.RESOURCES);
+            isContentStream = true;
+        }
+        else if (COSName.FORM.equals(stream.getCOSName(COSName.SUBTYPE)) ||
+                COSName.PATTERN.equals(stream.getCOSName(COSName.TYPE)))
+        {
+            if (stream.containsKey(COSName.RESOURCES))
+            {
+                resourcesDic = (COSDictionary) stream.getDictionaryObject(COSName.RESOURCES);
+            }
+            isContentStream = true;
+        }
+        else if (COSName.THUMB.equals(key))
+        {
+            resourcesDic = null;
+            isThumb = true;
+        }
+        else if (COSName.IMAGE.equals((stream).getCOSName(COSName.SUBTYPE)))
+        {
+            // not to be used for /Thumb, even if it contains /Subtype /Image
+            Object resourcesObj = path.getParentPath().getParentPath().getLastPathComponent();
+            resourcesDic = (COSDictionary) getUnderneathObject(resourcesObj);
+        }
+        StreamPane streamPane = new StreamPane(stream, isContentStream, isThumb, resourcesDic);
+        replaceRightComponent(streamPane.getPanel());
+    }
+
+    private void showFont(Object selectedNode, TreePath path)
+    {
+        COSName fontName = getNodeKey(selectedNode);
+        COSDictionary resourceDic = (COSDictionary) getUnderneathObject(path.getParentPath().getParentPath().getLastPathComponent());
+
+        FontEncodingPaneController fontEncodingPaneController = new FontEncodingPaneController(fontName, resourceDic);
+        JPanel pane = fontEncodingPaneController.getPane();
+        if (pane == null)
+        {
+            // unsupported font type
+            replaceRightComponent(jScrollPane2);
+            return;
+        }
+        replaceRightComponent(pane);
+    }
+
+    // replace the right component while keeping divider position
+    private void replaceRightComponent(Component pane)
+    {
+        int div = jSplitPane1.getDividerLocation();
+        jSplitPane1.setRightComponent(pane);
+        jSplitPane1.setDividerLocation(div);
+    }
+
+    private void showString(Object selectedNode)
+    {
+        COSString string = (COSString)getUnderneathObject(selectedNode);
+        replaceRightComponent(new StringPane(string).getPane());
+    }
+
+    private COSName getNodeKey(Object selectedNode)
+    {
+        if (selectedNode instanceof MapEntry)
+        {
+            return ((MapEntry) selectedNode).getKey();
+        }
+        return null;
+    }
+
+    private Object getUnderneathObject(Object selectedNode)
+    {
+        if (selectedNode instanceof MapEntry)
+        {
+            selectedNode = ((MapEntry) selectedNode).getValue();
+        }
+        else if (selectedNode instanceof ArrayEntry)
+        {
+            selectedNode = ((ArrayEntry) selectedNode).getValue();
+        }
+        else if (selectedNode instanceof PageEntry)
+        {
+            selectedNode = ((PageEntry) selectedNode).getDict();
+        }
+
+        if (selectedNode instanceof COSObject)
+        {
+            selectedNode = ((COSObject) selectedNode).getObject();
+        }
+        return selectedNode;
+    }
+
+    private String convertToString( Object selectedNode )
+    {
+        String data = null;
+        if(selectedNode instanceof COSBoolean)
+        {
+            data = "" + ((COSBoolean)selectedNode).getValue();
+        }
+        else if( selectedNode instanceof COSFloat )
+        {
+            data = "" + ((COSFloat)selectedNode).floatValue();
+        }
+        else if( selectedNode instanceof COSNull )
+        {
+            data = "null";
+        }
+        else if( selectedNode instanceof COSInteger )
+        {
+            data = "" + ((COSInteger)selectedNode).intValue();
+        }
+        else if( selectedNode instanceof COSName )
+        {
+            data = "" + ((COSName)selectedNode).getName();
+        }
+        else if( selectedNode instanceof COSString )
+        {
+            String text = ((COSString) selectedNode).getString();
+            // display unprintable strings as hex
+            for (char c : text.toCharArray())
+            {
+                if (Character.isISOControl(c))
+                {
+                    text = "<" + ((COSString) selectedNode).toHexString() + ">";
+                    break;
+                }
+            }
+            data = "" + text;
+        }
+        else if( selectedNode instanceof COSStream )
+        {
+            try
+            {
+                COSStream stream = (COSStream)selectedNode;
+                InputStream ioStream = stream.createInputStream();
+                ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
+                byte[] buffer = new byte[1024];
+                int amountRead;
+                while( (amountRead = ioStream.read( buffer, 0, buffer.length ) ) != -1 )
+                {
+                    byteArray.write( buffer, 0, amountRead );
+                }
+                data = byteArray.toString();
+            }
+            catch( IOException e )
+            {
+                throw new RuntimeException(e);
+            }
+        }
+        else if( selectedNode instanceof MapEntry )
+        {
+            data = convertToString( ((MapEntry)selectedNode).getValue() );
+        }
+        else if( selectedNode instanceof ArrayEntry )
+        {
+            data = convertToString( ((ArrayEntry)selectedNode).getValue() );
+        }
+        return data;
+    }
+
+    private void exitMenuItemActionPerformed(ActionEvent evt)
+    {
+        if( document != null )
+        {
+            try
+            {
+                document.close();
+                if (!currentFilePath.startsWith("http"))
+                {
+                    recentFiles.addFile(currentFilePath);
+                }
+                recentFiles.close();
+            }
+            catch( IOException e )
+            {
+                throw new RuntimeException(e);
+            }
+        }
+        System.exit(0);
+    }
+
+    /**
+     * Exit the Application.
+     */
+    private void exitForm(WindowEvent evt)
+    {
+        if( document != null )
+        {
+            try
+            {
+                document.close();
+                if (!currentFilePath.startsWith("http"))
+                {
+                    recentFiles.addFile(currentFilePath);
+                }
+                recentFiles.close();
+            }
+            catch( IOException e )
+            {
+                throw new RuntimeException(e);
+            }
+        }
+        System.exit(0);
+    }
+
+    /**
+     * Entry point.
+     * 
+     * @param args the command line arguments
+     * @throws Exception If anything goes wrong.
+     */
+    public static void main(String[] args) throws Exception
+    {
+        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+        System.setProperty("apple.laf.useScreenMenuBar", "true");
+
+        // handle uncaught exceptions
+        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()
+        {
+            @Override
+            public void uncaughtException(Thread thread, Throwable throwable)
+            {
+                new ErrorDialog(throwable).setVisible(true);
+            }
+        });
+        
+        final PDFDebugger viewer = new PDFDebugger();
+        
+        // open file, if any
+        String filename = null;
+        String password = "";
+        
+        for( int i = 0; i < args.length; i++ )
+        {
+            if( args[i].equals( PASSWORD ) )
+            {
+                i++;
+                if( i >= args.length )
+                {
+                    usage();
+                }
+                password = args[i];
+            }
+            else
+            {
+                filename = args[i];
+            }
+        }
+        
+        if (filename != null)
+        {
+            File file = new File(filename);
+            if (file.exists())
+            {
+                viewer.readPDFFile( filename, password );
+            }
+        }
+        viewer.setVisible(true);
+    }
+
+    private void readPDFFile(String filePath, String password) throws IOException
+    {
+        File file = new File(filePath);
+        readPDFFile(file, password);
+    }
+    
+    private void readPDFFile(File file, String password) throws IOException
+    {
+        if( document != null )
+        {
+            document.close();
+            if (!currentFilePath.startsWith("http"))
+            {
+                recentFiles.addFile(currentFilePath);
+            }
+        }
+        currentFilePath = file.getPath();
+        recentFiles.removeFile(file.getPath());
+        parseDocument( file, password );
+        
+        initTree();
+        
+        if (IS_MAC_OS)
+        {
+            setTitle(file.getName());
+            getRootPane().putClientProperty("Window.documentFile", file);
+        }
+        else
+        {
+            setTitle("PDF Debugger - " + file.getAbsolutePath());
+        }
+        addRecentFileItems();
+    }
+    
+    private void readPDFurl(String urlString, String password) throws IOException
+    {
+        if (document != null)
+        {
+            document.close();
+            if (!currentFilePath.startsWith("http"))
+            {
+                recentFiles.addFile(currentFilePath);
+            }
+        }
+        currentFilePath = urlString;
+        URL url = new URL(urlString);
+        document = PDDocument.load(url.openStream(), password);
+
+        initTree();
+
+        if (IS_MAC_OS)
+        {
+            setTitle(urlString);
+        }
+        else
+        {
+            setTitle("PDF Debugger - " + urlString);
+        }
+        addRecentFileItems();
+    }
+    
+    private void initTree()
+    {
+        TreeStatus treeStatus = new TreeStatus(document.getDocument().getTrailer());
+        statusPane.updateTreeStatus(treeStatus);
+        
+        if (isPageMode)
+        {
+            File file = new File(currentFilePath);
+            DocumentEntry documentEntry = new DocumentEntry(document, file.getName());
+            tree.setModel(new PDFTreeModel(documentEntry));
+            // Root/Pages/Kids/[0] is not always the first page, so use the first row instead:
+            tree.setSelectionPath(tree.getPathForRow(1));
+        }
+        else
+        {
+            tree.setModel(new PDFTreeModel(document));
+            tree.setSelectionPath(treeStatus.getPathForString("Root"));
+        }
+    }
+    
+    /**
+     * This will parse a document.
+     *
+     * @param file The file addressing the document.
+     *
+     * @throws IOException If there is an error parsing the document.
+     */
+    private void parseDocument( File file, String password )throws IOException
+    {
+        document = PDDocument.load(file, password);
+    }
+
+    private void addRecentFileItems()
+    {
+        Action recentMenuAction = new AbstractAction()
+        {
+            @Override
+            public void actionPerformed(ActionEvent actionEvent)
+            {
+                String filePath = (String) ((JComponent) actionEvent.getSource()).getClientProperty("path");
+                try
+                {
+                    readPDFFile(filePath, "");
+                }
+                catch (Exception e)
+                {
+                    throw new RuntimeException(e);
+                }
+            }
+        };
+        if (!recentFiles.isEmpty())
+        {
+            recentFilesMenu.removeAll();
+            List<String> files = recentFiles.getFiles();
+            for (int i = files.size() - 1; i >= 0; i--)
+            {
+                String path = files.get(i);
+                String name = new File(path).getName();
+                JMenuItem recentFileMenuItem = new JMenuItem(name);
+                recentFileMenuItem.putClientProperty("path", path);
+                recentFileMenuItem.addActionListener(recentMenuAction);
+                recentFilesMenu.add(recentFileMenuItem);
+            }
+            recentFilesMenu.setEnabled(true);
+        }
+    }
+
+    /**
+     * This will print out a message telling how to use this utility.
+     */
+    private static void usage()
+    {
+        String message = "Usage: java -jar pdfbox-app-x.y.z.jar PDFDebugger [options] <inputfile>\n"
+                + "\nOptons:\n"
+                + "  -password <password> : Password to decrypt the document\n"
+                + "  <inputfile>          : The PDF document to be loaded\n";
+        
+        System.err.println(message);
+        System.exit(1);
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/PDFDebugger.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/ArrayEntry.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/ArrayEntry.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/ArrayEntry.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/ArrayEntry.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pdfbox.tools.gui;
+
+import org.apache.pdfbox.cos.COSBase;
+
+/**
+ * This is a simple class that will contain an index and a value.
+ *
+ * @author Ben Litchfield
+ */
+public class ArrayEntry
+{
+    private int index;
+    private COSBase value;
+    private COSBase item;
+
+    /**
+     * This will get the value for this entry.
+     *
+     * @return The value for this entry.
+     */
+    public COSBase getValue()
+    {
+        return value;
+    }
+
+    /**
+     * This will get the value for this entry.
+     *
+     * @return The value for this entry.
+     */
+    public COSBase getItem()
+    {
+        return item;
+    }
+
+    /**
+     * This will set the value for this entry.
+     *
+     * @param val the new value for this entry.
+     */
+    public void setValue(COSBase val)
+    {
+        this.value = val;
+    }
+
+    /**
+     * This will set the value for this entry.
+     *
+     * @param val the new value for this entry.
+     */
+    public void setItem(COSBase val)
+    {
+        this.item = val;
+    }
+
+    /**
+     * This will get the index of the array entry.
+     *
+     * @return The 0-based index into the array
+     */
+    public int getIndex()
+    {
+        return index;
+    }
+
+    /**
+     * This will set the index value.
+     *
+     * @param i The new index value.
+     */
+    public void setIndex(int i)
+    {
+        index = i;
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/ArrayEntry.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/DocumentEntry.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/DocumentEntry.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/DocumentEntry.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/DocumentEntry.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.pdfbox.tools.gui;
+
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+
+/**
+ * Represents an abstract view of a document in the tree view.
+ *
+ * @author John Hewson
+ */
+public class DocumentEntry
+{
+    private final PDDocument doc;
+    private final String filename;
+    
+    public DocumentEntry(PDDocument doc, String filename)
+    {
+        this.doc = doc;
+        this.filename = filename;
+    }
+    
+    public int getPageCount()
+    {
+        return doc.getPages().getCount();
+    }
+    
+    public PageEntry getPage(int index)
+    {
+        PDPage page = doc.getPages().get(index);
+        return new PageEntry(page.getCOSObject(), index + 1);
+    }
+    
+    public int indexOf(PageEntry page)
+    {
+        return page.getPageNum() - 1;
+    }
+
+    @Override
+    public String toString()
+    {
+        return filename;
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/DocumentEntry.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/ErrorDialog.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/ErrorDialog.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/ErrorDialog.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/ErrorDialog.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,306 @@
+/*
+ * Copyright 2015 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pdfbox.tools.gui;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JEditorPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextPane;
+import javax.swing.KeyStroke;
+
+/**
+ * A dialog to display a runtime exception stack trace.
+ *
+ * @author Pinaki Poddar
+ *
+ * Modified from ErrorDialog.java and SwingHelper.java of the Apache OpenJPA
+ * <a href="https://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/openbooks/src/main/java/jpa/tools/swing/">jpa.tools.swing
+ * package</a>.
+ *
+ */
+@SuppressWarnings("serial")
+public class ErrorDialog extends JDialog
+{
+    private static final List<String> FILTERS = Arrays.asList(
+            "java.awt.",
+            "javax.swing.",
+            "sun.reflect.",
+            "java.util.concurrent.");
+    private static final Dimension MESSAGE_SIZE = new Dimension(800, 200);
+    private static final Dimension STACKTRACE_SIZE = new Dimension(800, 300);
+    private static final Dimension TOTAL_SIZE = new Dimension(800, 500);
+    private static final int BORDER_SIZE = 20;
+
+    private static final String NEWLINE = "\r\n";
+    private static final String INDENT = "    ";
+
+    private boolean showingDetails;
+    private boolean isFiltering = true;
+    private JComponent message;
+    private JComponent main;
+    private JScrollPane details;
+    private JTextPane stacktrace;
+    private final Throwable error;
+
+    /**
+     * Creates a modal dialog to display the given exception message.
+     *
+     * @param t the exception to display
+     */
+    public ErrorDialog(Throwable t)
+    {
+        this(null, null, t);
+    }
+
+    /**
+     * Creates a modal dialog to display the given exception message.
+     *
+     * @param owner if non-null, then the dialog is positioned (centered) w.r.t. this component
+     * @param t the exception to display
+     */
+    public ErrorDialog(JComponent owner, Throwable t)
+    {
+        this(owner, null, t);
+    }
+
+    /**
+     * Creates a modal dialog to display the given exception message.
+     *
+     * @param owner if non-null, then the dialog is positioned (centered) w.r.t. this component
+     * @param icon the icon to display
+     * @param t the exception to display
+     */
+    public ErrorDialog(JComponent owner, Icon icon, Throwable t)
+    {
+        setTitle(t.getClass().getName());
+        setModal(true);
+        if (icon instanceof ImageIcon)
+        {
+            setIconImage(((ImageIcon) icon).getImage());
+        }
+        setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+        error = t;
+        message = createErrorMessage(error);
+        main = createContent();
+        getContentPane().add(main);
+
+        pack();
+        position(this, owner);
+    }
+
+    /**
+     * Position the given component at the center of the given parent component or physical screen.
+     *
+     * @param c the component to be positioned
+     * @param parent the component whose center will match the center of the given component. If
+     * null, the given component will match the screen center.
+     *
+     */
+    static void position(Component c, Component parent)
+    {
+        Dimension d = c.getPreferredSize();
+        if (parent == null)
+        {
+            Dimension s = Toolkit.getDefaultToolkit().getScreenSize();
+            c.setLocation(s.width / 2 - d.width / 2, s.height / 2 - d.height / 2);
+        }
+        else
+        {
+            Point p = parent.getLocationOnScreen();
+            int pw = parent.getWidth();
+            int ph = parent.getHeight();
+            c.setLocation(p.x + pw / 2 - d.width / 2, p.y + ph / 2 - d.height / 2);
+        }
+    }
+
+    /**
+     * Creates the display with the top-level exception message followed by a pane (that toggles)
+     * for detailed stack traces.
+     *
+     * @param t a non-null exception
+     */
+    final JComponent createContent()
+    {
+        final JButton showDetails = new JButton("Show Details >>");
+        showDetails.addActionListener(new ActionListener()
+        {
+            @Override
+            public void actionPerformed(ActionEvent e)
+            {
+                if (showingDetails)
+                {
+                    main.remove(details);
+                    main.validate();
+                    main.setPreferredSize(MESSAGE_SIZE);
+                }
+                else
+                {
+                    if (details == null)
+                    {
+                        details = createDetailedMessage(error);
+                        StringBuilder buffer = new StringBuilder();
+                        stacktrace.setText(generateStackTrace(error, buffer).toString());
+                        stacktrace.setCaretPosition(0);
+                        stacktrace.setBackground(main.getBackground());
+                        stacktrace.setPreferredSize(STACKTRACE_SIZE);
+                    }
+                    main.add(details, BorderLayout.CENTER);
+                    main.validate();
+                    main.setPreferredSize(TOTAL_SIZE);
+                }
+                showingDetails = !showingDetails;
+                showDetails.setText(showingDetails ? "<< Hide Details" : "Show Details >>");
+                ErrorDialog.this.pack();
+            }
+        });
+        JPanel messagePanel = new JPanel();
+
+        final JCheckBox filter = new JCheckBox("Filter stack traces");
+        filter.setSelected(isFiltering);
+        filter.addActionListener(new ActionListener()
+        {
+            @Override
+            public void actionPerformed(ActionEvent e)
+            {
+                isFiltering = filter.isSelected();
+                StringBuilder buffer = new StringBuilder();
+                stacktrace.setText(generateStackTrace(error, buffer).toString());
+                stacktrace.setCaretPosition(0);
+                stacktrace.repaint();
+            }
+        });
+        message.setBackground(messagePanel.getBackground());
+        JPanel buttonPanel = new JPanel();
+        buttonPanel.add(Box.createHorizontalStrut(BORDER_SIZE));
+        buttonPanel.add(showDetails);
+        buttonPanel.add(filter);
+        buttonPanel.add(Box.createHorizontalGlue());
+        messagePanel.setLayout(new BorderLayout());
+        messagePanel.setBorder(BorderFactory.createEmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE));
+        messagePanel.add(message, BorderLayout.CENTER);
+        messagePanel.add(buttonPanel, BorderLayout.SOUTH);
+        messagePanel.setPreferredSize(MESSAGE_SIZE);
+
+        JPanel panel = new JPanel();
+        panel.setLayout(new BorderLayout());
+        panel.add(messagePanel, BorderLayout.NORTH);
+        
+        // allow closing with ESC
+        ActionListener actionListener = new ActionListener()
+        {
+            @Override
+            public void actionPerformed(ActionEvent actionEvent)
+            {
+                dispose();
+            }
+        };
+        KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
+        panel.registerKeyboardAction(actionListener, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW);        
+        
+        return panel;
+    }
+
+    /**
+     * Creates a non-editable widget to display the error message.
+     *
+     */
+    final JComponent createErrorMessage(Throwable t)
+    {
+        String txt = t.getLocalizedMessage();
+        JEditorPane msg = new JEditorPane();
+        msg.setContentType("text/plain");
+        msg.setEditable(false);
+        msg.setText(txt);
+        return msg;
+    }
+
+    /**
+     * Creates a non-editable widget to display the detailed stack trace.
+     */
+    JScrollPane createDetailedMessage(Throwable t)
+    {
+        stacktrace = new JTextPane();
+        stacktrace.setEditable(false);
+        JScrollPane pane = new JScrollPane(stacktrace,
+                JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+        return pane;
+    }
+
+    /**
+     * Recursively print the stack trace on the given buffer.
+     */
+    StringBuilder generateStackTrace(Throwable t, StringBuilder buffer)
+    {
+        buffer.append(t.getClass().getName()).append(": ").append(t.getMessage()).append(NEWLINE);
+        buffer.append(toString(t.getStackTrace()));
+        Throwable cause = t.getCause();
+        if (cause != null && !cause.equals(t))
+        {
+            buffer.append("Caused by: ");
+            generateStackTrace(cause, buffer);
+        }
+        return buffer;
+    }
+
+    StringBuilder toString(StackTraceElement[] traces)
+    {
+        StringBuilder err = new StringBuilder();
+        for (StackTraceElement e : traces)
+        {
+            if (!isFiltering || !isSuppressed(e.getClassName()))
+            {
+                String str = e.toString();
+                err.append(INDENT).append(str).append(NEWLINE);
+            }
+        }
+        return err;
+    }
+
+    /**
+     * Affirms if the error messages from the given class name is to be suppressed.
+     */
+    private boolean isSuppressed(String className)
+    {
+        for (String s : FILTERS)
+        {
+            if (className.startsWith(s))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/ErrorDialog.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/MapEntry.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/MapEntry.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/MapEntry.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/MapEntry.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pdfbox.tools.gui;
+
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSName;
+
+
+/**
+ * This is a simple class that will contain a key and a value.
+ *
+ * @author Ben Litchfield
+ */
+public class MapEntry
+{
+    private COSName key;
+    private COSBase value;
+    private COSBase item;
+
+    /**
+     * Get the key for this entry.
+     *
+     * @return The entry's key.
+     */
+    public COSName getKey()
+    {
+        return key;
+    }
+
+    /**
+     * This will set the key for this entry.
+     *
+     * @param k the new key for this entry.
+     */
+    public void setKey(COSName k)
+    {
+        key = k;
+    }
+
+    /**
+     * This will get the value for this entry.
+     *
+     * @return The value for this entry.
+     */
+    public COSBase getValue()
+    {
+        return value;
+    }
+
+    /**
+     * This will get the value for this entry.
+     *
+     * @return The value for this entry.
+     */
+    public COSBase getItem()
+    {
+        return item;
+    }
+
+    /**
+     * This will set the value for this entry.
+     *
+     * @param val the new value for this entry.
+     */
+    public void setValue(COSBase val)
+    {
+        this.value = val;
+    }
+
+    /**
+     * This will set the value for this entry.
+     *
+     * @param val the new value for this entry.
+     */
+    public void setItem(COSBase val)
+    {
+        this.item = val;
+    }
+
+    /**
+     * This will output a string representation of this class.
+     *
+     * @return A string representation of this class.
+     */
+    @Override
+    public String toString()
+    {
+        if (key != null)
+        {
+            return key.getName();
+        }
+        return "(null)";
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/gui/MapEntry.java
------------------------------------------------------------------------------
    svn:eol-style = native