/** * $Id: $ * $Date: $ * */ package org.xmlsh.marklogic.ui; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Desktop; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Image; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Semaphore; import javax.swing.DropMode; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; import javax.swing.tree.TreePath; import org.xmlsh.core.Options; import org.xmlsh.sh.shell.SerializeOpts; import org.xmlsh.sh.shell.Shell; import org.xmlsh.util.Util; import com.marklogic.xcc.Content; import com.marklogic.xcc.ContentCreateOptions; import com.marklogic.xcc.ContentFactory; import com.marklogic.xcc.ResultSequence; import com.marklogic.xcc.types.XdmVariable; import javax.swing.JList; import javax.swing.ListSelectionModel; import javax.swing.JComboBox; import java.awt.event.ItemListener; import java.awt.event.ItemEvent; import java.awt.image.BufferedImage; import javax.swing.JTextField; import javax.swing.event.MenuListener; import javax.swing.event.MenuEvent; import javax.swing.KeyStroke; import java.awt.event.KeyEvent; public class ExplorerShell { private ThreadGroup mThreadGroup ; private JFrame mframe; private ExplorerOptions mOptions ; private BlockingQueue<MLRequest> mCommandQueue = new ArrayBlockingQueue<MLRequest>(20, true); private File mCurdir; MLRequestThread mRequestThread; JTree mDirectoryTree; private MLTreeModel mDirectoryModel; SerializeOpts mSerializeOpts; private Shell mShell; private JLabel mStatus ; private File mTempDir; private JMenuItem mntmNext; private JMenuItem mntmPrev; private JButton mBtnConnect; private JComboBox mListDatabases; private boolean inConnect = false ; private JTextField mTextUriFilter; private JMenuItem mMntmProperties; public void run( ) { try { // Set System L&F UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { // handle exception } EventQueue.invokeLater(new Runnable() { public void run() { try { mframe.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } public ExplorerShell(Shell sh , Options opts) throws Exception { mThreadGroup = sh.newThreadGroup("mlui"); mShell = sh ; mCurdir = sh.getCurdir(); mSerializeOpts = sh.getSerializeOpts(opts); mOptions = new ExplorerOptions( opts.getOptString("connect", sh.getEnv().getVarString("MLCONNECT"))); QueryCache.init(this); initialize(); } /** * Initialize the contents of the frame. */ private void initialize() { mframe = new JFrame(); mframe.setTitle("MarkLogic Explorer"); mframe.setBounds(100, 100, 559, 445); mframe.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); JMenuBar menuBar = new JMenuBar(); menuBar.setAlignmentX(Component.LEFT_ALIGNMENT); mframe.setJMenuBar(menuBar); JMenu mnFile = new JMenu("File"); mnFile.setHorizontalAlignment(SwingConstants.LEFT); mnFile.setAlignmentX(Component.LEFT_ALIGNMENT); mnFile.setMnemonic('F'); menuBar.add(mnFile); JMenuItem mntmOptions = new JMenuItem("Options..."); mntmOptions.setHorizontalAlignment(SwingConstants.LEFT); mntmOptions.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { OptionsDialog dialog = new OptionsDialog(mOptions); dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); dialog.setVisible(true); } }); mnFile.add(mntmOptions); JMenuItem mntmCreateDirectory = new JMenuItem("Create Directory..."); mntmCreateDirectory.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { onCreateDirectory(); } catch (Exception e1) { printError("Exception opening file",e1); } } }); mnFile.add(mntmCreateDirectory); JMenuItem mntmExit = new JMenuItem("Exit"); mntmExit.setHorizontalAlignment(SwingConstants.LEFT); mnFile.add(mntmExit); JMenu mnView = new JMenu("View"); mnView.setHorizontalAlignment(SwingConstants.LEFT); mnView.addMenuListener(new MenuListener() { public void menuCanceled(MenuEvent e) { } public void menuDeselected(MenuEvent e) { } public void menuSelected(MenuEvent e) { int nsel = mDirectoryTree.getSelectionCount(); mMntmProperties.setEnabled( nsel == 1 ); } }); mnView.setMnemonic('V'); menuBar.add(mnView); mMntmProperties = new JMenuItem("Properties..."); mMntmProperties.setHorizontalAlignment(SwingConstants.LEFT); mMntmProperties.setIcon(null); mMntmProperties.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { onProperties(); } }); mnView.add(mMntmProperties); JPanel panel = new JPanel(); mframe.getContentPane().add(panel, BorderLayout.NORTH); GridBagLayout gbl_panel = new GridBagLayout(); gbl_panel.columnWidths = new int[]{87, 0, 0, 286, 0}; gbl_panel.rowHeights = new int[]{23, 0}; gbl_panel.columnWeights = new double[]{0.0, 0.0, 0.0, 1.0, Double.MIN_VALUE}; gbl_panel.rowWeights = new double[]{1.0, Double.MIN_VALUE}; panel.setLayout(gbl_panel); mBtnConnect = new JButton("Connect..."); mBtnConnect.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { if( isConnected() ) disconnect(); else connect(); } }); mBtnConnect.setMinimumSize(new Dimension(87, 20)); mBtnConnect.setMargin(new Insets(1, 12, 1, 12)); mBtnConnect.setMaximumSize(new Dimension(87, 20)); GridBagConstraints gbc_btnConnect = new GridBagConstraints(); gbc_btnConnect.anchor = GridBagConstraints.WEST; gbc_btnConnect.insets = new Insets(0, 0, 0, 5); gbc_btnConnect.gridx = 0; gbc_btnConnect.gridy = 0; panel.add(mBtnConnect, gbc_btnConnect); mBtnConnect.setHorizontalAlignment(SwingConstants.LEFT); mListDatabases = new JComboBox(); mListDatabases.setMinimumSize(new Dimension(120, 20)); mListDatabases.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent event) { if( inConnect ) return ; if (event.getStateChange() == ItemEvent.SELECTED) { Object item = event.getItem(); if( item instanceof String && ! Util.isBlank((String)item) ){ mOptions.mDatabase = (String) item ; if( isConnected() ){ disconnect(); connect(); } } } } }); GridBagConstraints gbc_listDatabases = new GridBagConstraints(); gbc_listDatabases.gridwidth = 2; gbc_listDatabases.insets = new Insets(0, 0, 0, 5); gbc_listDatabases.fill = GridBagConstraints.BOTH; gbc_listDatabases.gridx = 1; gbc_listDatabases.gridy = 0; panel.add(mListDatabases, gbc_listDatabases); GridBagConstraints gbc_TextUriFilter = new GridBagConstraints(); gbc_TextUriFilter.fill = GridBagConstraints.HORIZONTAL; gbc_TextUriFilter.insets = new Insets(0, 0, 0, 5); gbc_TextUriFilter.gridx = 3; gbc_TextUriFilter.gridy = 0; mTextUriFilter = new JTextField(); mTextUriFilter.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { mOptions.mQuery = mTextUriFilter.getText(); refresh(); } }); panel.add(mTextUriFilter, gbc_TextUriFilter); mTextUriFilter.setColumns(10); /* * Icon on text field to clear it */ mTextUriFilter.setLayout(new BorderLayout()); //creating dummy image... Image image = new BufferedImage(18, 18, BufferedImage.TYPE_INT_RGB); Graphics graphics = image.getGraphics(); graphics.setColor(Color.WHITE); graphics.fillRect(0, 0, 18,18); graphics.setColor(Color.RED); graphics.drawLine(6,6, 11, 11); graphics.drawLine(6,11,11,6); JLabel iimage = new JLabel(new ImageIcon(image)); iimage.setCursor( Cursor.getDefaultCursor()); mTextUriFilter.add(iimage, BorderLayout.EAST); iimage.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { mTextUriFilter.setText(""); mOptions.mQuery = ""; refresh(); } }); JLabel lblStatus = mStatus= new JLabel("Status"); mframe.getContentPane().add(lblStatus, BorderLayout.SOUTH); JScrollPane scrollPane = new JScrollPane(); mframe.getContentPane().add(scrollPane, BorderLayout.CENTER); JTree tree = new JTree( ); tree.setDropMode(DropMode.ON); tree.setDragEnabled(true); tree.setRootVisible(false); tree.setTransferHandler( new TreeTransferHandler(this) ); scrollPane.setViewportView(tree); mDirectoryTree = tree ; mDirectoryTree.setModel( mDirectoryModel = new MLTreeModel(new LazyTreeNode(), tree, this) ); JPopupMenu popupMenu = new JPopupMenu(); addPopup(tree, popupMenu); final JMenuItem mntmOpen = new JMenuItem("Open..."); addOpenAction(mntmOpen); final JMenuItem mntmRefresh = new JMenuItem("Refresh..."); addRefreshAction(mntmRefresh); mntmNext = new JMenuItem("Next 1000..."); mntmNext.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, 0)); addNextAction(); popupMenu.add(mntmNext); mntmPrev = new JMenuItem("Prev 1000..."); mntmPrev.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { onPrev(); } }); popupMenu.add(mntmPrev); popupMenu.add(mntmRefresh); final JMenuItem mntmRename = new JMenuItem("Rename..."); addRenameAction(mntmRename); popupMenu.add(mntmRename); popupMenu.add(mntmOpen); final JMenuItem mntmLoad = new JMenuItem("Load..."); addLoadAction(mntmLoad); popupMenu.add(mntmLoad); final JMenuItem mntmSaveAs = new JMenuItem("Save As..."); addSaveAsAction(mntmSaveAs); final JMenuItem mntmDelete = new JMenuItem("Delete..."); addDeleteAction(mntmDelete); popupMenu.add(mntmDelete); popupMenu.add(mntmSaveAs); popupMenu.addPopupMenuListener(new PopupMenuListener() { public void popupMenuCanceled(PopupMenuEvent e) { } public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { } public void popupMenuWillBecomeVisible(PopupMenuEvent e) { int nsel = mDirectoryTree.getSelectionCount(); boolean isDir = false ; for( String u : getSelectedUrls() ) if( u.endsWith("/")) isDir=true; mntmDelete.setEnabled(nsel > 0); mntmOpen.setEnabled(nsel == 1 && ! isDir ); mntmRename.setEnabled(nsel == 1 && ! isDir ); mntmLoad.setEnabled( nsel == 0 || ( nsel == 1 && isDir ) ); mntmSaveAs.setEnabled( nsel > 0 ); mntmRefresh.setEnabled( nsel == 0 || isDir ); mntmNext.setText("Next " + mOptions.mMaxRows + "..."); mntmPrev.setText("Prev " + mOptions.mMaxRows + "..."); if( nsel == 1 ){ TreePath path = mDirectoryTree.getSelectionPath(); LazyTreeNode node = (LazyTreeNode) path.getLastPathComponent(); mntmNext.setEnabled( node.isDirectory() && ( node.getStart() != node.getEnd() )); mntmPrev.setEnabled( node.isDirectory() && node.getStart() > 1 ); } else { mntmNext.setEnabled(false); mntmPrev.setEnabled(false); } } }); } private void addRenameAction(final JMenuItem mntmRename) { mntmRename.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { } }); } private void addLoadAction(final JMenuItem mntmLoad) { mntmLoad.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { onLoad(); } catch (InterruptedException e1) { printError( "Exception loading documents",e1); } } }); } private void addSaveAsAction(final JMenuItem mitem) { mitem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { onSaveAs(); } }); } private void addDeleteAction(final JMenuItem mitem) { mitem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { onDelete(); } catch (InterruptedException e1) { printError( "Exception deleting documents",e1); } } }); } private void addNextAction() { mntmNext.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { onNext(); } }); } private void addRefreshAction(final JMenuItem mitem) { mitem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { onRefresh(); } }); } private void addOpenAction(final JMenuItem mitem) { mitem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { onOpen(); } catch (Exception e1) { printError("Exception opening file",e1); } } }); } protected void onRefresh() { if( mDirectoryTree.getSelectionCount() > 0 ){ for( TreePath p : mDirectoryTree.getSelectionPaths() ){ LazyTreeNode parentNode = (LazyTreeNode) p.getLastPathComponent(); if( parentNode.isDirectory()){ mDirectoryModel.postReload(parentNode); } } } else mDirectoryModel.loadFirstLevel(); } protected void onNext() { TreePath p = mDirectoryTree.getSelectionPath(); if( p != null ){ LazyTreeNode parentNode = (LazyTreeNode) p.getLastPathComponent(); if( parentNode.isDirectory()) mDirectoryModel.postNext( parentNode , mOptions.mMaxRows ); } } protected void onPrev() { TreePath p = mDirectoryTree.getSelectionPath(); if( p != null ){ LazyTreeNode parentNode = (LazyTreeNode) p.getLastPathComponent(); if( parentNode.isDirectory()){ if( parentNode.getStart() > 1 ) mDirectoryModel.postPrev( parentNode , mOptions.mMaxRows ); } } } protected void onCreateDirectory() throws InterruptedException { String parentUrl = getSelectedUrl(); if( ! Util.isBlank(parentUrl) && !parentUrl.endsWith("/")){ JOptionPane.showMessageDialog(null, "Cannot create a sub directory under a regular document."); return ; } String dir = JOptionPane.showInputDialog(null, "Create Directory:", "Parent: " + parentUrl , JOptionPane.INFORMATION_MESSAGE); if( Util.isBlank(dir ) || ! dir.endsWith("/")){ JOptionPane.showMessageDialog(null, "Directory must end with a /"); return; } putCommand( new MLCreateDirectoryRequest( parentUrl + dir ){ @Override void onComplete(ResultSequence rs) throws Exception { onRefresh(); }} ); } private void onDelete() throws InterruptedException { if( mDirectoryTree.getSelectionCount() > 0 ){ if( confirmYesNo("Delete Selected Files?")){ doDelete( getSelectedUrls() ); Set<LazyTreeNode> parents = new HashSet<LazyTreeNode>(); for( TreePath p : mDirectoryTree.getSelectionPaths() ){ parents.add((LazyTreeNode) ((LazyTreeNode)p.getLastPathComponent()).getParent() ); } for( LazyTreeNode p : parents ) mDirectoryModel.postReload( p ); } } } private List<String> getSelectedUrls() { List<String> list = new ArrayList<String>(); if( mDirectoryTree.getSelectionCount() > 0 ){ for( TreePath p : mDirectoryTree.getSelectionPaths() ){ list.add( ((LazyTreeNode) p.getLastPathComponent()).getUrl() ); } } return list; } private boolean confirmYesNo(String string) { return JOptionPane.showConfirmDialog(mframe, string, "Confirm", JOptionPane.YES_NO_OPTION ) == JOptionPane.YES_OPTION; } List<File> doStore(final String url) throws Exception { try { mframe.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); final Semaphore sem = new Semaphore(1); sem.acquire(); if( url.endsWith("/")) { // Directory String name = url.substring( 0 , url.lastIndexOf('/')); // strip trailing slash name = name.substring(name.lastIndexOf('/') + 1 ); final File tmpDir = getTempFile(name); tmpDir.mkdirs(); MLListDirectoryRequest dirRequest = new MLListDirectoryRequest( url , mOptions.mQuery ) { @Override void onComplete(ResultSequence rs) throws Exception { final String children[] = rs.asStrings(); for( String child_url : children ){ MLGetRequest getRequest; File outFile = new File( tmpDir , child_url.substring(url.length())); File outDir = outFile.getParentFile(); try { if( ! outDir.exists()) outDir.mkdirs(); getRequest = new MLGetRequest( child_url , outFile,mSerializeOpts); getRequest.run( mRequestThread ); } catch (Exception e) { printError("Exception getting: " + child_url + " to local file: " + outFile.getAbsolutePath() , e ); } } sem.release(); } } ; putCommand( dirRequest ); sem.acquire(); return Arrays.asList(tmpDir); } else { String name = url.substring(url.lastIndexOf('/') + 1 ); File tmpFile = getTempFile(name); MLGetRequest r = new MLGetRequest(url, tmpFile, mSerializeOpts) { void onComplete( ResultSequence rs) throws Exception { super.onComplete(rs); sem.release(); } }; putCommand( r ); sem.acquire(); return Arrays.asList(tmpFile); } } finally { mframe.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } } void doLoad(final LazyTreeNode parentNode, List<File> files) throws InterruptedException { try { mframe.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); for( File f : files ){ List<Content> c = getContents( parentNode == null ? "" : parentNode.getUrl(), f ); if( c == null || c.size() == 0 ) continue ; int start = 0; int end = c.size(); int n = mOptions.mBatchSize ; while( start < end ){ if( start + n >= end ) n = end - start ; List<Content> batch = c.subList(start, start + n); final boolean last = (start + n ) >= end; putCommand( new MLPutRequest( batch.toArray( new Content[batch.size()])){ public void onComplete(boolean bSuccess) { if( last ) mDirectoryModel.postReload(parentNode); } }); start += n ; n = mOptions.mBatchSize ; } } }finally { mframe.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } } private List<Content> getContents(String parentUri , File f) { List<Content> list = new ArrayList<Content>(); String fileUri = parentUri + f.getName(); if( f.isDirectory() ){ for( File child : f.listFiles() ){ String name = child.getName() ; if( name.equals(".") || name.equals("..")) continue ; list.addAll( getContents( fileUri + "/" , child ) ); } } else if( f.isFile() && f.canRead() ){ list.add( ContentFactory.newContent(fileUri , f, getCreateOptions() ) ) ; } return list; } private ContentCreateOptions getCreateOptions() { return new ContentCreateOptions(); } protected void onSaveAs() { // TODO Auto-generated method stub } protected void onLoad() throws InterruptedException { JFileChooser fc = new JFileChooser(); fc.setMultiSelectionEnabled(true); fc.setCurrentDirectory( mCurdir ); if( fc.showDialog(mframe, "Load") == JFileChooser.APPROVE_OPTION ){ File[] files = fc.getSelectedFiles(); LazyTreeNode node = (LazyTreeNode) mDirectoryTree.getSelectionPath().getLastPathComponent() ; doLoad( node , Arrays.asList( files ) ); } } protected String getSelectedUrl() { List<String> urls = getSelectedUrls(); if( urls != null && urls.size() > 0 ) return urls.get(0); return "" ; } protected void onOpen() throws Exception { String url = getSelectedUrl(); List<File> files = doStore( url ); Desktop.getDesktop().edit(files.get(0)); } void printError(String s, Exception e) { mShell.printErr(s,e); } public Shell getShell() { return mShell; } private void connect() { if( ! isConnected() ){ mRequestThread = new MLRequestThread( this , mOptions , mCommandQueue ); mRequestThread.start(); mDirectoryModel.loadFirstLevel(); this.mBtnConnect.setText("Disconnect..."); try { refreshDatabases(); } catch( Exception e ) { printError("Exception refreshing databases",e); } } } private void disconnect() { if( isConnected() ){ mRequestThread.close(); mRequestThread = null ; this.mBtnConnect.setText("Connect..."); mListDatabases.removeAllItems(); mDirectoryModel.reset(); } } private boolean isConnected() { return mRequestThread != null ; } private void refreshDatabases() throws InterruptedException { putCommand( new MLQueryRequest( "Getting Databases ..." , QueryCache.getInstance().getQuery("listDatabases.xquery"), null ){ @Override void onComplete(ResultSequence rs) throws Exception { final String[] dbs = rs.asStrings(); SwingUtilities.invokeLater(new Runnable() { public void run() { inConnect = true ; mListDatabases.removeAllItems(); boolean first = true ; String selected = null ; for( String db : dbs ) { if( ! first ){ mListDatabases.addItem( db ); if( db.equals( dbs[0])) selected =db ; } first = false ; } mListDatabases.setSelectedItem(selected); inConnect = false ; } }); } }); } private static void addPopup(Component component, final JPopupMenu popup) { component.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { if (e.isPopupTrigger()) { showMenu(e); } } public void mouseReleased(MouseEvent e) { if (e.isPopupTrigger()) { showMenu(e); } } private void showMenu(MouseEvent e) { popup.show(e.getComponent(), e.getX(), e.getY()); } }); } public void setStatus(final String operation) { SwingUtilities.invokeLater(new Runnable() { public void run() { mStatus.setText(operation); } }); } File getTempFile(String name) throws IOException { if( mTempDir == null ){ mTempDir = File.createTempFile("mlui", null ); mTempDir.delete(); mTempDir.mkdir(); mTempDir.deleteOnExit(); } File f = new File( mTempDir , name ); if( f.exists() ) f.delete(); f.deleteOnExit(); return f; } private void doDelete( List<String> urls ) throws InterruptedException { List<MLRequest> deletes = new ArrayList<MLRequest>( urls.size()); for( String url : urls ) deletes.add( new MLDeleteRequest(url){ @Override void onComplete(ResultSequence rs) throws Exception { }} ); final Semaphore sem = new Semaphore(1); sem.acquire(); mframe.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); putCommand( new MLMultiRequest( "Deleting documents ..." , deletes ){ @Override void onComplete() { sem.release(); } }); sem.acquire(); mframe.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } boolean putCommand(MLRequest command) { try { mCommandQueue.put(command); } catch (InterruptedException e) { printError("Interrupted putting command to command queue" , e); return false; } return true; } /** * @return the options */ protected ExplorerOptions getOptions() { return mOptions; } private void refresh() { if( isConnected() ) { disconnect(); connect(); } } private void onProperties() { String url = getSelectedUrl(); PropertiesDialog dialog; try { dialog = new PropertiesDialog(this, url); dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); dialog.setVisible(true); } catch (InterruptedException e) { mShell.printErr("Exception loading Properties Dialog" , e ); } } ThreadGroup getThreadGroup() { // TODO Auto-generated method stub return mThreadGroup; } } /* * Copyright (C) 2008-2014 David A. Lee. * * The contents of this file are subject to the "Simplified BSD License" (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.opensource.org/licenses/bsd-license.php * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. * See the License for the specific language governing rights and limitations under the License. * * The Original Code is: all this file. * * The Initial Developer of the Original Code is David A. Lee * * Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved. * * Contributor(s): David A. Lee * */