Index: oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/Explorer.java =================================================================== --- oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/Explorer.java (revision 1697622) +++ oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/Explorer.java (working copy) @@ -41,6 +41,7 @@ import javax.swing.UIManager; import javax.swing.UIManager.LookAndFeelInfo; +import org.apache.commons.io.IOUtils; import org.apache.jackrabbit.oak.plugins.segment.file.FileStore.ReadOnlyStore; import org.apache.jackrabbit.oak.plugins.segment.file.JournalReader; @@ -67,14 +68,17 @@ } final String path = args[0]; - final ReadOnlyStore store = new ReadOnlyStore(new File(path)); final boolean skipSizeCheck = args.length == 2 && skip.equalsIgnoreCase(args[1]); javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { initLF(); - createAndShowGUI(path, store, skipSizeCheck); + try { + createAndShowGUI(path, skipSizeCheck); + } catch (IOException e) { + throw new RuntimeException(e); + } } }); } @@ -93,25 +97,27 @@ } } - private void createAndShowGUI(final String path, final ReadOnlyStore store, boolean skipSizeCheck) { + private void createAndShowGUI(final String path, boolean skipSizeCheck) + throws IOException { + + JTextArea log = new JTextArea(5, 20); + log.setMargin(new Insets(5, 5, 5, 5)); + log.setLineWrap(true); + log.setEditable(false); + + final NodeStoreTree treePanel = new NodeStoreTree(path, log, skipSizeCheck); + final JFrame frame = new JFrame("Explore " + path + " @head"); frame.addWindowListener(new java.awt.event.WindowAdapter() { @Override public void windowClosing(java.awt.event.WindowEvent windowEvent) { - store.close(); + IOUtils.closeQuietly(treePanel); System.exit(0); } }); JPanel content = new JPanel(new GridBagLayout()); - JTextArea log = new JTextArea(5, 20); - log.setMargin(new Insets(5, 5, 5, 5)); - log.setLineWrap(true); - log.setEditable(false); - - final NodeStoreTree treePanel = new NodeStoreTree(store, log, skipSizeCheck); - GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; c.weightx = 1; @@ -126,6 +132,19 @@ JMenuBar menuBar = new JMenuBar(); menuBar.setMargin(new Insets(2, 2, 2, 2)); + JMenuItem menuReopen = new JMenuItem("Reopen"); + menuReopen.setMnemonic(KeyEvent.VK_R); + menuReopen.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ev) { + try { + treePanel.reopen(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }); + JMenuItem menuCompaction = new JMenuItem("Time Machine"); menuCompaction.setMnemonic(KeyEvent.VK_T); menuCompaction.addActionListener(new ActionListener() { @@ -221,6 +240,8 @@ } }); + menuBar.add(menuReopen); + menuBar.add(new JSeparator(JSeparator.VERTICAL)); menuBar.add(menuCompaction); menuBar.add(new JSeparator(JSeparator.VERTICAL)); menuBar.add(menuRefs); Index: oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/NodeStoreTree.java =================================================================== --- oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/NodeStoreTree.java (revision 1697622) +++ oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/NodeStoreTree.java (working copy) @@ -24,6 +24,7 @@ import static com.google.common.escape.Escapers.builder; import java.awt.GridLayout; +import java.io.Closeable; import java.io.File; import java.io.IOException; import java.util.Collections; @@ -67,9 +68,11 @@ import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry; import org.apache.jackrabbit.oak.spi.state.NodeState; -public class NodeStoreTree extends JPanel implements TreeSelectionListener { +public class NodeStoreTree extends JPanel implements TreeSelectionListener, + Closeable { - private final ReadOnlyStore store; + private final String path; + private ReadOnlyStore store; private DefaultTreeModel treeModel; private final JTree tree; @@ -81,32 +84,31 @@ // TODO make this configurable private final boolean cacheNodeState = false; - public NodeStoreTree(ReadOnlyStore store, JTextArea log, boolean skipSizeCheck) { + public NodeStoreTree(String path, JTextArea log, boolean skipSizeCheck) + throws IOException { super(new GridLayout(1, 0)); - this.store = store; + this.path = path; this.log = log; - - this.index = store.getTarReaderIndex(); - this.sizeCache = new HashMap(); this.skipSizeCheck = skipSizeCheck; - DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode( - new NamePathModel("/", "/", store.getHead(), sizeCache, - skipSizeCheck, store, cacheNodeState), true); - treeModel = new DefaultTreeModel(rootNode); - addChildren(rootNode); - - tree = new JTree(treeModel); + tree = new JTree(); tree.getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION); tree.setShowsRootHandles(true); tree.addTreeSelectionListener(this); tree.setExpandsSelectedPaths(true); + refreshStore(); + refreshModel(); + JScrollPane scrollPane = new JScrollPane(tree); add(scrollPane); } + private void refreshStore() throws IOException { + this.store = new ReadOnlyStore(new File(path)); + } + private void refreshModel() { index = store.getTarReaderIndex(); sizeCache = new HashMap(); @@ -115,6 +117,13 @@ skipSizeCheck, store, cacheNodeState), true); treeModel = new DefaultTreeModel(rootNode); addChildren(rootNode); + tree.setModel(treeModel); + } + + public void reopen() throws IOException { + close(); + refreshStore(); + refreshModel(); } @Override @@ -802,4 +811,9 @@ } + @Override + public void close() throws IOException { + store.close(); + } + }