001    package com.sptci.echo2;
002    
003    import java.io.InputStream;
004    import java.io.IOException;
005    import java.util.Locale;
006    import java.util.logging.Logger;
007    
008    import javax.xml.parsers.DocumentBuilder;
009    import javax.xml.parsers.DocumentBuilderFactory;
010    import javax.xml.parsers.ParserConfigurationException;
011    
012    import org.w3c.dom.Document;
013    import org.w3c.dom.Element;
014    import org.xml.sax.SAXException;
015    
016    /**
017     * Representation of a client/server-interaction delay message.
018     * Client/server-interaction delay messages are presented to the user
019     * while the client is communicating synchronously with the server.
020     *
021     * <p><b>Note:</b> This class expects the server delay message to be specified
022     * in a <code>wait.xml</code> (or its localised equivalents) file under the
023     * <code>META-INF/resource/localisation</code> directory in the jar file, since
024     * this is the standard location used for all localisation files.</p>
025     *
026     * <p>&copy; Copyright 2007 Sans Pareil Technologies, Inc.</p>
027     * @author Rakesh Vidyadharan 2007-06-07
028     * @version $Id: ServerDelayMessage.java 3331 2007-06-08 02:17:59Z rakesh $
029     */
030    public class ServerDelayMessage extends nextapp.echo2.webrender.ServerDelayMessage
031    {
032      /**
033       * The resource file that contains the custom wait message to display.
034       *
035       * {@value}
036       */
037      public static final String WAIT_FILE = "/META-INF/resource/localisation/wait";
038      
039      /**
040       * The element that represents the message contained in {@link #WAIT_FILE}.
041       */
042      protected Element message;
043      
044      /**
045       * Create a new instance of the message for the specified locale.
046       *
047       * @see #getInputStream
048       * @see #parseDocument
049       * @param locales The locale(s) of the client browser to use to fetch the
050       *   localised message.
051       * @throws IOException If errors are encountered while reading the resource
052       *   file.
053       */
054      public ServerDelayMessage( final Locale[] locales ) throws IOException
055      {
056        InputStream in = getInputStream( locales );
057        parseDocument( in );
058      }
059      
060      /**
061       * Return the {@link java.io.InputStream} for the resource file.
062       *
063       * @param locales The locale(s) of the client browser to use to fetch the
064       *   localised resource file.
065       * @throws IOException If errors are encountered while fetching the resource
066       *   file.
067       */
068      protected InputStream getInputStream( final Locale[] locales )
069        throws IOException
070      {
071        InputStream inputStream = null;
072        String name = "";
073        
074        for ( Locale locale : locales )
075        {
076          name = WAIT_FILE + "_" + locale.toString() + ".xml";
077          inputStream = ServerDelayMessage.class.getResourceAsStream( name );
078          Logger.getAnonymousLogger().fine( "Trying resource file: " + name );
079    
080          if ( inputStream != null )
081          {
082            break;
083          }
084          else
085          {
086            name = WAIT_FILE + "_" + locale.getLanguage() + ".xml";
087            inputStream = ServerDelayMessage.class.getResourceAsStream( name );
088            Logger.getAnonymousLogger().fine( "Trying resource file: " + name );
089          }
090        }
091        
092        if ( inputStream == null )
093        {
094          name = WAIT_FILE + ".xml";
095          inputStream = ServerDelayMessage.class.getResourceAsStream( name );
096          Logger.getAnonymousLogger().fine( "Trying resource file: " + name );
097        }
098        
099        if ( inputStream == null )
100        {
101          throw new IOException( "Resource not found: " + name + "." );
102        }
103        
104        return inputStream;
105      }
106      
107      /**
108       * Build the {@link org.w3c.dom.Document} out of the contents in the specified
109       * {@link java.io.InputStream}.
110       *
111       * @param inputStream The <code>InputStream</code> to build the document from.
112       * @return Returns the initialised {@link org.w3c.dom.Document} for convenience.
113       * @throws IOException If errors are encountered while reading from the
114       *   <code>InputStream</code>.
115       */
116      protected Document parseDocument( final InputStream inputStream )
117        throws IOException
118      {
119        Document document = null;
120        
121        try
122        {
123          final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
124          final DocumentBuilder builder = factory.newDocumentBuilder();
125          document = builder.parse( inputStream );
126        }
127        catch ( ParserConfigurationException ex )
128        {
129          throw new IOException( "Failed to parse InputStream." );
130        }
131        catch ( SAXException ex )
132        {
133          throw new IOException( "Failed to parse InputStream." );
134        }
135        finally
136        {
137          if ( inputStream != null )
138          {
139            try { inputStream.close(); } catch ( IOException ex ) {} 
140          }
141        }
142    
143        message = document.getDocumentElement();
144        return document;
145      }
146      
147      /**
148       * Return the {@link #message} text to display.
149       */
150      @Override
151      public Element getMessage()
152      {
153        return message;
154      }
155    }