Skip to content

Instantly share code, notes, and snippets.

@kBashar
Created March 12, 2015 04:39
Show Gist options
  • Save kBashar/5ad0f487b51a9c5fcd73 to your computer and use it in GitHub Desktop.
Save kBashar/5ad0f487b51a9c5fcd73 to your computer and use it in GitHub Desktop.
This is Customized PDFDebugger That shows understandable Tree string for tree nodes when clicked
package org.apache.pdfbox;
import org.apache.pdfbox.cos.*;
import org.apache.pdfbox.pdfviewer.ArrayEntry;
import org.apache.pdfbox.pdfviewer.MapEntry;
import org.apache.pdfbox.pdfviewer.PDFTreeCellRenderer;
import org.apache.pdfbox.pdfviewer.PDFTreeModel;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.util.ExtensionFileFilter;
import javax.swing.*;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Created by kbashar on 3/10/15.
*/
public class PDFDebuggerCustomized extends JFrame {
private File currentDir=new File(".");
private PDDocument document = null;
private static final String NONSEQ = "-nonSeq";
private static final String PASSWORD = "-password";
private static boolean useNonSeqParser = false;
/**
* Constructor.
*/
public PDFDebuggerCustomized()
{
initComponents();
}
/**
* This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
private void initComponents()
{
jSplitPane1 = new javax.swing.JSplitPane();
jScrollPane1 = new javax.swing.JScrollPane();
jTree1 = new javax.swing.JTree();
jScrollPane2 = new javax.swing.JScrollPane();
jTextPane1 = new javax.swing.JTextPane();
menuBar = new javax.swing.JMenuBar();
fileMenu = new javax.swing.JMenu();
openMenuItem = new javax.swing.JMenuItem();
saveMenuItem = new javax.swing.JMenuItem();
saveAsMenuItem = new javax.swing.JMenuItem();
exitMenuItem = new javax.swing.JMenuItem();
editMenu = new javax.swing.JMenu();
cutMenuItem = new javax.swing.JMenuItem();
copyMenuItem = new javax.swing.JMenuItem();
pasteMenuItem = new javax.swing.JMenuItem();
deleteMenuItem = new javax.swing.JMenuItem();
helpMenu = new javax.swing.JMenu();
contentsMenuItem = new javax.swing.JMenuItem();
aboutMenuItem = new javax.swing.JMenuItem();
jTree1.setCellRenderer( new PDFTreeCellRenderer() );
jTree1.setModel( null );
setTitle("PDFBox - PDF Viewer");
addWindowListener(new java.awt.event.WindowAdapter()
{
public void windowClosing(java.awt.event.WindowEvent evt)
{
exitForm(evt);
}
});
jScrollPane1.setBorder(new javax.swing.border.BevelBorder(javax.swing.border.BevelBorder.RAISED));
jScrollPane1.setPreferredSize(new java.awt.Dimension(300, 500));
jTree1.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener()
{
public void valueChanged(javax.swing.event.TreeSelectionEvent evt)
{
jTree1ValueChanged(evt);
}
});
jScrollPane1.setViewportView(jTree1);
jSplitPane1.setRightComponent(jScrollPane2);
jScrollPane2.setPreferredSize(new java.awt.Dimension(300, 500));
jScrollPane2.setViewportView(jTextPane1);
jSplitPane1.setLeftComponent(jScrollPane1);
JScrollPane documentScroller = new JScrollPane();
//documentScroller.setPreferredSize( new Dimension( 300, 500 ) );
documentScroller.setViewportView( documentPanel );
getContentPane().add( jSplitPane1, java.awt.BorderLayout.CENTER );
fileMenu.setText("File");
openMenuItem.setText("Open");
openMenuItem.setToolTipText("Open PDF file");
openMenuItem.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
openMenuItemActionPerformed(evt);
}
});
fileMenu.add(openMenuItem);
saveMenuItem.setText("Save");
saveAsMenuItem.setText("Save As ...");
exitMenuItem.setText("Exit");
exitMenuItem.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
exitMenuItemActionPerformed(evt);
}
});
fileMenu.add(exitMenuItem);
menuBar.add(fileMenu);
editMenu.setText("Edit");
cutMenuItem.setText("Cut");
editMenu.add(cutMenuItem);
copyMenuItem.setText("Copy");
editMenu.add(copyMenuItem);
pasteMenuItem.setText("Paste");
editMenu.add(pasteMenuItem);
deleteMenuItem.setText("Delete");
editMenu.add(deleteMenuItem);
helpMenu.setText("Help");
contentsMenuItem.setText("Contents");
helpMenu.add(contentsMenuItem);
aboutMenuItem.setText("About");
helpMenu.add(aboutMenuItem);
setJMenuBar(menuBar);
java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
setBounds((screenSize.width-700)/2, (screenSize.height-600)/2, 700, 600);
}//GEN-END:initComponents
private void openMenuItemActionPerformed(java.awt.event.ActionEvent evt)
{
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(currentDir);
ExtensionFileFilter pdfFilter = new ExtensionFileFilter(new String[] {"pdf", "PDF"}, "PDF Files");
chooser.setFileFilter(pdfFilter);
int result = chooser.showOpenDialog(PDFDebuggerCustomized.this);
if (result == JFileChooser.APPROVE_OPTION)
{
String name = chooser.getSelectedFile().getPath();
currentDir = new File(name).getParentFile();
try
{
readPDFFile(name, "");
}
catch (Exception e)
{
e.printStackTrace();
}
}
}//GEN-LAST:event_openMenuItemActionPerformed
private void jTree1ValueChanged(javax.swing.event.TreeSelectionEvent evt)
{
TreePath path = jTree1.getSelectionPath();
if (path != null)
{
try
{
Object selectedNode = path.getLastPathComponent();
String data=convertToString(selectedNode);
if (data != null)
{
jTextPane1.setText(data);
}
else
{
jTextPane1.setText( "" );
}
printPath(path);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}//GEN-LAST:event_jTree1ValueChanged
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 )
{
data = "" + ((COSString)selectedNode).getString();
}
else if( selectedNode instanceof COSStream )
{
try
{
COSStream stream = (COSStream)selectedNode;
InputStream ioStream = stream.getUnfilteredStream();
ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int amountRead = 0;
while( (amountRead = ioStream.read( buffer, 0, buffer.length ) ) != -1 )
{
byteArray.write( buffer, 0, amountRead );
}
data = byteArray.toString();
}
catch( IOException e )
{
e.printStackTrace();
}
}
else if( selectedNode instanceof MapEntry)
{
data = convertToString( ((MapEntry)selectedNode).getValue() );
}
else if( selectedNode instanceof ArrayEntry)
{
data = convertToString( ((ArrayEntry)selectedNode).getValue() );
}
return data;
}
private void printPath(TreePath path)
{
StringBuilder pathStringBuilder = new StringBuilder();
while (path.getParentPath()!=null)
{
Object object = path.getLastPathComponent();
pathStringBuilder.insert(0,"/"+getObjectName(object));
path = path.getParentPath();
}
pathStringBuilder.deleteCharAt(0);
System.out.println(pathStringBuilder.toString());
}
private String getObjectName(Object object)
{
String name = "";
if( object instanceof MapEntry )
{
MapEntry entry = (MapEntry)object;
COSName key = (COSName)entry.getKey();
name = key.getName();
}
else if( object instanceof ArrayEntry )
{
ArrayEntry entry = (ArrayEntry)object;
name = "[" + entry.getIndex() + "]";
}
else if( object instanceof COSDictionary )
{
COSDictionary dict = (COSDictionary)object;
if( object instanceof COSStream )
{
name = "Stream";
}
else
{
name = "Dictionary";
}
COSName type = (COSName)dict.getDictionaryObject( COSName.TYPE );
if( type != null )
{
name = name + "(" + type.getName();
COSName subType = (COSName)dict.getDictionaryObject( COSName.SUBTYPE );
if( subType != null )
{
name = name + ":" + subType.getName();
}
name = name + ")";
}
}
else if( object instanceof COSArray )
{
name="Array";
}
else
{
throw new RuntimeException( "Unknown COS type " + object.getClass().getName() );
}
return name;
}
private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt)
{
if( document != null )
{
try
{
document.close();
}
catch( IOException io )
{
io.printStackTrace();
}
}
System.exit(0);
}
/**
* Exit the Application.
*/
private void exitForm(java.awt.event.WindowEvent evt)
{
if( document != null )
{
try
{
document.close();
}
catch( IOException io )
{
io.printStackTrace();
}
}
System.exit(0);
}
/**
* @param args the command line arguments
*
* @throws Exception If anything goes wrong.
*/
public static void main(String[] args) throws Exception
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
PDFDebuggerCustomized viewer = new PDFDebuggerCustomized();
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];
}
if( args[i].equals( NONSEQ ) )
{
useNonSeqParser = true;
}
else
{
filename = args[i];
}
}
if (filename != null)
{
viewer.readPDFFile( filename, password );
}
viewer.setVisible(true);
}
private void readPDFFile(String file, String password) throws Exception
{
if( document != null )
{
document.close();
}
File f = new File( file );
parseDocument( f, password );
TreeModel model=new PDFTreeModel(document);
jTree1.setModel(model);
setTitle( "PDFBox - " + f.getAbsolutePath() );
}
/**
* 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
{
if (useNonSeqParser)
{
document = PDDocument.loadNonSeq(file, null, password);
}
else
{
document = PDDocument.load( file );
if( document.isEncrypted() )
{
try
{
document.decrypt( password );
}
catch( org.apache.pdfbox.exceptions.CryptographyException e )
{
e.printStackTrace();
}
}
}
}
/**
* This will print out a message telling how to use this utility.
*/
private static void usage()
{
System.err.println(
"usage: java -jar pdfbox-app-x.y.z.jar PDFDebugger [OPTIONS] <input-file>\n" +
" -password <password> Password to decrypt the document\n" +
" -nonSeq Enables the new non-sequential parser\n" +
" <input-file> The PDF document to be loaded\n"
);
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JMenuItem aboutMenuItem;
private javax.swing.JMenuItem contentsMenuItem;
private javax.swing.JMenuItem copyMenuItem;
private javax.swing.JMenuItem cutMenuItem;
private javax.swing.JMenuItem deleteMenuItem;
private javax.swing.JMenu editMenu;
private javax.swing.JMenuItem exitMenuItem;
private javax.swing.JMenu fileMenu;
private javax.swing.JMenu helpMenu;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JSplitPane jSplitPane1;
private javax.swing.JTextPane jTextPane1;
private javax.swing.JTree jTree1;
private javax.swing.JMenuBar menuBar;
private javax.swing.JMenuItem openMenuItem;
private javax.swing.JMenuItem pasteMenuItem;
private javax.swing.JMenuItem saveAsMenuItem;
private javax.swing.JMenuItem saveMenuItem;
private JPanel documentPanel = new JPanel();
// End of variables declaration//GEN-END:variables
}
@kBashar
Copy link
Author

kBashar commented Mar 12, 2015

Here only two methods is written by me. All other codes are from PDFDebugger class of PDFBox

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment