From 30881a5975459400ac6e208cd28d51b6855d1d95 Mon Sep 17 00:00:00 2001 From: HongKee Moon <hkmoon@me.com> Date: Tue, 6 Jan 2015 14:10:24 +0100 Subject: [PATCH] Handle multiple datasets with different contexts and XML file provided through http For example, if BigDataViewer uses http://localhost:8080/HisYFP-SPIM, it will process the xml file directly and access the remote BigDataServer. --- src/main/java/bdv/server/BigDataServer.java | 120 ++------------- src/main/java/bdv/server/CellHandler.java | 153 +++++++++++++++++++ src/main/java/bdv/server/DataSetHandler.java | 46 ++++++ 3 files changed, 211 insertions(+), 108 deletions(-) create mode 100644 src/main/java/bdv/server/CellHandler.java create mode 100644 src/main/java/bdv/server/DataSetHandler.java diff --git a/src/main/java/bdv/server/BigDataServer.java b/src/main/java/bdv/server/BigDataServer.java index 992c7fb..d9faf64 100644 --- a/src/main/java/bdv/server/BigDataServer.java +++ b/src/main/java/bdv/server/BigDataServer.java @@ -1,125 +1,29 @@ package bdv.server; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintWriter; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import mpicbg.spim.data.SpimDataException; -import net.imglib2.img.basictypeaccess.volatiles.array.VolatileShortArray; -import net.imglib2.realtransform.AffineTransform3D; - -import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.handler.AbstractHandler; -import bdv.img.cache.CacheHints; -import bdv.img.cache.LoadingStrategy; -import bdv.img.cache.VolatileCell; -import bdv.img.cache.VolatileGlobalCellCache; -import bdv.img.hdf5.Hdf5ImageLoader; -import bdv.img.remote.AffineTransform3DJsonSerializer; -import bdv.img.remote.RemoteImageLoaderMetaData; -import bdv.spimdata.SequenceDescriptionMinimal; -import bdv.spimdata.SpimDataMinimal; -import bdv.spimdata.XmlIoSpimDataMinimal; - -import com.google.gson.GsonBuilder; +import java.util.HashMap; public class BigDataServer { + static HashMap< String, String > dataSet = new HashMap<>(); + public static void main( final String[] args ) throws Exception { - final String fn = args.length > 0 ? args[ 0 ] : "/Users/pietzsch/Desktop/data/fibsem.xml"; + final String fn = args.length > 0 ? args[ 0 ] : "/Users/moon/Projects/git-projects/BigDataViewer/data/HisYFP-SPIM.xml"; + + dataSet.put( "HisYFP-SPIM", fn ); + final int port = args.length > 1 ? Integer.parseInt( args[ 1 ] ) : 8080; System.setProperty( "org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.StdErrLog" ); final Server server = new Server( port ); - server.setHandler( new CellHandler( fn ) ); - server.start(); - server.join(); - } - static class CellHandler extends AbstractHandler - { - private final VolatileGlobalCellCache< VolatileShortArray > cache; - - private final String metadataJson; - - private final RemoteImageLoaderMetaData metadata; - - private final CacheHints cacheHints; - - public CellHandler( final String xmlFilename ) throws SpimDataException - { - final SpimDataMinimal spimData = new XmlIoSpimDataMinimal().load( xmlFilename ); - final SequenceDescriptionMinimal seq = spimData.getSequenceDescription(); - final Hdf5ImageLoader imgLoader = ( Hdf5ImageLoader ) seq.getImgLoader(); - cache = imgLoader.getCache(); - metadata = new RemoteImageLoaderMetaData( imgLoader, seq ); + String baseURL = "http://" + server.getURI().getHost() + ":" + port + "/"; - final GsonBuilder gsonBuilder = new GsonBuilder(); - gsonBuilder.registerTypeAdapter( AffineTransform3D.class, new AffineTransform3DJsonSerializer() ); - gsonBuilder.enableComplexMapKeySerialization(); - metadataJson = gsonBuilder.create().toJson( metadata ); - cacheHints = new CacheHints( LoadingStrategy.BLOCKING, 0, false ); - } +// System.out.println(baseURL); - @Override - public void handle( final String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response ) throws IOException, ServletException - { - final String cellString = request.getParameter( "p" ); - if ( cellString == null ) - return; - final String[] parts = cellString.split( "/" ); - if ( parts[ 0 ].equals( "cell" ) ) - { - final int index = Integer.parseInt( parts[ 1 ] ); - final int timepoint = Integer.parseInt( parts[ 2 ] ); - final int setup = Integer.parseInt( parts[ 3 ] ); - final int level = Integer.parseInt( parts[ 4 ] ); - VolatileCell< VolatileShortArray > cell = cache.getGlobalIfCached( timepoint, setup, level, index, cacheHints ); - if ( cell == null ) - { - final int[] cellDims = new int[] { - Integer.parseInt( parts[ 5 ] ), - Integer.parseInt( parts[ 6 ] ), - Integer.parseInt( parts[ 7 ] ) }; - final long[] cellMin = new long[] { - Long.parseLong( parts[ 8 ] ), - Long.parseLong( parts[ 9 ] ), - Long.parseLong( parts[ 10 ] ) }; - cell = cache.createGlobal( cellDims, cellMin, timepoint, setup, level, index, cacheHints ); - } - - final short[] data = cell.getData().getCurrentStorageArray(); - final byte[] buf = new byte[ 2 * data.length ]; - for ( int i = 0, j = 0; i < data.length; i++ ) - { - final short s = data[ i ]; - buf[ j++ ] = ( byte ) ( ( s >> 8 ) & 0xff ); - buf[ j++ ] = ( byte ) ( s & 0xff ); - } - - response.setContentType( "application/octet-stream" ); - response.setContentLength( buf.length ); - response.setStatus( HttpServletResponse.SC_OK ); - baseRequest.setHandled( true ); - final OutputStream os = response.getOutputStream(); - os.write( buf ); - os.close(); - } - else if ( parts[ 0 ].equals( "init" ) ) - { - response.setContentType( "application/octet-stream" ); - response.setStatus( HttpServletResponse.SC_OK ); - baseRequest.setHandled( true ); - final PrintWriter ow = response.getWriter(); - ow.write( metadataJson ); - ow.close(); - } - } + server.setHandler( new DataSetHandler( baseURL, dataSet ) ); + server.start(); + server.join(); } } diff --git a/src/main/java/bdv/server/CellHandler.java b/src/main/java/bdv/server/CellHandler.java new file mode 100644 index 0000000..db215cc --- /dev/null +++ b/src/main/java/bdv/server/CellHandler.java @@ -0,0 +1,153 @@ +package bdv.server; + +import bdv.img.cache.CacheHints; +import bdv.img.cache.LoadingStrategy; +import bdv.img.cache.VolatileCell; +import bdv.img.cache.VolatileGlobalCellCache; +import bdv.img.hdf5.Hdf5ImageLoader; +import bdv.img.remote.AffineTransform3DJsonSerializer; +import bdv.img.remote.RemoteImageLoaderMetaData; +import bdv.spimdata.SequenceDescriptionMinimal; +import bdv.spimdata.SpimDataMinimal; +import bdv.spimdata.XmlIoSpimDataMinimal; +import com.google.gson.GsonBuilder; +import mpicbg.spim.data.SpimDataException; +import net.imglib2.img.basictypeaccess.volatiles.array.VolatileShortArray; +import net.imglib2.realtransform.AffineTransform3D; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.handler.AbstractHandler; +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.input.SAXBuilder; +import org.jdom2.output.XMLOutputter; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; + +public class CellHandler extends AbstractHandler +{ + private final VolatileGlobalCellCache< VolatileShortArray > cache; + + private final String metadataJson; + + private final RemoteImageLoaderMetaData metadata; + + private final CacheHints cacheHints; + + private final String xmlFile; + + private final String dataSetURL; + + public CellHandler( final String baseUrl, final String xmlFilename ) throws SpimDataException + { + final SpimDataMinimal spimData = new XmlIoSpimDataMinimal().load( xmlFilename ); + final SequenceDescriptionMinimal seq = spimData.getSequenceDescription(); + final Hdf5ImageLoader imgLoader = ( Hdf5ImageLoader ) seq.getImgLoader(); + cache = imgLoader.getCache(); + metadata = new RemoteImageLoaderMetaData( imgLoader, seq ); + + final GsonBuilder gsonBuilder = new GsonBuilder(); + gsonBuilder.registerTypeAdapter( AffineTransform3D.class, new AffineTransform3DJsonSerializer() ); + gsonBuilder.enableComplexMapKeySerialization(); + metadataJson = gsonBuilder.create().toJson( metadata ); + cacheHints = new CacheHints( LoadingStrategy.BLOCKING, 0, false ); + + // dataSetURL property is used for providing the XML file by replace SequenceDescription>ImageLoader>baseUrl + xmlFile = xmlFilename; + dataSetURL = baseUrl; + } + + @Override + public void handle( final String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response ) throws IOException, ServletException + { + final String cellString = request.getParameter( "p" ); + if ( cellString == null ) + return; + final String[] parts = cellString.split( "/" ); + if ( parts[ 0 ].equals( "cell" ) ) + { + final int index = Integer.parseInt( parts[ 1 ] ); + final int timepoint = Integer.parseInt( parts[ 2 ] ); + final int setup = Integer.parseInt( parts[ 3 ] ); + final int level = Integer.parseInt( parts[ 4 ] ); + VolatileCell< VolatileShortArray > cell = cache.getGlobalIfCached( timepoint, setup, level, index, cacheHints ); + if ( cell == null ) + { + final int[] cellDims = new int[] { + Integer.parseInt( parts[ 5 ] ), + Integer.parseInt( parts[ 6 ] ), + Integer.parseInt( parts[ 7 ] ) }; + final long[] cellMin = new long[] { + Long.parseLong( parts[ 8 ] ), + Long.parseLong( parts[ 9 ] ), + Long.parseLong( parts[ 10 ] ) }; + cell = cache.createGlobal( cellDims, cellMin, timepoint, setup, level, index, cacheHints ); + } + + final short[] data = cell.getData().getCurrentStorageArray(); + final byte[] buf = new byte[ 2 * data.length ]; + for ( int i = 0, j = 0; i < data.length; i++ ) + { + final short s = data[ i ]; + buf[ j++ ] = ( byte ) ( ( s >> 8 ) & 0xff ); + buf[ j++ ] = ( byte ) ( s & 0xff ); + } + + response.setContentType( "application/octet-stream" ); + response.setContentLength( buf.length ); + response.setStatus( HttpServletResponse.SC_OK ); + baseRequest.setHandled( true ); + final OutputStream os = response.getOutputStream(); + os.write( buf ); + os.close(); + } + else if ( parts[ 0 ].equals( "init" ) ) + { + response.setContentType( "application/octet-stream" ); + response.setStatus( HttpServletResponse.SC_OK ); + baseRequest.setHandled( true ); + final PrintWriter ow = response.getWriter(); + ow.write( metadataJson ); + ow.close(); + } + } + + public void provideXML( final Request baseRequest, final HttpServletResponse response ) throws IOException, ServletException + { + final SAXBuilder sax = new SAXBuilder(); + Document doc; + try + { + doc = sax.build( xmlFile ); + } + catch ( final Exception e ) + { + throw new ServletException( e ); + } + final Element root = doc.getRootElement(); + final Element SequenceDescription = root.getChild( "SequenceDescription" ); + final Element ImageLoader = SequenceDescription.getChild( "ImageLoader" ); + + ImageLoader.setAttribute( "format", "bdv.remote" ); + + ImageLoader.removeChild( "hdf5" ); + + final Element baseUrl = new Element( "baseUrl" ); + baseUrl.setText( dataSetURL ); + ImageLoader.setContent( baseUrl ); + +// System.out.println(ImageLoader.getAttribute( "format" )); +// System.out.println(ImageLoader.getValue()); + + response.setContentType( "application/xml" ); + response.setStatus( HttpServletResponse.SC_OK ); + baseRequest.setHandled( true ); + final PrintWriter ow = response.getWriter(); + ow.write( new XMLOutputter().outputString( doc ) ); + ow.close(); + } +} \ No newline at end of file diff --git a/src/main/java/bdv/server/DataSetHandler.java b/src/main/java/bdv/server/DataSetHandler.java new file mode 100644 index 0000000..8e66076 --- /dev/null +++ b/src/main/java/bdv/server/DataSetHandler.java @@ -0,0 +1,46 @@ +package bdv.server; + +import mpicbg.spim.data.SpimDataException; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.handler.AbstractHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.HashMap; + +public class DataSetHandler extends AbstractHandler +{ + final private HashMap< String, CellHandler > cellHandlers; + + public DataSetHandler( String baseURL, HashMap< String, String > ds ) throws SpimDataException, MalformedURLException + { + cellHandlers = new HashMap<>(); + + for ( String dataSet : ds.keySet() ) + { + cellHandlers.put( dataSet, new CellHandler( baseURL + dataSet + "/", ds.get( dataSet ) ) ); + } + } + + @Override + public void handle( final String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response ) throws IOException, ServletException + { + String dsName = target.replace( "/", "" ); + + if ( cellHandlers.containsKey( dsName ) ) + { + if ( request.getParameter( "p" ) != null ) + cellHandlers.get( dsName ).handle( target, baseRequest, request, response ); + else + // Provide XML file + cellHandlers.get( dsName ).provideXML( baseRequest, response ); + } + else + { + return; + } + } +} -- GitLab