From 3f658c8f51e2423a216b22df8a4a6ed771fa2723 Mon Sep 17 00:00:00 2001 From: HongKee Moon Date: Tue, 24 Mar 2015 10:19:32 +0100 Subject: [PATCH 01/11] Add ".bdv" file handler --- .../java/bdv/ij/BigDataBrowserPlugIn.java | 50 +++++++++++++++---- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java index 94a1139..d727cab 100644 --- a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java +++ b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java @@ -19,9 +19,7 @@ import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; +import java.io.*; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; @@ -51,13 +49,47 @@ public void run( final String arg ) e.printStackTrace(); } - final Object remoteUrl = JOptionPane.showInputDialog( null, "Enter BigDataServer Remote URL:", "BigDataServer", - JOptionPane.QUESTION_MESSAGE, new ImageIcon( image ), null, serverUrl ); + if ( null == arg ) + { + final Object remoteUrl = JOptionPane.showInputDialog( null, "Enter BigDataServer Remote URL:", "BigDataServer", + JOptionPane.QUESTION_MESSAGE, new ImageIcon( image ), null, serverUrl ); + + if ( remoteUrl == null ) + return; + + serverUrl = remoteUrl.toString(); + } + else + { + String line = null; + FileReader fileReader = null; + + try + { + fileReader = new FileReader( new File( arg ) ); + } + catch ( FileNotFoundException e ) + { + e.printStackTrace(); + } - if ( remoteUrl == null ) - return; + BufferedReader br = new BufferedReader( fileReader ); - serverUrl = remoteUrl.toString(); + try + { + if ( ( line = br.readLine() ) != null ) + { + serverUrl = line; + } + } + catch ( IOException e ) + { + e.printStackTrace(); + } + + if ( line == null ) + return; + } final ArrayList< String > nameList = new ArrayList< String >(); try @@ -185,6 +217,6 @@ public Component getListCellRendererComponent( public static void main( final String[] args ) { ImageJ.main( args ); - new BigDataBrowserPlugIn().run( null ); + new BigDataBrowserPlugIn().run( "/Users/moon/Desktop/local.bdv" ); } } From c5de915e9ce2bfbe42e5da1f9f65c82cd26ca6b4 Mon Sep 17 00:00:00 2001 From: HongKee Moon Date: Thu, 7 May 2015 15:55:04 +0200 Subject: [PATCH 02/11] Include the empty string check along with null check --- src/main/java/bdv/ij/BigDataBrowserPlugIn.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java index d727cab..856c49e 100644 --- a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java +++ b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java @@ -49,7 +49,7 @@ public void run( final String arg ) e.printStackTrace(); } - if ( null == arg ) + if ( null == arg || arg == "" ) { final Object remoteUrl = JOptionPane.showInputDialog( null, "Enter BigDataServer Remote URL:", "BigDataServer", JOptionPane.QUESTION_MESSAGE, new ImageIcon( image ), null, serverUrl ); @@ -217,6 +217,7 @@ public Component getListCellRendererComponent( public static void main( final String[] args ) { ImageJ.main( args ); - new BigDataBrowserPlugIn().run( "/Users/moon/Desktop/local.bdv" ); + //new BigDataBrowserPlugIn().run( "/Users/moon/Desktop/local.bdv" ); + new BigDataBrowserPlugIn().run( null ); } } From d4e91dcbdb7ca11039b23e842ffbdb2e997aeb40 Mon Sep 17 00:00:00 2001 From: HongKee Moon Date: Fri, 29 May 2015 18:42:46 +0200 Subject: [PATCH 03/11] Support DataSet category and description BigDataServer provides category and description information, so that BigDataBrowserPlugin renders those information. --- .../java/bdv/ij/BigDataBrowserPlugIn.java | 108 +++++++++++++++--- 1 file changed, 92 insertions(+), 16 deletions(-) diff --git a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java index 856c49e..3fdfdb0 100644 --- a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java +++ b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java @@ -91,7 +91,7 @@ public void run( final String arg ) return; } - final ArrayList< String > nameList = new ArrayList< String >(); + final ArrayList< Object > nameList = new ArrayList< Object >(); try { getDatasetList( serverUrl, nameList ); @@ -104,7 +104,52 @@ public void run( final String arg ) createDatasetListUI( serverUrl, nameList.toArray() ); } - private boolean getDatasetList( final String remoteUrl, final ArrayList< String > nameList ) throws IOException + class DataSet + { + private final String name; + private final String description; + private final String category; + + DataSet( String name, String description, String category ) + { + + this.name = name; + this.description = description; + this.category = category; + } + + public String getName() + { + return name; + } + + public String getDescription() + { + return description; + } + + public String getCategory() + { + return category; + } + } + + class Category + { + private final String name; + + Category( String name ) + { + this.name = name; + } + + public String getName() + { + return name; + } + } + + private boolean getDatasetList( final String remoteUrl, final ArrayList< Object > nameList ) throws IOException { // Get JSON string from the server final URL url = new URL( remoteUrl + "/json/" ); @@ -112,6 +157,8 @@ private boolean getDatasetList( final String remoteUrl, final ArrayList< String final InputStream is = url.openStream(); final JsonReader reader = new JsonReader( new InputStreamReader( is, "UTF-8" ) ); + String prevCategory = null; + reader.beginObject(); while ( reader.hasNext() ) @@ -121,7 +168,7 @@ private boolean getDatasetList( final String remoteUrl, final ArrayList< String reader.beginObject(); - String id = null, description = null, thumbnailUrl = null, datasetUrl = null; + String id = null, category = null, description = null, thumbnailUrl = null, datasetUrl = null; while ( reader.hasNext() ) { final String name = reader.nextName(); @@ -133,11 +180,21 @@ else if ( name.equals( "thumbnailUrl" ) ) thumbnailUrl = reader.nextString(); else if ( name.equals( "datasetUrl" ) ) datasetUrl = reader.nextString(); + else if ( name.equals( "category" ) ) + category = reader.nextString(); + else if ( name.equals( "index" ) ) + reader.nextString(); + } + + if ( prevCategory == null || prevCategory != category ) + { + prevCategory = category; + nameList.add( new Category( prevCategory ) ); } if ( id != null ) { - nameList.add( id ); + nameList.add( new DataSet( id, description, category ) ); if ( thumbnailUrl != null && StringUtils.isNotEmpty( thumbnailUrl ) ) imageMap.put( id, new ImageIcon( new URL( thumbnailUrl ) ) ); if ( datasetUrl != null ) @@ -167,15 +224,20 @@ public void mouseClicked( final MouseEvent evt ) if ( evt.getClickCount() == 2 ) { final int index = list.locationToIndex( evt.getPoint() ); - final String key = String.valueOf( list.getModel().getElementAt( index ) ); - System.out.println( key ); - try - { - BigDataViewer.view( datasetUrlMap.get( key ), new ProgressWriterIJ() ); - } - catch ( final SpimDataException e ) + final Object cell = list.getModel().getElementAt( index ); + + if ( cell instanceof DataSet ) { - e.printStackTrace(); + DataSet ds = ( DataSet ) cell; + System.out.println( ds.getName() ); + try + { + BigDataViewer.view( datasetUrlMap.get( ds.getName() ), new ProgressWriterIJ() ); + } + catch ( final SpimDataException e ) + { + e.printStackTrace(); + } } } } @@ -197,7 +259,7 @@ public class ThumbnailListRenderer extends DefaultListCellRenderer { private static final long serialVersionUID = 1L; - Font font = new Font( "helvetica", Font.BOLD, 12 ); + Font font = new Font( "helvetica", Font.PLAIN, 12 ); @Override public Component getListCellRendererComponent( @@ -207,9 +269,23 @@ public Component getListCellRendererComponent( final JLabel label = ( JLabel ) super.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus ); - label.setIcon( imageMap.get( ( String ) value ) ); - label.setHorizontalTextPosition( JLabel.RIGHT ); - label.setFont( font ); + + if ( value instanceof Category ) + { + Category category = ( Category ) value; + label.setText( category.getName() ); + label.setFont( label.getFont().deriveFont( Font.BOLD, 26 ) ); + label.setBorder( BorderFactory.createEmptyBorder( 0, 5, 0, 0 ) ); + } + else + { + DataSet ds = ( DataSet ) value; + label.setIcon( imageMap.get( ds.getName() ) ); + label.setText( "" + ds.getName() + "
" + ds.getDescription() + "" ); + label.setHorizontalTextPosition( JLabel.RIGHT ); + label.setFont( font ); + } + return label; } } From 7bbb22134613f6d2d6b4bcbd3f34ec1adcfbee34 Mon Sep 17 00:00:00 2001 From: HongKee Moon Date: Mon, 1 Jun 2015 14:22:46 +0200 Subject: [PATCH 04/11] Support Category based browsing BigDataServer If the URL is http://{server}:{port}/category/{categoryName} then, only the category relevant datasets are shown. --- src/main/java/bdv/ij/BigDataBrowserPlugIn.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java index 3fdfdb0..355d053 100644 --- a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java +++ b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java @@ -21,6 +21,7 @@ import java.awt.image.BufferedImage; import java.io.*; import java.net.URL; +import java.net.URLEncoder; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -94,7 +95,14 @@ public void run( final String arg ) final ArrayList< Object > nameList = new ArrayList< Object >(); try { - getDatasetList( serverUrl, nameList ); + String category = ""; + if ( serverUrl.indexOf( "/category/" ) > -1 ) + { + String[] tokens = serverUrl.split( "/category/" ); + serverUrl = tokens[ 0 ]; + category = tokens[ 1 ]; + } + getDatasetList( serverUrl, nameList, category ); } catch ( final IOException e ) { @@ -149,10 +157,10 @@ public String getName() } } - private boolean getDatasetList( final String remoteUrl, final ArrayList< Object > nameList ) throws IOException + private boolean getDatasetList( final String remoteUrl, final ArrayList< Object > nameList, final String searchCategory ) throws IOException { // Get JSON string from the server - final URL url = new URL( remoteUrl + "/json/" ); + final URL url = new URL( remoteUrl + "/json/?category=" + URLEncoder.encode( searchCategory, "UTF-8" ) ); final InputStream is = url.openStream(); final JsonReader reader = new JsonReader( new InputStreamReader( is, "UTF-8" ) ); From 64e0c3f23be709610a5749018ad4cb942d2f3964 Mon Sep 17 00:00:00 2001 From: HongKee Moon Date: Tue, 9 Jun 2015 18:09:12 +0200 Subject: [PATCH 05/11] Fix the bug showing multiple same categories --- src/main/java/bdv/ij/BigDataBrowserPlugIn.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java index 355d053..5da471a 100644 --- a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java +++ b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java @@ -194,7 +194,7 @@ else if ( name.equals( "index" ) ) reader.nextString(); } - if ( prevCategory == null || prevCategory != category ) + if ( prevCategory == null || !prevCategory.equals( category ) ) { prevCategory = category; nameList.add( new Category( prevCategory ) ); From 8e344a59f04c6082a748b4820709e556bd1f304d Mon Sep 17 00:00:00 2001 From: HongKee Moon Date: Wed, 10 Jun 2015 08:56:24 +0200 Subject: [PATCH 06/11] Add category URL in the title bar --- src/main/java/bdv/ij/BigDataBrowserPlugIn.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java index 5da471a..92b2b3d 100644 --- a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java +++ b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java @@ -93,9 +93,10 @@ public void run( final String arg ) } final ArrayList< Object > nameList = new ArrayList< Object >(); + String category = ""; try { - String category = ""; + if ( serverUrl.indexOf( "/category/" ) > -1 ) { String[] tokens = serverUrl.split( "/category/" ); @@ -109,7 +110,7 @@ public void run( final String arg ) IJ.showMessage( "Error connecting to server at " + serverUrl ); e.printStackTrace(); } - createDatasetListUI( serverUrl, nameList.toArray() ); + createDatasetListUI( category, serverUrl, nameList.toArray() ); } class DataSet @@ -219,7 +220,7 @@ else if ( name.equals( "index" ) ) return true; } - private void createDatasetListUI( final String remoteUrl, final Object[] values ) + private void createDatasetListUI( final String category, final String remoteUrl, final Object[] values ) { final JList list = new JList( values ); list.setCellRenderer( new ThumbnailListRenderer() ); @@ -237,7 +238,7 @@ public void mouseClicked( final MouseEvent evt ) if ( cell instanceof DataSet ) { DataSet ds = ( DataSet ) cell; - System.out.println( ds.getName() ); + try { BigDataViewer.view( datasetUrlMap.get( ds.getName() ), new ProgressWriterIJ() ); @@ -255,7 +256,10 @@ public void mouseClicked( final MouseEvent evt ) scroll.setPreferredSize( new Dimension( 600, 800 ) ); final JFrame frame = new JFrame(); - frame.setTitle( "BigDataServer Browser - " + remoteUrl ); + if ( category.equals( "" ) ) + frame.setTitle( "BigDataServer Browser - " + remoteUrl ); + else + frame.setTitle( "BigDataServer Browser - " + remoteUrl + "/category/" + category ); frame.add( scroll ); frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE ); frame.pack(); From 6cb27c971f6605558070a60ab3923fcc0ab01de3 Mon Sep 17 00:00:00 2001 From: HongKee Moon Date: Wed, 22 Jul 2015 16:03:39 +0200 Subject: [PATCH 07/11] Make safer way to handle json reader In order to handle the higher version of BigDataServer, it should skip the String value with reader.nextString() call for default. --- src/main/java/bdv/ij/BigDataBrowserPlugIn.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java index 92b2b3d..3275a42 100644 --- a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java +++ b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java @@ -193,6 +193,8 @@ else if ( name.equals( "category" ) ) category = reader.nextString(); else if ( name.equals( "index" ) ) reader.nextString(); + else + reader.nextString(); } if ( prevCategory == null || !prevCategory.equals( category ) ) From 586789e009f63fc928a487ed6043cbcdb5ff4aa7 Mon Sep 17 00:00:00 2001 From: HongKee Moon Date: Thu, 23 Jul 2015 14:51:03 +0200 Subject: [PATCH 08/11] Add fiji icon in the resources Fixed it for handling the situation that fiji.sc site does not provide Fiji-icon.png properly. --- src/main/java/bdv/ij/BigDataBrowserPlugIn.java | 2 +- src/main/resources/fiji.png | Bin 0 -> 5304 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 src/main/resources/fiji.png diff --git a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java index 3275a42..d1f6080 100644 --- a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java +++ b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java @@ -43,7 +43,7 @@ public void run( final String arg ) BufferedImage image = null; try { - image = ImageIO.read( new URL( "http://fiji.sc/_images/a/ae/Fiji-icon.png" ) ); + image = ImageIO.read( getClass().getResourceAsStream( "/fiji.png" ) ); } catch ( final IOException e ) { diff --git a/src/main/resources/fiji.png b/src/main/resources/fiji.png new file mode 100644 index 0000000000000000000000000000000000000000..2d61641500d57ee0e0a4bdcf4a9ae40320ea1ea9 GIT binary patch literal 5304 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 KMNUMnLSTY&b|bm~ literal 0 HcmV?d00001 From fcaae4474f57e834eab8fdf31c802551d11e329b Mon Sep 17 00:00:00 2001 From: HongKee Moon Date: Mon, 31 Aug 2015 17:00:05 +0200 Subject: [PATCH 09/11] Support Category and Description data of dataset --- src/main/java/bdv/ij/BigDataBrowserPlugIn.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java index ee62e43..04a4fe7 100644 --- a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java +++ b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java @@ -10,6 +10,10 @@ import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -20,6 +24,7 @@ import java.util.Map; import javax.imageio.ImageIO; +import javax.swing.BorderFactory; import javax.swing.DefaultListCellRenderer; import javax.swing.ImageIcon; import javax.swing.JFrame; From f9190c69fba61e837b83942ba79e4383dd6d407d Mon Sep 17 00:00:00 2001 From: HongKee Moon Date: Wed, 13 Apr 2016 11:55:57 +0200 Subject: [PATCH 10/11] Support drag/drop BigDataViewer xml file --- src/main/java/bdv/ij/BigDataViewerPlugIn.java | 131 ++++++++++-------- 1 file changed, 71 insertions(+), 60 deletions(-) diff --git a/src/main/java/bdv/ij/BigDataViewerPlugIn.java b/src/main/java/bdv/ij/BigDataViewerPlugIn.java index 0e26d3b..6fdfd0b 100644 --- a/src/main/java/bdv/ij/BigDataViewerPlugIn.java +++ b/src/main/java/bdv/ij/BigDataViewerPlugIn.java @@ -23,80 +23,83 @@ public class BigDataViewerPlugIn implements PlugIn @Override public void run( final String arg ) { - File file = null; + File file = getFile( arg ); - if ( Prefs.useJFileChooser ) + if( file == null ) { - final JFileChooser fileChooser = new JFileChooser(); - fileChooser.setSelectedFile( new File( lastDatasetPath ) ); - fileChooser.setFileFilter( new FileFilter() + if ( Prefs.useJFileChooser ) { - @Override - public String getDescription() + final JFileChooser fileChooser = new JFileChooser(); + fileChooser.setSelectedFile( new File( lastDatasetPath ) ); + fileChooser.setFileFilter( new FileFilter() { - return "xml files"; - } + @Override + public String getDescription() + { + return "xml files"; + } - @Override - public boolean accept( final File f ) - { - if ( f.isDirectory() ) - return true; - if ( f.isFile() ) + @Override + public boolean accept( final File f ) { - final String s = f.getName(); - final int i = s.lastIndexOf('.'); - if (i > 0 && i < s.length() - 1) { - final String ext = s.substring(i+1).toLowerCase(); - return ext.equals( "xml" ); - } + if ( f.isDirectory() ) + return true; + if ( f.isFile() ) + { + final String s = f.getName(); + final int i = s.lastIndexOf('.'); + if (i > 0 && i < s.length() - 1) { + final String ext = s.substring(i+1).toLowerCase(); + return ext.equals( "xml" ); + } + } + return false; } - return false; - } - } ); + } ); - final int returnVal = fileChooser.showOpenDialog( null ); - if ( returnVal == JFileChooser.APPROVE_OPTION ) - file = fileChooser.getSelectedFile(); - } - else // use FileDialog - { - final FileDialog fd = new FileDialog( ( Frame ) null, "Open", FileDialog.LOAD ); - fd.setDirectory( new File( lastDatasetPath ).getParent() ); - fd.setFile( new File( lastDatasetPath ).getName() ); - final AtomicBoolean workedWithFilenameFilter = new AtomicBoolean( false ); - fd.setFilenameFilter( new FilenameFilter() + final int returnVal = fileChooser.showOpenDialog( null ); + if ( returnVal == JFileChooser.APPROVE_OPTION ) + file = fileChooser.getSelectedFile(); + } + else // use FileDialog { - private boolean firstTime = true; - - @Override - public boolean accept( final File dir, final String name ) + final FileDialog fd = new FileDialog( ( Frame ) null, "Open", FileDialog.LOAD ); + fd.setDirectory( new File( lastDatasetPath ).getParent() ); + fd.setFile( new File( lastDatasetPath ).getName() ); + final AtomicBoolean workedWithFilenameFilter = new AtomicBoolean( false ); + fd.setFilenameFilter( new FilenameFilter() { - if ( firstTime ) - { - workedWithFilenameFilter.set( true ); - firstTime = false; - } + private boolean firstTime = true; - final int i = name.lastIndexOf( '.' ); - if ( i > 0 && i < name.length() - 1 ) + @Override + public boolean accept( final File dir, final String name ) { - final String ext = name.substring( i + 1 ).toLowerCase(); - return ext.equals( "xml" ); + if ( firstTime ) + { + workedWithFilenameFilter.set( true ); + firstTime = false; + } + + final int i = name.lastIndexOf( '.' ); + if ( i > 0 && i < name.length() - 1 ) + { + final String ext = name.substring( i + 1 ).toLowerCase(); + return ext.equals( "xml" ); + } + return false; } - return false; - } - } ); - fd.setVisible( true ); - if ( isMac() && !workedWithFilenameFilter.get() ) - { - fd.setFilenameFilter( null ); + } ); fd.setVisible( true ); - } - final String filename = fd.getFile(); - if ( filename != null ) - { - file = new File( fd.getDirectory() + filename ); + if ( isMac() && !workedWithFilenameFilter.get() ) + { + fd.setFilenameFilter( null ); + fd.setVisible( true ); + } + final String filename = fd.getFile(); + if ( filename != null ) + { + file = new File( fd.getDirectory() + filename ); + } } } @@ -114,6 +117,14 @@ public boolean accept( final File dir, final String name ) } } + private File getFile( String arg ) + { + final File file = new File( arg ); + if( file.exists() ) + return file; + else return null; + } + private boolean isMac() { final String OS = System.getProperty( "os.name", "generic" ).toLowerCase( Locale.ENGLISH ); From 800dc2327973380111053ad7dd635192001e1125 Mon Sep 17 00:00:00 2001 From: HongKee Moon Date: Fri, 6 Jan 2017 18:10:00 +0100 Subject: [PATCH 11/11] Add tags instead of category --- .../java/bdv/ij/BigDataBrowserPlugIn.java | 308 +++++++++++++++--- .../java/bdv/ij/util/SpringUtilities.java | 250 ++++++++++++++ 2 files changed, 516 insertions(+), 42 deletions(-) create mode 100644 src/main/java/bdv/ij/util/SpringUtilities.java diff --git a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java index 04a4fe7..36069ee 100644 --- a/src/main/java/bdv/ij/BigDataBrowserPlugIn.java +++ b/src/main/java/bdv/ij/BigDataBrowserPlugIn.java @@ -1,5 +1,6 @@ package bdv.ij; +import bdv.ij.util.SpringUtilities; import ij.IJ; import ij.ImageJ; import ij.plugin.PlugIn; @@ -7,6 +8,8 @@ import java.awt.Component; import java.awt.Dimension; import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; @@ -17,21 +20,40 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.net.Authenticator; +import java.net.HttpURLConnection; +import java.net.PasswordAuthentication; import java.net.URL; +import java.net.URLConnection; import java.net.URLEncoder; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import javax.imageio.ImageIO; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; import javax.swing.DefaultListCellRenderer; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JRadioButton; import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.SpringLayout; import mpicbg.spim.data.SpimDataException; @@ -53,6 +75,8 @@ public class BigDataBrowserPlugIn implements PlugIn public static String serverUrl = "http://"; + public static String domain = "/public"; + @Override public void run( final String arg ) { @@ -68,13 +92,90 @@ public void run( final String arg ) if ( null == arg || arg == "" ) { - final Object remoteUrl = JOptionPane.showInputDialog( null, "Enter BigDataServer Remote URL:", "BigDataServer", + final JRadioButton publicButton = new JRadioButton( "Public" ); + publicButton.setActionCommand( "Public" ); + + final JRadioButton privateButton = new JRadioButton( "Private" ); + privateButton.setActionCommand( "Private" ); + + ButtonGroup group = new ButtonGroup(); + group.add( publicButton ); + group.add( privateButton ); + + final JTextField id = new JTextField(); + final JPasswordField password = new JPasswordField(); + + final JPanel userPanel = new JPanel( new SpringLayout() ); + userPanel.setBorder( BorderFactory.createTitledBorder( "" ) ); + + userPanel.add( new JLabel( "Enter ID" ) ); + userPanel.add( id ); + userPanel.add( new JLabel( "Enter Password" ) ); + userPanel.add( password ); + + SpringUtilities.makeCompactGrid( userPanel, + 2, 2, //rows, cols + 6, 6, //initX, initY + 6, 6 ); //xPad, yPad + + for ( Component c : userPanel.getComponents() ) + { + c.setEnabled( false ); + } + + Object[] inputFields = { + publicButton, + privateButton, + userPanel, + "Remote URL" }; + + publicButton.addActionListener( new ActionListener() + { + @Override public void actionPerformed( ActionEvent e ) + { + for ( Component c : userPanel.getComponents() ) + { + c.setEnabled( !publicButton.isSelected() ); + } + } + } ); + + privateButton.addActionListener( new ActionListener() + { + @Override public void actionPerformed( ActionEvent e ) + { + for ( Component c : userPanel.getComponents() ) + { + c.setEnabled( privateButton.isSelected() ); + } + } + } ); + + publicButton.setSelected( true ); + + final Object remoteUrl = JOptionPane.showInputDialog( null, inputFields, "BigDataServer", JOptionPane.QUESTION_MESSAGE, new ImageIcon( image ), null, serverUrl ); if ( remoteUrl == null ) return; serverUrl = remoteUrl.toString(); + + if ( privateButton.isSelected() ) + { + Authenticator.setDefault( new Authenticator() + { + protected PasswordAuthentication getPasswordAuthentication() + { + return new PasswordAuthentication( id.getText(), password.getPassword() ); + } + } ); + domain = "/private"; + } + else + { + domain = "/public"; + } } else { @@ -109,38 +210,51 @@ public void run( final String arg ) } final ArrayList< Object > nameList = new ArrayList< Object >(); - String category = ""; + + String tag = ""; try { - - if ( serverUrl.indexOf( "/category/" ) > -1 ) - { - String[] tokens = serverUrl.split( "/category/" ); - serverUrl = tokens[ 0 ]; - category = tokens[ 1 ]; - } - getDatasetList( serverUrl, nameList, category ); + // TODO: search datasets by tag name should be provided soon + getDatasetList( serverUrl, nameList, tag ); } catch ( final IOException e ) { IJ.showMessage( "Error connecting to server at " + serverUrl ); e.printStackTrace(); } - createDatasetListUI( category, serverUrl, nameList.toArray() ); + catch ( NoSuchAlgorithmException e ) + { + e.printStackTrace(); + } + catch ( KeyManagementException e ) + { + e.printStackTrace(); + } + createDatasetListUI( tag, serverUrl, nameList.toArray() ); } class DataSet { + private final String index; private final String name; private final String description; - private final String category; + private final String tags; + private final String sharedBy; + private final Boolean isPublic; - DataSet( String name, String description, String category ) + DataSet( String index, String name, String description, String tags, String sharedBy, Boolean isPublic ) { - + this.index = index; this.name = name; this.description = description; - this.category = category; + this.tags = tags; + this.sharedBy = sharedBy; + this.isPublic = isPublic; + } + + public String getIndex() + { + return index; } public String getName() @@ -153,9 +267,19 @@ public String getDescription() return description; } - public String getCategory() + public String getTags() { - return category; + return tags; + } + + public String getSharedBy() + { + return sharedBy; + } + + public Boolean isPublic() + { + return isPublic; } } @@ -174,15 +298,52 @@ public String getName() } } - private boolean getDatasetList( final String remoteUrl, final ArrayList< Object > nameList, final String searchCategory ) throws IOException + private boolean getDatasetList( final String remoteUrl, final ArrayList< Object > nameList, final String searchTag ) throws IOException, NoSuchAlgorithmException, KeyManagementException { - // Get JSON string from the server - final URL url = new URL( remoteUrl + "/json/?category=" + URLEncoder.encode( searchCategory, "UTF-8" ) ); + TrustManager[] trustAllCerts = new TrustManager[] { + new X509TrustManager() + { + public java.security.cert.X509Certificate[] getAcceptedIssuers() + { + return null; + } - final InputStream is = url.openStream(); - final JsonReader reader = new JsonReader( new InputStreamReader( is, "UTF-8" ) ); + public void checkClientTrusted( X509Certificate[] certs, String authType ) + { + } + + public void checkServerTrusted( X509Certificate[] certs, String authType ) + { + } + + } + }; + + SSLContext sc = SSLContext.getInstance( "SSL" ); + sc.init( null, trustAllCerts, new java.security.SecureRandom() ); + HttpsURLConnection.setDefaultSSLSocketFactory( sc.getSocketFactory() ); - String prevCategory = null; + // Create all-trusting host name verifier + HostnameVerifier allHostsValid = new HostnameVerifier() + { + public boolean verify( String hostname, SSLSession session ) + { + return true; + } + }; + // Install the all-trusting host verifier + HttpsURLConnection.setDefaultHostnameVerifier( allHostsValid ); + + String urlString = resolveRedirectedURL( remoteUrl + domain + "/tag/?name=" + URLEncoder.encode( searchTag, "UTF-8" ) ); + + final URL url = new URL( urlString ); + + URLConnection conn = url.openConnection(); + + System.out.println( url ); + + final InputStream is = conn.getInputStream(); + final JsonReader reader = new JsonReader( new InputStreamReader( is, "UTF-8" ) ); reader.beginObject(); @@ -193,35 +354,35 @@ private boolean getDatasetList( final String remoteUrl, final ArrayList< Object reader.beginObject(); - String id = null, category = null, description = null, thumbnailUrl = null, datasetUrl = null; + String id = null, datasetName = null, tags = null, description = null, thumbnailUrl = null, datasetUrl = null, sharedBy = null; + Boolean isPublic = false; + while ( reader.hasNext() ) { final String name = reader.nextName(); - if ( name.equals( "id" ) ) - id = reader.nextString(); + if ( name.equals( "name" ) ) + datasetName = reader.nextString(); else if ( name.equals( "description" ) ) description = reader.nextString(); else if ( name.equals( "thumbnailUrl" ) ) thumbnailUrl = reader.nextString(); else if ( name.equals( "datasetUrl" ) ) datasetUrl = reader.nextString(); - else if ( name.equals( "category" ) ) - category = reader.nextString(); + else if ( name.equals( "tags" ) ) + tags = reader.nextString(); else if ( name.equals( "index" ) ) - reader.nextString(); + id = reader.nextString(); + else if ( name.equals( "sharedBy" ) ) + sharedBy = reader.nextString(); + else if ( name.equals( "isPublic" ) ) + isPublic = reader.nextBoolean(); else reader.skipValue(); } - if ( prevCategory == null || !prevCategory.equals( category ) ) - { - prevCategory = category; - nameList.add( new Category( prevCategory ) ); - } - if ( id != null ) { - nameList.add( new DataSet( id, description, category ) ); + nameList.add( new DataSet( id, datasetName, description, tags, sharedBy, isPublic ) ); if ( thumbnailUrl != null && StringUtils.isNotEmpty( thumbnailUrl ) ) imageMap.put( id, new ImageIcon( new URL( thumbnailUrl ) ) ); if ( datasetUrl != null ) @@ -238,7 +399,57 @@ else if ( name.equals( "index" ) ) return true; } - private void createDatasetListUI( final String category, final String remoteUrl, final Object[] values ) + private String resolveRedirectedURL( String url ) + { + try + { + URL obj = new URL( url ); + + HttpURLConnection conn = ( HttpURLConnection ) obj.openConnection(); + conn.setReadTimeout( 5000 ); + conn.addRequestProperty( "Accept-Language", "en-US,en;q=0.8" ); + conn.addRequestProperty( "User-Agent", "Mozilla" ); + + boolean redirect = false; + + // normally, 3xx is redirect + int status = conn.getResponseCode(); + if ( status != HttpURLConnection.HTTP_OK ) + { + if ( status == HttpURLConnection.HTTP_MOVED_TEMP + || status == HttpURLConnection.HTTP_MOVED_PERM + || status == HttpURLConnection.HTTP_SEE_OTHER ) + redirect = true; + } + + if ( redirect ) + { + + // get redirect url from "location" header field + String newUrl = conn.getHeaderField( "Location" ); + + // get the cookie if need, for login + String cookies = conn.getHeaderField( "Set-Cookie" ); + + // open the new connnection again + conn = ( HttpURLConnection ) new URL( newUrl ).openConnection(); + conn.setRequestProperty( "Cookie", cookies ); + conn.addRequestProperty( "Accept-Language", "en-US,en;q=0.8" ); + conn.addRequestProperty( "User-Agent", "Mozilla" ); + + return newUrl; + } + + return url; + } + catch ( Exception e ) + { + e.printStackTrace(); + } + return url; + } + + private void createDatasetListUI( final String tag, final String remoteUrl, final Object[] values ) { final JList list = new JList( values ); list.setCellRenderer( new ThumbnailListRenderer() ); @@ -259,7 +470,7 @@ public void mouseClicked( final MouseEvent evt ) try { - BigDataViewer.view( datasetUrlMap.get( ds.getName() ), new ProgressWriterIJ() ); + BigDataViewer.view( ds.getName(), datasetUrlMap.get( ds.getIndex() ), new ProgressWriterIJ() ); } catch ( final SpimDataException e ) { @@ -274,10 +485,10 @@ public void mouseClicked( final MouseEvent evt ) scroll.setPreferredSize( new Dimension( 600, 800 ) ); final JFrame frame = new JFrame(); - if ( category.equals( "" ) ) + if ( tag.equals( "" ) ) frame.setTitle( "BigDataServer Browser - " + remoteUrl ); else - frame.setTitle( "BigDataServer Browser - " + remoteUrl + "/category/" + category ); + frame.setTitle( "BigDataServer Browser - " + remoteUrl + " searched by " + tag ); frame.add( scroll ); frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE ); frame.pack(); @@ -310,8 +521,21 @@ public Component getListCellRendererComponent( else { DataSet ds = ( DataSet ) value; - label.setIcon( imageMap.get( ds.getName() ) ); - label.setText( "" + ds.getName() + "
" + ds.getDescription() + "" ); + label.setIcon( imageMap.get( ds.getIndex() ) ); + + StringBuilder sb = new StringBuilder( "" + ds.getName() + "
" ); + + if ( domain.equals( "/private" ) ) + { + sb.append( "Public: " + ds.isPublic() + "
" ); + if ( !ds.sharedBy.isEmpty() ) + sb.append( "Shared by " + ds.getSharedBy() + "
" ); + } + + sb.append( "Tags: " + ds.getTags() + "
" ); + sb.append( ds.getDescription() + "
" ); + + label.setText( sb.toString() ); label.setHorizontalTextPosition( JLabel.RIGHT ); label.setFont( font ); } diff --git a/src/main/java/bdv/ij/util/SpringUtilities.java b/src/main/java/bdv/ij/util/SpringUtilities.java new file mode 100644 index 0000000..dc3ed9e --- /dev/null +++ b/src/main/java/bdv/ij/util/SpringUtilities.java @@ -0,0 +1,250 @@ +package bdv.ij.util; + +/* + * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle or the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import javax.swing.*; +import javax.swing.SpringLayout; + +import java.awt.*; + +/** + * A 1.4 file that provides utility methods for + * creating form- or grid-style layouts with SpringLayout. + * These utilities are used by several programs, such as + * SpringBox and SpringCompactGrid. + */ +public class SpringUtilities +{ + /** + * A debugging utility that prints to stdout the component's + * minimum, preferred, and maximum sizes. + */ + public static void printSizes( Component c ) + { + System.out.println( "minimumSize = " + c.getMinimumSize() ); + System.out.println( "preferredSize = " + c.getPreferredSize() ); + System.out.println( "maximumSize = " + c.getMaximumSize() ); + } + + /** + * Aligns the first rows * cols + * components of parent in + * a grid. Each component is as big as the maximum + * preferred width and height of the components. + * The parent is made just big enough to fit them all. + * @param rows number of rows + * @param cols number of columns + * @param initialX x location to start the grid at + * @param initialY y location to start the grid at + * @param xPad x padding between cells + * @param yPad y padding between cells + */ + public static void makeGrid( Container parent, + int rows, int cols, + int initialX, int initialY, + int xPad, int yPad ) + { + SpringLayout layout; + try + { + layout = ( SpringLayout ) parent.getLayout(); + } + catch ( ClassCastException exc ) + { + System.err.println( "The first argument to makeGrid must use SpringLayout." ); + return; + } + + Spring xPadSpring = Spring.constant( xPad ); + Spring yPadSpring = Spring.constant( yPad ); + Spring initialXSpring = Spring.constant( initialX ); + Spring initialYSpring = Spring.constant( initialY ); + int max = rows * cols; + + //Calculate Springs that are the max of the width/height so that all + //cells have the same size. + Spring maxWidthSpring = layout.getConstraints( parent.getComponent( 0 ) ). + getWidth(); + Spring maxHeightSpring = layout.getConstraints( parent.getComponent( 0 ) ). + getHeight(); + for ( int i = 1; i < max; i++ ) + { + SpringLayout.Constraints cons = layout.getConstraints( + parent.getComponent( i ) ); + + maxWidthSpring = Spring.max( maxWidthSpring, cons.getWidth() ); + maxHeightSpring = Spring.max( maxHeightSpring, cons.getHeight() ); + } + + //Apply the new width/height Spring. This forces all the + //components to have the same size. + for ( int i = 0; i < max; i++ ) + { + SpringLayout.Constraints cons = layout.getConstraints( + parent.getComponent( i ) ); + + cons.setWidth( maxWidthSpring ); + cons.setHeight( maxHeightSpring ); + } + + //Then adjust the x/y constraints of all the cells so that they + //are aligned in a grid. + SpringLayout.Constraints lastCons = null; + SpringLayout.Constraints lastRowCons = null; + for ( int i = 0; i < max; i++ ) + { + SpringLayout.Constraints cons = layout.getConstraints( + parent.getComponent( i ) ); + if ( i % cols == 0 ) + { //start of new row + lastRowCons = lastCons; + cons.setX( initialXSpring ); + } + else + { //x position depends on previous component + cons.setX( Spring.sum( lastCons.getConstraint( SpringLayout.EAST ), + xPadSpring ) ); + } + + if ( i / cols == 0 ) + { //first row + cons.setY( initialYSpring ); + } + else + { //y position depends on previous row + cons.setY( Spring.sum( lastRowCons.getConstraint( SpringLayout.SOUTH ), + yPadSpring ) ); + } + lastCons = cons; + } + + //Set the parent's size. + SpringLayout.Constraints pCons = layout.getConstraints( parent ); + pCons.setConstraint( SpringLayout.SOUTH, + Spring.sum( + Spring.constant( yPad ), + lastCons.getConstraint( SpringLayout.SOUTH ) ) ); + pCons.setConstraint( SpringLayout.EAST, + Spring.sum( + Spring.constant( xPad ), + lastCons.getConstraint( SpringLayout.EAST ) ) ); + } + + /* Used by makeCompactGrid. */ + private static SpringLayout.Constraints getConstraintsForCell( + int row, int col, + Container parent, + int cols ) + { + SpringLayout layout = ( SpringLayout ) parent.getLayout(); + Component c = parent.getComponent( row * cols + col ); + return layout.getConstraints( c ); + } + + /** + * Aligns the first rows * cols + * components of parent in + * a grid. Each component in a column is as wide as the maximum + * preferred width of the components in that column; + * height is similarly determined for each row. + * The parent is made just big enough to fit them all. + * @param rows number of rows + * @param cols number of columns + * @param initialX x location to start the grid at + * @param initialY y location to start the grid at + * @param xPad x padding between cells + * @param yPad y padding between cells + */ + public static void makeCompactGrid( Container parent, + int rows, int cols, + int initialX, int initialY, + int xPad, int yPad ) + { + SpringLayout layout; + try + { + layout = ( SpringLayout ) parent.getLayout(); + } + catch ( ClassCastException exc ) + { + System.err.println( "The first argument to makeCompactGrid must use SpringLayout." ); + return; + } + + //Align all cells in each column and make them the same width. + Spring x = Spring.constant( initialX ); + for ( int c = 0; c < cols; c++ ) + { + Spring width = Spring.constant( 0 ); + for ( int r = 0; r < rows; r++ ) + { + width = Spring.max( width, + getConstraintsForCell( r, c, parent, cols ). + getWidth() ); + } + for ( int r = 0; r < rows; r++ ) + { + SpringLayout.Constraints constraints = + getConstraintsForCell( r, c, parent, cols ); + constraints.setX( x ); + constraints.setWidth( width ); + } + x = Spring.sum( x, Spring.sum( width, Spring.constant( xPad ) ) ); + } + + //Align all cells in each row and make them the same height. + Spring y = Spring.constant( initialY ); + for ( int r = 0; r < rows; r++ ) + { + Spring height = Spring.constant( 0 ); + for ( int c = 0; c < cols; c++ ) + { + height = Spring.max( height, + getConstraintsForCell( r, c, parent, cols ). + getHeight() ); + } + for ( int c = 0; c < cols; c++ ) + { + SpringLayout.Constraints constraints = + getConstraintsForCell( r, c, parent, cols ); + constraints.setY( y ); + constraints.setHeight( height ); + } + y = Spring.sum( y, Spring.sum( height, Spring.constant( yPad ) ) ); + } + + //Set the parent's size. + SpringLayout.Constraints pCons = layout.getConstraints( parent ); + pCons.setConstraint( SpringLayout.SOUTH, y ); + pCons.setConstraint( SpringLayout.EAST, x ); + } +}