package com.laytonsmith.tools.pnviewer; import com.laytonsmith.PureUtilities.ClassLoading.ClassDiscovery; import com.laytonsmith.PureUtilities.UI.TextDialog; import com.laytonsmith.PureUtilities.Common.AutoFlushObjectOutputStream; import com.laytonsmith.PureUtilities.Common.MutableObject; import com.laytonsmith.PureUtilities.Common.StackTraceUtils; import com.laytonsmith.PureUtilities.Common.StreamUtils; import com.laytonsmith.PureUtilities.Common.StringUtils; import com.laytonsmith.PureUtilities.Common.TemplateBuilder; import com.laytonsmith.PureUtilities.Common.UIUtils; import com.laytonsmith.abstraction.Implementation; import com.laytonsmith.core.CHVersion; import com.laytonsmith.core.constructs.CNull; import com.laytonsmith.core.constructs.Construct; import com.laytonsmith.core.constructs.Target; import com.laytonsmith.core.exceptions.MarshalException; import com.laytonsmith.core.functions.DataHandling; import com.laytonsmith.persistence.DataSourceException; import com.laytonsmith.persistence.PersistenceNetwork; import com.laytonsmith.persistence.io.ConnectionMixinFactory; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.EOFException; import java.io.File; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.management.ManagementFactory; import java.lang.reflect.InvocationTargetException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketTimeoutException; import java.net.URI; import java.net.URISyntaxException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.ImageIO; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; /** * */ public class PNViewer extends javax.swing.JFrame { private Map<String, String> data; private VirtualPersistenceNetwork network; private Boolean isLocalConfig = null; // Remote connection data private Thread remoteSocketThread; private Socket remoteSocket; private ObjectOutputStream remoteOutput; private ObjectInputStream remoteInput; private ConfigurationLoaderDialog loaderDialog; // Local connection data private String localPath; /** * Creates new form PNViewer */ public PNViewer() { initComponents(); setTitle("Persistence Network Viewer"); configurationFromLabel.setText(""); namespaceLabel.setText(""); keyLabel.setText(""); valueTypeLabel.setText(""); sourceLabel.setText(""); try { setIconImage(ImageIO.read(PNViewer.class.getResourceAsStream("GearIcon.png"))); } catch (IOException ex) { Logger.getLogger(PNViewer.class.getName()).log(Level.SEVERE, null, ex); } setStatus("Waiting for configuration to be loaded...", false); this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); this.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { if (remoteSocketThread != null && remoteSocketThread.isAlive()) { int sel = JOptionPane.showConfirmDialog(PNViewer.this, "A connection to the remote server is still active, are you sure you wish to disconnect?", "Confirm", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); if (sel == JOptionPane.YES_OPTION) { System.exit(0); } } else { System.exit(0); } } }); loaderDialog = new ConfigurationLoaderDialog(PNViewer.this, true); loaderDialog.setLoaderDialogFinish(new ConfigurationLoaderDialog.LoaderDialogFinish() { @Override public void data(boolean isLocal, String localPath, String host, int port, String password, String remoteFile) { isLocalConfig = isLocal; if (isLocal) { loadFromLocal(localPath); } else { loadFromRemote(host, port, password, remoteFile); } } }); loadFromConfigurationMenu.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { UIUtils.centerWindowOnWindow(loaderDialog, PNViewer.this); loaderDialog.setVisible(true); } }); closeRemoteConnectionMenu.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (remoteSocketThread == null) { showError("No remote connection is established."); } else { setStatus("Closing remote connection...", false); try { remoteOutput.writeUTF("DISCONNECT"); } catch (IOException ex) { log(ex); //Fallback in case a clean close doesn't work. try { remoteSocket.close(); } catch (IOException ex1) { // } } remoteSocketThread.interrupt(); } } }); keyTree.addTreeSelectionListener(new TreeSelectionListener() { @Override public void valueChanged(TreeSelectionEvent e) { try { String[] key = new String[e.getNewLeadSelectionPath().getPathCount() - 1]; for (int i = 1; i < e.getNewLeadSelectionPath().getPathCount(); i++) { key[i - 1] = (String) ((DefaultMutableTreeNode) e.getNewLeadSelectionPath().getPathComponent(i)).getUserObject(); } showData(join(key), data.get(join(key))); } catch (NullPointerException ex) { // Ignore } } }); keyTree.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { int selRow = keyTree.getRowForLocation(e.getX(), e.getY()); TreePath selPath = keyTree.getPathForLocation(e.getX(), e.getY()); if (selRow != -1) { if (SwingUtilities.isRightMouseButton(e)) { StreamUtils.GetSystemOut().println("Right click on " + selPath); } } } }); manageBookmarksMenu.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { ManageBookmarksDialog bd = new ManageBookmarksDialog(PNViewer.this, true); UIUtils.centerWindowOnWindow(bd, PNViewer.this); bd.setVisible(true); } }); reloadButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (isLocalConfig == null) { showError("No configuration is loaded."); } else if (isLocalConfig == true) { loadFromLocal(localPath); } else { if (remoteSocketThread == null) { showError("Remote connection isn't established, cannot reload data"); } else { try { remoteOutput.writeUTF("LOAD-DATA"); } catch (IOException ex) { Logger.getLogger(PNViewer.class.getName()).log(Level.SEVERE, null, ex); } } } } }); aboutMenu.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { TemplateBuilder builder = new TemplateBuilder(); builder.addTemplate("version", new TemplateBuilder.Generator() { @Override public String generate(String... args) { return CHVersion.LATEST.toString(); } }); builder.addTemplate("implementation", new TemplateBuilder.Generator() { @Override public String generate(String... args) { try { return Implementation.GetServerType().getBranding(); } catch(Exception ex){ return "MethodScript"; } } }); builder.addTemplate("clientVersion", new TemplateBuilder.Generator() { @Override public String generate(String... args) { return Integer.toString(PROTOCOL_VERSION); } }); String text = builder.build(StreamUtils.GetString(PNViewer.class.getResourceAsStream("AboutDialog.html"))); TextDialog td = new TextDialog(PNViewer.this, true, text); UIUtils.centerWindowOnWindow(td, PNViewer.this); td.setVisible(true); } }); helpMenu.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { TemplateBuilder builder = new TemplateBuilder(); builder.addTemplate("wiki", new TemplateBuilder.Generator() { @Override public String generate(String... args) { return "http://wiki.sk89q.com/wiki/CommandHelper/Staged/" + args[0]; } }); builder.addTemplate("jarName", new TemplateBuilder.Generator() { @Override public String generate(String... args) { return new File(ClassDiscovery.GetClassContainer(PNViewer.class).getPath()).getName(); } }); String text = builder.build(StreamUtils.GetString(PNViewer.class.getResourceAsStream("HelpDialog.html"))); TextDialog td = new TextDialog(PNViewer.this, false, text); UIUtils.centerWindowOnWindow(td, PNViewer.this); td.setVisible(true); } }); // Map<String[], String> data = new HashMap<>(); // Map<String, String> dataSources = new HashMap<>(); // data.put(new String[]{"first"}, "\"1\""); // data.put(new String[]{"first", "first"}, "1"); // data.put(new String[]{"first", "second"}, "1"); // data.put(new String[]{"second", "first"}, "1"); // for(String[] key : data.keySet()){ // dataSources.put(join(key), "Test Source"); // } // displayData(data, dataSources); } private String join(String[] key) { return StringUtils.Join(key, "."); } private void showData(final String key, String value) { String[] split = key.split("\\."); String[] namespace = new String[split.length - 1]; String keyPart = null; for (int i = 0; i < split.length; i++) { if (i == split.length - 1) { keyPart = split[i]; } else { namespace[i] = split[i]; } } namespaceLabel.setText(join(namespace)); keyLabel.setText(keyPart); if (value == null) { sourceLabel.setText(""); valueTypeLabel.setText("(empty key)"); valueTextArea.setText(""); } else { sourceLabel.setText("(resolving)"); new Thread(new Runnable() { @Override public void run() { final String source = network.getKeySource(key.split("\\.")).toString(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { sourceLabel.setText(source); } }); } }).start(); Construct c = CNull.NULL; try { c = Construct.json_decode(value, Target.UNKNOWN); } catch (MarshalException ex) { Logger.getLogger(PNViewer.class.getName()).log(Level.SEVERE, null, ex); } valueTypeLabel.setText(new DataHandling.typeof().exec(Target.UNKNOWN, null, c).val()); valueTextArea.setText(c.val()); } } private void loadFromLocal(final String path) { localPath = path; new Thread(new Runnable() { @Override public void run() { setStatus("Loading from local file system", true); setProgress(null); try { final PersistenceNetwork pn = getPersistenceNetwork(path); VirtualPersistenceNetwork vpn = new VirtualPersistenceNetwork() { @Override public Map<String[], String> getAllData() throws DataSourceException { return pn.getNamespace(new String[0]); } @Override public URI getKeySource(String[] key) { return pn.getKeySource(key); } }; displayData(vpn); } catch (URISyntaxException | IOException | DataSourceException ex) { Logger.getLogger(PNViewer.class.getName()).log(Level.SEVERE, null, ex); showError(ex.getMessage()); } } }).start(); } /** * This version is the first thing sent across the wire. If the versions * don't match, the connection won't succeed. */ private static final int PROTOCOL_VERSION = 2; private void loadFromRemote(final String host, final int port, final String password, final String remoteFile) { remoteSocketThread = new Thread(new Runnable() { @Override public void run() { try { try (Socket s = new Socket()) { s.connect(new InetSocketAddress(host, port), 30000); remoteSocket = s; setStatus("Connected to remote server", true); setProgress(null); try { final ObjectOutputStream os = new AutoFlushObjectOutputStream(s.getOutputStream()); final ObjectInputStream is = new ObjectInputStream(s.getInputStream()); remoteOutput = os; remoteInput = is; // Set up our initial data log("Writing client version: " + PROTOCOL_VERSION); os.writeInt(PROTOCOL_VERSION); switch (is.readUTF()) { case "VERSION-OK": break; default: showError("The server does not support this client's version."); return; } os.writeUTF(password); switch (is.readUTF()) { case "PASSWORD-OK": log("Password accepted by server."); break; default: showError("Server rejected our password. Check the password and try again."); return; } os.writeUTF("SET-REMOTE-FILE"); os.writeUTF(remoteFile); final MutableObject<Map<String[], String>> data = new MutableObject<>(); final MutableObject<URI> sourceURI = new MutableObject<>(); VirtualPersistenceNetwork vpn = null; connection: while (!Thread.currentThread().isInterrupted() && s.isConnected()) { String serverCommand = is.readUTF(); switch (serverCommand) { case "DISCONNECT": break connection; case "FILE-OK": os.writeUTF("LOAD-DATA"); reloadButton.setEnabled(false); break; case "FILE-BAD": showError("Remote file doesn't exist, disconnecting."); break; case "LOAD-DATA": int size = is.readInt(); setStatus("Downloading data from server...", true); setProgress(0); byte[] bdata = new byte[size]; for (int i = 0; i < size; i++) { bdata[i] = is.readByte(); setProgress((int) ((((double) i) / ((double) size)) * 100)); } setStatus("Processing data from server", true); setProgress(null); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bdata)); try { Map<String[], String> d = (Map<String[], String>) ois.readObject(); data.setObject(d); vpn = new VirtualPersistenceNetwork() { Map<String, URI> sources = new HashMap<>(); @Override public Map<String[], String> getAllData() throws DataSourceException { return data.getObject(); } @Override public URI getKeySource(String[] key) { String kk = join(key); if (!sources.containsKey(kk)) { try { sourceURI.setObject(null); os.writeUTF("KEY-SOURCE"); os.writeUTF(kk); synchronized (sourceURI) { if (sourceURI.getObject() == null) { try { sourceURI.wait(); } catch (InterruptedException ex) { // } } } URI uri = sourceURI.getObject(); sources.put(kk, uri); } catch (IOException ex) { showError(ex.getMessage()); log(ex); } } return sources.get(kk); } }; try { displayData(vpn); setStatus("Done.", false); } catch (DataSourceException ex) { log(ex); showError(ex.getMessage()); } } catch (ClassNotFoundException ex) { log(ex); showError(ex.getMessage()); } reloadButton.setEnabled(true); break; case "KEY-SOURCE": try { URI uri = (URI) is.readObject(); sourceURI.setObject(uri); synchronized (sourceURI) { sourceURI.notifyAll(); } } catch (ClassNotFoundException ex) { log(ex); } break; case "LOAD-ERROR": String message = is.readUTF(); setStatus(message, false); showError(message); reloadButton.setEnabled(true); break; default: showError("Server sent unrecognized command, disconnecting."); log("Unrecognized command: " + serverCommand); break connection; } } log("Closing connection."); } catch (EOFException ex) { log(ex); showError("The server closed the connection unexpectedly."); } } catch (SocketTimeoutException ex) { showError("Connection timed out, check your settings and try again."); } finally { setStatus("Connection to remote server closed.", false); remoteOutput = null; remoteInput = null; reloadButton.setEnabled(true); } } catch (IOException ex) { showError(ex.getMessage()); Logger.getLogger(PNViewer.class.getName()).log(Level.SEVERE, null, ex); } remoteSocketThread = null; } }); remoteSocketThread.start(); } public static void startServer(int port, final String password) throws IOException { ServerSocket socket = new ServerSocket(port); log("Server started on port " + port + ". Type Ctrl+C to kill the server."); log("Process info: " + ManagementFactory.getRuntimeMXBean().getName()); log("Server version: " + PROTOCOL_VERSION); connection: while (true) { log("Persistence Network Viewers may now connect to this server."); final Socket s = socket.accept(); log("A client has connected from " + s.getInetAddress().toString()); new Thread(new Runnable() { @Override public void run() { Thread waitThread = null; try { final AtomicBoolean dataReceieved = new AtomicBoolean(false); final AtomicBoolean longTimeout = new AtomicBoolean(false); waitThread = new Thread(new Runnable() { @Override public void run() { try { while (true) { synchronized (dataReceieved) { dataReceieved.wait(longTimeout.get() ? 10 * 60 * 1000 : 10 * 1000); } if (dataReceieved.get() == false) { log("No response from client in too long, forcibly closing connection."); try { s.close(); } catch (IOException ex) { // } break; } dataReceieved.set(false); } } catch (InterruptedException ex) { // } } }); waitThread.start(); ObjectInputStream is = new ObjectInputStream(s.getInputStream()); ObjectOutputStream os = new AutoFlushObjectOutputStream(s.getOutputStream()); int protocolVersion = is.readInt(); if (protocolVersion != PROTOCOL_VERSION) { log("Client version unsupported: " + protocolVersion); os.writeUTF("VERSION-MISMATCH"); return; } else { log("Client version supported: " + protocolVersion); os.writeUTF("VERSION-OK"); } String clientPassword = is.readUTF(); if (!password.equals(clientPassword)) { log("Client supplied the wrong password, disconnecting."); os.writeUTF("PASSWORD-BAD"); os.writeUTF("DISCONNECT"); return; } else { if (!"".equals(password)) { log("Client supplied the correct password"); } os.writeUTF("PASSWORD-OK"); } // They have now authed correctly, so we can up the idle time. longTimeout.set(true); // Now we need to create instance variables for the remainder of // the connection, that is, the meat of the connection. String remoteFile = null; PersistenceNetwork pn = null; connected: while (s.isConnected()) { String command = is.readUTF(); log("Command received from client: " + command); dataReceieved.set(true); synchronized (dataReceieved) { dataReceieved.notifyAll(); } switch (command) { case "DISCONNECT": // Write the disconnect out to the client as well, so // the client will gracefully disconnect. os.writeUTF("DISCONNECT"); break connected; case "SET-REMOTE-FILE": remoteFile = is.readUTF(); log("File set to " + remoteFile); if (new File(remoteFile).exists()) { log("File accepted."); os.writeUTF("FILE-OK"); } else { log("File not accepted."); os.writeUTF("FILE-BAD"); os.writeUTF("DISCONNECT"); } break; case "LOAD-DATA": os.writeUTF("LOAD-DATA"); try { // Load the data from the PN, and send it on pn = getPersistenceNetwork(remoteFile); Map<String[], String> data = pn.getNamespace(new String[0]); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(data); oos.flush(); byte[] output = baos.toByteArray(); os.writeInt(output.length); os.write(output); } catch (URISyntaxException | DataSourceException ex) { os.writeUTF("LOAD-ERROR"); os.writeUTF(ex.getMessage()); log("Load error!"); log(ex); } break; case "KEY-SOURCE": os.writeUTF("KEY-SOURCE"); String key = is.readUTF(); if (pn == null) { log("pn is null, can't get key source"); os.writeUTF("DISCONNECT"); } else { log("Requested source for key: " + key); URI uri = pn.getKeySource(key.split("\\.")); log("Responding with: " + uri); os.writeObject(uri); } break; default: // Bad command, disconnect them. os.writeUTF("DISCONNECT"); break connected; } } } catch (IOException ex) { // Disconnected } finally { try { s.close(); } catch (IOException ex) { // } log("Client has disconnected."); if (waitThread != null) { waitThread.interrupt(); } } } }).start(); } } private static PersistenceNetwork getPersistenceNetwork(String configPath) throws URISyntaxException, IOException, DataSourceException { File config = new File(configPath); ConnectionMixinFactory.ConnectionMixinOptions options = new ConnectionMixinFactory.ConnectionMixinOptions(); options.setWorkingDirectory(config.getParentFile().getParentFile()); return new PersistenceNetwork(config, new URI("sqlite://" + new File(config.getParentFile().getParentFile(), "persistence.db").toString().replace('\\', '/')), options); } /** * Once the data is loaded, however that may take place, the data should be * sent here, which will load the data into the viewer. * * @param data */ private void displayData(VirtualPersistenceNetwork pn) throws DataSourceException { this.network = pn; final Map<String[], String> data = pn.getAllData(); final Map<String, String> dataSources = new HashMap<>(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { PNViewer.this.data = new HashMap<>(); DefaultTreeModel model = (DefaultTreeModel) keyTree.getModel(); DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot(); root.removeAllChildren(); for (String[] key : data.keySet()) { PNViewer.this.data.put(join(key), data.get(key)); DefaultMutableTreeNode node = root; outer: for (String n : key) { for (int i = 0; i < node.getChildCount(); i++) { DefaultMutableTreeNode at = (DefaultMutableTreeNode) node.getChildAt(i); if (n.equals(at.getUserObject())) { // This is our node, so recurse down this node = at; continue outer; } } // If we got here, then there is not an appropriate node at this level, so we needd // to create it. DefaultMutableTreeNode newChild = new DefaultMutableTreeNode(n); node.add(newChild); node = newChild; } } model.reload(root); setStatus("Data loaded.", false); } }); } /** * Sets the status label. If the current operation is happening because the * system is actively doing something, thinking should be set to true, and * the progress bar will be set to visible (but will keep its existing * state) otherwise, the progress bar is hidden. * * @param statusString * @param thinking */ private void setStatus(final String statusString, final boolean thinking) { Runnable r = new Runnable() { @Override public void run() { statusLabel.setText(statusString); statusProgressBar.setVisible(thinking); } }; if (SwingUtilities.isEventDispatchThread()) { r.run(); } else { try { SwingUtilities.invokeAndWait(r); } catch (InterruptedException | InvocationTargetException ex) { log(ex); } } } /** * Sets the progress bar percentage. * * @param i A percentage point, from 0 to 100. If null, it is set to be * indeterminate. */ private void setProgress(final Integer i) { Runnable r = new Runnable() { @Override public void run() { statusProgressBar.setValue(i == null ? 100 : i); statusProgressBar.setIndeterminate(i == null); } }; if (SwingUtilities.isEventDispatchThread()) { r.run(); } else { try { SwingUtilities.invokeAndWait(r); } catch (InterruptedException | InvocationTargetException ex) { log(ex); } } } private void showError(String message) { JOptionPane.showMessageDialog(this, message, "Error", JOptionPane.ERROR_MESSAGE); } private static void log(Throwable t) { log(StackTraceUtils.GetStacktrace(t)); } private static void log(String message) { StreamUtils.GetSystemOut().println("[" + new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z").format(new Date()) + "]: " + message); } private static interface VirtualPersistenceNetwork { Map<String[], String> getAllData() throws DataSourceException; URI getKeySource(String[] key); } /** * 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. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { jSplitPane1 = new javax.swing.JSplitPane(); jScrollPane1 = new javax.swing.JScrollPane(); keyTree = new javax.swing.JTree(); jPanel1 = new javax.swing.JPanel(); jLabel1 = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel(); jLabel3 = new javax.swing.JLabel(); jLabel4 = new javax.swing.JLabel(); namespaceLabel = new javax.swing.JLabel(); keyLabel = new javax.swing.JLabel(); valueTypeLabel = new javax.swing.JLabel(); jScrollPane2 = new javax.swing.JScrollPane(); valueTextArea = new javax.swing.JTextArea(); jLabel6 = new javax.swing.JLabel(); sourceLabel = new javax.swing.JLabel(); jLabel5 = new javax.swing.JLabel(); configurationFromLabel = new javax.swing.JLabel(); statusLabel = new javax.swing.JLabel(); statusProgressBar = new javax.swing.JProgressBar(); reloadButton = new javax.swing.JButton(); jMenuBar1 = new javax.swing.JMenuBar(); fileMenu = new javax.swing.JMenu(); loadFromConfigurationMenu = new javax.swing.JMenuItem(); closeRemoteConnectionMenu = new javax.swing.JMenuItem(); bookmarksMenu = new javax.swing.JMenu(); manageBookmarksMenu = new javax.swing.JMenuItem(); jSeparator1 = new javax.swing.JPopupMenu.Separator(); jMenu1 = new javax.swing.JMenu(); helpMenu = new javax.swing.JMenuItem(); aboutMenu = new javax.swing.JMenuItem(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); jSplitPane1.setDividerLocation(200); javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("root"); keyTree.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1)); keyTree.setToolTipText(""); keyTree.setRootVisible(false); jScrollPane1.setViewportView(keyTree); jSplitPane1.setLeftComponent(jScrollPane1); jLabel1.setText("Namespace:"); jLabel2.setText("Key:"); jLabel3.setText("Value type:"); jLabel4.setText("Value:"); namespaceLabel.setText("............."); keyLabel.setText("............."); valueTypeLabel.setText("............"); valueTextArea.setEditable(false); valueTextArea.setColumns(20); valueTextArea.setFont(new java.awt.Font("Monospaced", 0, 11)); // NOI18N valueTextArea.setLineWrap(true); valueTextArea.setRows(5); jScrollPane2.setViewportView(valueTextArea); jLabel6.setText("Source:"); sourceLabel.setText("..........."); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 722, Short.MAX_VALUE) .addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel4) .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(namespaceLabel)) .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(jLabel2) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(keyLabel)) .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(jLabel6) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(sourceLabel)) .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(jLabel3) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(valueTypeLabel))) .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap()) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel1) .addComponent(namespaceLabel)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel2) .addComponent(keyLabel)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel6) .addComponent(sourceLabel)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel3) .addComponent(valueTypeLabel)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel4) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 232, Short.MAX_VALUE)) ); jSplitPane1.setRightComponent(jPanel1); jLabel5.setText("Configuration from:"); configurationFromLabel.setText("..............."); statusLabel.setText("........."); reloadButton.setText("Reload"); reloadButton.setToolTipText("Reloads the data from the configuration"); fileMenu.setText("File"); loadFromConfigurationMenu.setText("Load from Configuration..."); fileMenu.add(loadFromConfigurationMenu); closeRemoteConnectionMenu.setText("Close Remote Connection"); fileMenu.add(closeRemoteConnectionMenu); jMenuBar1.add(fileMenu); bookmarksMenu.setText("Bookmarks"); manageBookmarksMenu.setText("Manage Bookmarks..."); bookmarksMenu.add(manageBookmarksMenu); bookmarksMenu.add(jSeparator1); jMenuBar1.add(bookmarksMenu); jMenu1.setText("Help"); helpMenu.setText("Help..."); jMenu1.add(helpMenu); aboutMenu.setText("About..."); jMenu1.add(aboutMenu); jMenuBar1.add(jMenu1); setJMenuBar(jMenuBar1); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 780, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addComponent(jLabel5) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(configurationFromLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(reloadButton)) .addGroup(layout.createSequentialGroup() .addComponent(statusLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(statusProgressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel5) .addComponent(configurationFromLabel) .addComponent(reloadButton)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jSplitPane1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(statusProgressBar, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(statusLabel, javax.swing.GroupLayout.Alignment.TRAILING)) .addContainerGap()) ); pack(); }// </editor-fold>//GEN-END:initComponents /** * @param args the command line arguments */ public static void main(String args[]) { /* Set the Nimbus look and feel */ //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) "> /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel. * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html */ try { for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(info.getName())) { javax.swing.UIManager.setLookAndFeel(info.getClassName()); break; } } } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) { java.util.logging.Logger.getLogger(PNViewer.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } //</editor-fold> /* Create and display the form */ java.awt.EventQueue.invokeLater(new Runnable() { @Override public void run() { PNViewer pnViewer = new PNViewer(); UIUtils.centerWindow(pnViewer); pnViewer.setVisible(true); } }); } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JMenuItem aboutMenu; private javax.swing.JMenu bookmarksMenu; private javax.swing.JMenuItem closeRemoteConnectionMenu; private javax.swing.JLabel configurationFromLabel; private javax.swing.JMenu fileMenu; private javax.swing.JMenuItem helpMenu; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; private javax.swing.JLabel jLabel4; private javax.swing.JLabel jLabel5; private javax.swing.JLabel jLabel6; private javax.swing.JMenu jMenu1; private javax.swing.JMenuBar jMenuBar1; private javax.swing.JPanel jPanel1; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JPopupMenu.Separator jSeparator1; private javax.swing.JSplitPane jSplitPane1; private javax.swing.JLabel keyLabel; private javax.swing.JTree keyTree; private javax.swing.JMenuItem loadFromConfigurationMenu; private javax.swing.JMenuItem manageBookmarksMenu; private javax.swing.JLabel namespaceLabel; private javax.swing.JButton reloadButton; private javax.swing.JLabel sourceLabel; private javax.swing.JLabel statusLabel; private javax.swing.JProgressBar statusProgressBar; private javax.swing.JTextArea valueTextArea; private javax.swing.JLabel valueTypeLabel; // End of variables declaration//GEN-END:variables }