package glg_demos; import java.io.*; import java.net.*; import javax.servlet.*; import javax.servlet.http.*; import javax.imageio.*; import java.awt.image.*; import com.genlogic.*; public final class GlgProcessServletSimple extends HttpServlet implements GlgErrorHandler { static final long serialVersionUID = 0; static GlgObject viewport = null; // Drawing path relative to the servlet app's dir. static String drawing_name = "/drawings/process2.glg"; // Global simulated data used by all servlets. static GlgProcessDemoData data = new GlgProcessDemoData(); ///////////////////////////////////////////////////////////////// // A wrapper around the main method, doGet2(), to properly handle // the access synchronization and unlocking on an error. ///////////////////////////////////////////////////////////////// public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException { try { doGet2( request, response ); } catch( Exception e ) { // Unlock if was interrupted by the exception while locked. GlgObject.UnlockThread(); throw new ServletException( e ); // Re-thow to log an error } // Unlock just in case the code did not do it due to a programming error. GlgObject.UnlockThread(); } ///////////////////////////////////////////////////////////////// // Main servlet's method: everything is handled here. ///////////////////////////////////////////////////////////////// public void doGet2( HttpServletRequest request, HttpServletResponse response ) { InitGLG(); // Init the Toolkit // Load the drawing (if first time) and update with data. // Get requested width/height of the image. int width = GetIntegerParameter( request, "width", 500 ); int height = GetIntegerParameter( request, "height", 400 ); // Limit max. size to avoid running out of heap space creating an image. if( width > 1000 ) width = 1000; if( height > 1000 ) height = 1000; // This example reuses the same drawing between all servlets' threads. // Therefore lock to synchronize and prevent other servlets from // changing the drawing size, etc., before we are done. GlgObject.Lock(); // Load drawing just once and share it among all servlets and threads. // Alternatively, each servlet may load its own drawing. if( viewport == null ) // First time: load the drawing. { viewport = LoadDrawing( drawing_name ); viewport.SetImageSize( width, height ); viewport.SetupHierarchy(); // Setup to prepare to receive data } else // Already loaded, reuse the drawing. viewport.SetImageSize( width, height ); ShowPipes( request ); // Show pipes and flow lines if requested. data.UpdateProcessData(); // Get the new data values from any source. UpdateDrawingWithData(); // Updates drawing with current data. // Setup after data update to prepare to generate image. viewport.SetupHierarchy(); // Create an image of the viewport's graphics. BufferedImage image = (BufferedImage) viewport.CreateImage( null ); GlgObject.Unlock(); // Write the image try { response.setContentType("image/png"); OutputStream out_stream = response.getOutputStream(); ImageIO.write( image, "png", out_stream ); out_stream.close(); } catch( IOException e ) { // Log( "Aborted writing of image file." ); } } ///////////////////////////////////////////////////////////////// // Helper methods ///////////////////////////////////////////////////////////////// int GetIntegerParameter( HttpServletRequest request, String name, int default_value ) { String parameter_string = request.getParameter( name ); if( parameter_string == null || parameter_string.equals( "" ) ) return default_value; try { return Integer.parseInt( parameter_string ); } catch( NumberFormatException e ) { Log( "Invalid parameter value for: " + name + " = " + parameter_string ); return default_value; } } ///////////////////////////////////////////////////////////////// void Log( String msg ) { getServletContext().log( "GlgProcessServletSimple: " + msg ); } // GlgErrorHandler interface method for error handling. public void Error( String message ) { Log( message ); // Log errors Log( GlgObject.GetStackTraceAsString() ); // Print stack } ///////////////////////////////////////////////////////////////// void InitGLG() { // Set an error handler to log errors. GlgObject.SetErrorHandler( this ); GlgObject.Init(); // Init GlgToolkit } ///////////////////////////////////////////////////////////////// GlgObject LoadDrawing( String drawing_name ) { // Get drawing URL relative to the servlet's directory. URL drawing_url = null; try { drawing_url = getServletConfig().getServletContext().getResource( drawing_name ); } catch( MalformedURLException e ) { Log( "Malformed URL: " + drawing_name ); return null; } if( drawing_url == null ) { Log( "Can't find resource: " + drawing_name ); return null; } // Load drawing from the URL viewport = GlgObject.LoadWidget( drawing_url.toString(), GlgObject.URL ); if( viewport == null ) { Log( "Can't load drawing: " + drawing_name ); return null; } // Disable viewport border in the image: let html define it if needed. viewport.SetDResource( "LineWidth", 0. ); return viewport; } ////////////////////////////////////////////////////////////////////////// // Updates drawing state with data. ////////////////////////////////////////////////////////////////////////// void UpdateDrawingWithData() { viewport.SetDResource( "SolventValve/Angle", data.SolventValve ); viewport.SetDResource( "SteamValve/Angle", data.SteamValve ); viewport.SetDResource( "CoolingValve/Angle", data.CoolingValve ); viewport.SetDResource( "WaterValve/Angle", data.WaterValve ); viewport.SetDResource( "Heater/SteamTemperature", data.SteamTemperature ); viewport.SetDResource( "Heater/HeaterTemperature", data.HeaterTemperature ); viewport.SetDResource( "BeforePreHeaterTemperature", data.BeforePreHeaterTemperature ); viewport.SetDResource( "PreHeaterTemperature", data.PreHeaterTemperature ); viewport.SetDResource( "AfterPreHeaterTemperature", data.AfterPreHeaterTemperature ); viewport.SetDResource( "CoolingTemperature", data.CoolingTemperature ); viewport.SetDResource( "Heater/HeaterLevel", data.HeaterLevel ); viewport.SetDResource( "WaterSeparator/WaterLevel", data.WaterLevel ); viewport.SetDResource( "HeaterAlarm", data.HeaterAlarm ? 1. : 0 ); viewport.SetDResource( "WaterAlarm", data.WaterAlarm ? 1. : 0 ); viewport.SetDResource( "Graph/DataGroup/EntryPoint", data.HeaterTemperature ); viewport.SetDResource( "PressureGauge/Value", 5. * data.HeaterPressure ); } ///////////////////////////////////////////////////////////////// // Shows pipes and flow lines if requested. // Constraints in the drawing take care of updating associated // toggle buttons when the pipe or flow line display state is // changed. The last parameter of SetDResource() is set to true // to update the drawing only if the resource value gets changed. ///////////////////////////////////////////////////////////////// void ShowPipes( HttpServletRequest request ) { // Show pipes if requested, default 0. int show_pipes = GetIntegerParameter( request, "show_pipes", 0 ); viewport.SetDResource( "3DPipes/Visibility", (double)show_pipes, true ); // Show flow if requested, default 1. int show_flow = GetIntegerParameter( request, "show_flow", 1 ); viewport.SetDResource( "FlowGroup/Visibility", (double)show_flow, true ); } }