1  This file was updated on Thursday, 2002-10-10 at 9:05 PM
   2  
   3  
   4  ============================================================
   5  MyXMLApplet.java
   6  ============================================================
   7  
   8  
   9  /*
  10   *  MyXMLApplet.java
  11   *
  12   *  Created on September 27, 2002, 4:00 PM
  13   *  updated by JMH on October 05, 2002 at 09:17 AM
  14   *
  15   *  jar command used:
  16   *  jar cvf umlgui.jar edu/uml/gui/UmlGuiException.class edu/uml/gui/UmlGuiException.java
  17   *
  18   *  To compile this .java file on the WebLabPCs, use:
  19   *     javac -classpath .:/opt/JRun/lib/ext/xerces.jar MyXMLApplet.java
  20   */
  21  
  22  import java.awt.* ;             // required for Swing, too
  23  import javax.swing.* ;          // the standard Swing package
  24  
  25  import javax.xml.parsers.* ;    // for DocumentBuilderFactory and DocumentBuilder
  26  import org.w3c.dom.* ;          // for Document and the Document Object Model
  27  import org.xml.sax.* ;          // for SAXException
  28  import java.io.* ;              // for IOException
  29  import java.net.* ;             // for URL
  30  
  31  import edu.uml.gui.* ;          // the UML GUI package
  32  
  33  
  34  /** This program demonstrates reading an XML document from a server, 
  35   *  manipulating it, and writing it back to the server.
  36   *  @author  Jesse Heines, <a href="mailto:heines@cs.uml.edu">heines@cs.uml.edu</a>
  37   *  @version 1.9, updated by JMH on October 04, 2002 at 08:18 PM
  38   */
  39  public class MyXMLApplet extends javax.swing.JApplet
  40  {
  41    /** test case number to run */
  42    int intCaseNo = 5 ;
  43    
  44    /** applet content pane */
  45    Container c ;
  46    
  47    /** the path on the server to the XML file to open */
  48    private String strXMLInputFilePath ; 
  49    // note that this path must always be on the server from which the applet was
  50    // loaded, therefore it is best to prefix the file path with getCodeBase()
  51    
  52    /** the XML Document object */
  53    private Document doc ;
  54    
  55    /** text area to hold output */
  56    JTextArea jtxtOut ;
  57    
  58  
  59    /** Creates a new instance of TestArchive */
  60    public MyXMLApplet()
  61    {
  62    }
  63    
  64  
  65    /** the standard JApplet init method, called once when the applet starts */
  66    public void init()
  67    {
  68      // Notes:
  69      // (1)  an applet can only access files on the server from which it was 
  70      //        loaded
  71      // (2)  recall that getCodeBase() returns the path on the server from 
  72      //        which this applet was loaded
  73      // (3)  to get only the server from which this applet was loaded so that 
  74      //        you can construct a different path on that server, use 
  75      //        getCodeBase().getHost()
  76      // (4)  the base of the path where your XML files will be stored is always
  77      //        /students/ + the user name you specify, therefore to read a file
  78      //        that you previously stored, use "/students/username/..."
  79      switch ( intCaseNo )
  80      {
  81        case 1 : 
  82          strXMLInputFilePath = getCodeBase() + "j2.xml" ;
  83          break ;
  84        case 2 : 
  85          strXMLInputFilePath = "http://" + getCodeBase().getHost() + 
  86                           "/~heines/91.461/91.461-2002-03f/course.xml" ;
  87          break ;
  88        case 3 : 
  89          strXMLInputFilePath = "http://philip/~heines/91.513/91.513-2002-03f/course.xml" ;
  90          break ;
  91        case 4 : 
  92          strXMLInputFilePath = getCodeBase() + "j3.xml" ;
  93          break ;
  94        case 5 : 
  95          strXMLInputFilePath = "http://" + getCodeBase().getHost() + 
  96            "/students/heines/uploads/linux/j3.xml" ;
  97          break ;
  98        case 6 : 
  99          strXMLInputFilePath = "http://" + getCodeBase().getHost() + 
 100                           "/students/heines/j3a.xml" ;
 101          break ;
 102      }
 103      // System.out.println( strXMLInputFilePath ) ;
 104  
 105      // get a reference to the applet content pane
 106      c = getContentPane() ;
 107  
 108      // put a scrollable text area on the screen
 109      Font font16 = new Font( "Courier New", Font.BOLD, 16 ) ;
 110      jtxtOut = new JTextArea() ;
 111      jtxtOut.setFont( font16 ) ;
 112      JScrollPane jspnOut = new JScrollPane( jtxtOut ) ;
 113      c.add( jspnOut, BorderLayout.CENTER ) ;
 114      
 115      // initialize document
 116      try {
 117        doc = UmlGui.openXMLDocument( strXMLInputFilePath ) ;
 118        // if ( doc == null )
 119        //   System.out.println( "null" ) ;
 120        // else
 121        //   System.out.println( doc.getDocumentElement() ) ;
 122      } catch ( UmlGuiException uge ) {
 123        System.out.println( uge.toString() ) ;
 124      }
 125  
 126    } // init()
 127    
 128  
 129    /** the standard JApplet start method, called each time the page is visited */
 130    public void start()
 131    {
 132      String strText = "" ;
 133  
 134      // show information about this applet
 135      strText += "Applet Loaded at:  " + (new java.util.Date()).toString() ;
 136      strText += "\nTest Case Number:  " + intCaseNo ;
 137      strText += "\nApplet Directory:  " + getCodeBase().toString() ;
 138      strText += "\n  XML Input File:  " + strXMLInputFilePath ;
 139      
 140      if ( doc == null ) 
 141      {
 142        strText += "\n\ndoc is null" ;
 143        jtxtOut.setText( strText ) ;
 144        return ;
 145      }
 146      
 147      // show some of the data from the XML file
 148      strText += "\n" + showSomeXMLData() ;
 149      // manipulate the data
 150      modifyXMLData() ;
 151      // show some of the data again
 152      strText += "\n" + showSomeXMLData() ;
 153  
 154      // store the XML file back on the server
 155      String strReturn = null ;
 156  
 157      try {
 158        switch ( intCaseNo )
 159        {
 160          case 1 :
 161            strReturn = UmlGui.storeXMLDocument( this, doc, "j2.xml", 
 162                  "uml/gui/one" ) ;
 163            break ;
 164          case 2 :
 165            strReturn = UmlGui.storeXMLDocument( this, doc, "course.xml", 
 166                  "uml/gui/91.461" ) ;
 167            break ;
 168          case 3 :
 169            strReturn = UmlGui.storeXMLDocument( this, doc, "course.xml", 
 170                  "uml/gui/91.513" ) ;
 171            break ;
 172          case 4 :
 173          case 5 :
 174            strReturn = UmlGui.storeXMLDocument( this, doc, "j3.xml", 
 175              "uploads/linux/" ) ;
 176            break ;
 177          case 6 :
 178            strReturn = UmlGui.storeXMLDocument( this, doc, "j3a.xml" ) ;
 179            break ;
 180        }
 181      } catch ( UmlGuiException uge ) {
 182        System.out.println( uge.toString() ) ;
 183      }
 184  
 185      // test return value
 186      if ( strReturn != null ) 
 187      {
 188        strReturn = strReturn.trim() ;
 189        if ( strReturn.startsWith( "http:" ) )
 190          strText += "\n\nYour document was stored at URL:\n   " + strReturn ;
 191        else
 192          strText += "\nError: " + strReturn ;
 193      }
 194      
 195      // display all results in the text area
 196      jtxtOut.setText( strText ) ;
 197    }
 198    
 199    
 200    /** this method returns some of the XML data in a printable string just to
 201     *  show what it looks like
 202     */
 203    private String showSomeXMLData()
 204    {
 205      // initialize the string to return
 206      String strText = "" ;
 207      
 208      // get the root element
 209      Element root = doc.getDocumentElement() ;
 210      
 211      // initialize a list of nodes
 212      NodeList nodes = null ;
 213  
 214      // populate the list of nodes appropriately for the different cases
 215      switch ( intCaseNo )
 216      {
 217        case 1 : 
 218        case 4 : 
 219        case 5 : 
 220        case 6 : 
 221          nodes = root.getElementsByTagName( "name" ) ;
 222          break ;
 223        case 2 :
 224        case 3 :
 225          nodes = root.getElementsByTagName( "student" ) ;
 226          break ;
 227      }
 228  
 229      // generate output from the list of node appropriate to the different cases
 230      if ( nodes != null )
 231        for ( int k = 0 ; k < nodes.getLength() && k < 6 ; k++ )
 232        {
 233          strText += "\nNode #" + ( k+1 < 10 ? " " : "" ) + (k+1) + ":  " ;
 234          switch ( intCaseNo )
 235          {
 236            case 1 :
 237            case 4 :
 238            case 5 :
 239            case 6 :
 240              strText += ((Element) nodes.item( k )).getFirstChild().getNodeValue() ; 
 241              break ;
 242            case 2 :
 243            case 3 :
 244              strText += ((Element) nodes.item( k )).getAttribute( "name" ) ;
 245              break ;
 246          }
 247        }
 248      
 249      // return the generated output
 250      return strText ;
 251    }
 252  
 253  
 254    /** this method modifies the XML data a bit just to show what might be done
 255     */
 256    private void modifyXMLData()
 257    {
 258      // get the root element
 259      Element root = doc.getDocumentElement() ;
 260      
 261      // initialize a list of nodes
 262      NodeList nodes = null ;
 263  
 264      // populate the list of nodes appropriately for the different cases
 265      switch ( intCaseNo )
 266      {
 267        case 1 : 
 268        case 4 : 
 269        case 5 : 
 270        case 6 :
 271          nodes = root.getElementsByTagName( "name" ) ;
 272          break ;
 273        case 2 :
 274        case 3 :
 275          nodes = root.getElementsByTagName( "student" ) ;
 276          break ;
 277      }
 278  
 279      // reverse the order of the nodes
 280      if ( nodes != null )
 281      {
 282        // create a new element to serve as the root which will hold the 
 283        // manipulated data
 284        Element elemNewRoot = doc.createElement( root.getTagName() ) ;
 285      
 286        // append the existing nodes in reverse order
 287        for ( int k = nodes.getLength() - 1 ; k > -1 ; k-- )
 288        {
 289          elemNewRoot.appendChild( nodes.item( k ) ) ;
 290        }
 291        
 292        // replace the old document root with the new one
 293        doc.replaceChild( elemNewRoot, root ) ;
 294      }
 295    }
 296  
 297  
 298  
 299  }
 300  
 301  
 302  ============================================================
 303  MyXMLApplet.html
 304  ============================================================
 305  
 306  
 307  <HTML>
 308  <!--
 309    updated by JMH on September 28, 2002 at 9:22 PM
 310  -->
 311  <HEAD>
 312     <TITLE>MyXMLApplet HTML Page</TITLE>
 313  </HEAD>
 314  <BODY>
 315  
 316  <H3>
 317    <HR WIDTH="100%">
 318      <script type="text/javascript">
 319        var strPageName = location.toString() ;
 320        strPageName = strPageName.substr( strPageName.lastIndexOf( "/" ) + 1 ) ;
 321        document.writeln( "Applet " + strPageName ) ;
 322      </script>
 323    <HR WIDTH="100%">
 324  </H3>
 325  
 326  <P>
 327  <!-- 
 328    <APPLET codebase=".." code="tests/TestXML.class" width="350" height="200"></APPLET>
 329    <APPLET codebase=".." code="xml/TestXML.class" width="350" height="200"></APPLET>
 330  -->
 331  <APPLET code="MyXMLApplet.class" width="800" height="400"></APPLET>
 332  </P>
 333  <!--
 334  <HR WIDTH="100%"><FONT SIZE="-1"><I>Generated by NetBeans IDE, modified by JMH</I></FONT>
 335  -->
 336  </BODY>
 337  </HTML>
 338  
 339  
 340  ============================================================
 341  edu\uml\gui\UmlGui.java
 342  ============================================================
 343  
 344  
 345  /*
 346   *  UmlGui.java
 347   *  by Jesse M. Heines, heines@cs.uml.edu
 348   *
 349   *  Created on September 27, 2002, 7:29 PM
 350   *
 351   *  Note: To use this class, files xercesImpl.jar and xerces.jar must be 
 352   *  installed in the lib\ext directory of the JRE directory that is being 
 353   *  used by Internet Explorer.  On my systems, this is 
 354   *  C:\Program Files\Java\j2re1.4.0_02\lib\ext.
 355   *
 356   *  To compile this class, xerces.jar and xercesImpl.jar must be in the 
 357   *  classpath.  The easiest way to do this is to put these files in the 
 358   *  jre\lib\ext directory of the Java Development Kit home.  On my systems,
 359   *  this is C:\Program Files\j2sdk1.4.0_02\jre\lib\ext.
 360   *
 361   *  Files xerces.jar and xercesImpl.jar are downloadable from 
 362   *  http://xml.apache.org/dist/xerces-j/, where they are contained within 
 363   *  file Xerces-J-bin.2.1.0.zip.  That ZIP file includes three .jar files 
 364   *  as well as all of the API documentation.
 365   *
 366   *  To compile this .java file on the WebLabPCs, cd to its directory and
 367   *  enter:
 368   *     javac -classpath ../../..:/opt/JRun/lib/ext/xerces.jar UmlGui.java
 369   */
 370  package edu.uml.gui ;
 371  
 372  import java.awt.* ;             // required for Swing, too
 373  import javax.swing.* ;          // the standard Swing package, for getCodeBase
 374  import java.applet.* ;          // for Applet
 375  
 376  import javax.xml.parsers.* ;    // for DocumentBuilderFactory and DocumentBuilder
 377  import org.w3c.dom.* ;          // for Document and the Document Object Model
 378  import org.xml.sax.* ;          // for SAXException
 379  import java.io.* ;              // for IOException
 380  import java.net.* ;             // for URL
 381  
 382  import org.apache.xml.serialize.* ;   // for OutputFormat
 383  
 384  
 385  /** This class contains all the methods available in the edu.uml.gui package.
 386   *
 387   *  @author  Jesse M. Heines, <a href="mailto:heines@cs.uml.edu">heines@cs.uml.edu</a>
 388   *  @version 1.0, updated by JMH on October 05, 2002 at 11:15 AM
 389   */
 390  public class UmlGui {
 391    
 392    /** location of umlguiStoreXML.jsp */
 393    private static String strServletURI = "/~heines/xml/umlguiStoreXML9.jsp" ;
 394    /** location of umlguiStoreXML servlet */
 395    // private static String strServletURI = "/~heines/servlet/umlguiStoreXML6" ;
 396  
 397  
 398    /** Creates a new instance of UmlGui */
 399    public UmlGui() {
 400    }
 401    
 402  
 403    /** This <code>public static</code> method opens and XML file and returns the 
 404     *  <code>Document</code> object representing the XML document it contains.</p>
 405     *  <p>If the file cannot be opened or parsed, a <code>UmlGuiException</code> is 
 406     *  thrown. This is a checked exception derived from <code>IOException</code>, 
 407     *  so this method must be called from within a try<code></code> block.
 408     *  @param strFilePath full path to the XML file to be opened
 409     *  @return <code>Document</code> object for that file
 410     *  @throws UmlGuiException
 411     */
 412    public static Document openXMLDocument( String strFilePath ) 
 413        throws UmlGuiException
 414    {
 415      // (1) get an instance of the DocumentBuilderFactory class
 416      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance() ;
 417      
 418      // (2) use the instance of the DocumentBuilderFactory class to get 
 419      // an instance of the DocumentBuilder class, noting that the call 
 420      // to newDocumentBuilder() can throw a ParserConfigurationException
 421      DocumentBuilder db = null ;  // declare outside of try block 
 422      try {
 423        db = dbf.newDocumentBuilder() ;
 424      } catch ( ParserConfigurationException pce ) {
 425        String err = pce.toString() ;
 426        throw new UmlGuiException( 
 427            "\nParser Configuration Error (ParserConfigurationException) in openXMLDocument:" + 
 428            "\n   " + err.substring( 0, err.indexOf( ":" ) + 1 ) + 
 429            "\n   " + err.substring( err.indexOf( ":" ) + 2 ) ) ;
 430      }
 431  
 432      // (3) use the instance of the DocumentBuilder class to open and parse the 
 433      // document, returning the Document object if successfull or null if not
 434      Document doc = null ;
 435      try {
 436        doc = db.parse( strFilePath ) ;
 437        return doc ;
 438      } catch ( SAXException saxe ) {
 439        String err = saxe.toString() ;
 440        throw new UmlGuiException( 
 441            "\nParsing Error (SAXException) in openXMLDocument:" + 
 442            "\n   " + err.substring( 0, err.indexOf( ":" ) + 1 ) + 
 443            "\n   " + err.substring( err.indexOf( ":" ) + 2 ) ) ;
 444      } catch ( FileNotFoundException fnfe ) {
 445        String err = fnfe.toString() ;
 446        throw new UmlGuiException( 
 447            "\nFile Not Found Error ( FileNotFoundException ) in openXMLDocument:" + 
 448            "\n   " + err.substring( 0, err.indexOf( ":" ) + 1 ) + 
 449            "\n   " + err.substring( err.indexOf( ":" ) + 2 ) ) ;
 450      } catch ( IOException ioe ) {
 451        String err = ioe.toString() ;
 452        throw new UmlGuiException( 
 453            "\nI/O Error ( IOException ) in openXMLDocument:" + 
 454            "\n   " + err.substring( 0, err.indexOf( ":" ) + 1 ) + 
 455            "\n   " + err.substring( err.indexOf( ":" ) + 2 ) ) ;
 456      }
 457    } // openXMLDocument(...)
 458  
 459    
 460    /** This <code>private static</code> method saves an XML Document on a 
 461     *  specified system. It is the main version of this method that is called 
 462     *  by all overloaded methods with the same name.</p>
 463     *  <p>It works by calling the current version of <code>umlguiStoreXML.jsp</code> 
 464     *  (specified in <code>private static String strServletURI</code>) on the 
 465     *  system specified in the first parameter.  Note that it will only work if 
 466     *  the system specified in the first parameter is the same as that from which 
 467     *  the calling applet was loaded.</p>
 468     *  <p>The file is saved in the user area specified in the third parameter, 
 469     *  under the name specified in the fourth parameter, and in the subdirectory 
 470     *  specified in the fifth parameter.</p>
 471     *  <p>Note that if a file exists with the same name in the same area and the
 472     *  same subdirectory, it is overwritten.</p>  
 473     *  <p>If an error occurs, a <code>UmlGuiException</code> is thrown.  This is a 
 474     *  checked exception derived from <code>IOException</code>, so this method must 
 475     *  be called from within a <code>try</code> block.</p>
 476     *  @param strHost      name of host system on which to store the document
 477     *  @param doc          XML document to save
 478     *  @param strFileName  name under which to store the document
 479     *  @param strFilePath  subdirectory of the user area in which to store the 
 480     *                        document
 481     *  @param strUserName  name of user area in which to store the document
 482     *  @return a <code>String</code> indicating the full path to the XML document
 483     *      stored
 484     *  @throws UmlGuiException
 485     */
 486    private static String storeXMLDocument( String strHost, Document doc, 
 487          String strFileName, String strFilePath, String strUserName ) 
 488        throws UmlGuiException
 489    {
 490      //// clean up passed parameters
 491      
 492      // remove excess characters from user name
 493      strUserName = strUserName.trim() ;
 494      
 495      // user name cannot contain spaces
 496      if ( strUserName.indexOf( " " ) != -1 )
 497        throw new UmlGuiException( 
 498            "\nInvalid user name in storeXMLDocument:" + 
 499            "\n   the user name cannot contain spaces" ) ;
 500      
 501      // file name cannot contain a path (slashes)
 502      strFileName = strFileName.trim() ;
 503      if ( strFileName.indexOf( "/" ) != -1 )
 504        throw new UmlGuiException( 
 505            "\nInvalid file name in storeXMLDocument:" + 
 506            "\n   the file name cannot contain a path (no slashes (\"/\") " +
 507            "are allowed)" ) ;
 508      
 509      // file name cannot contain spaces
 510      if ( strFileName.indexOf( " " ) != -1 )
 511        throw new UmlGuiException( 
 512            "\nInvalid file name in storeXMLDocument:" + 
 513            "\n   the file name cannot contain spaces" ) ;
 514      
 515      // remove leading and trailing slashes from file path
 516      if ( strFilePath != null )
 517      {
 518        strFilePath = strFilePath.trim() ;
 519        while ( strFilePath.startsWith( "/" ) )
 520          strFilePath = strFilePath.substring( 1 ) ;
 521        while ( strFilePath.endsWith( "/" ) )
 522          strFilePath = strFilePath.substring( 0, strFilePath.length()-1 ) ;
 523      }
 524      
 525      // replace null file path with ""
 526      if ( strFilePath == null ) 
 527        strFilePath = "" ;
 528      
 529      // file path cannot contain back slashes
 530      if ( strFilePath != null && strFilePath.indexOf( "\\" ) != -1 )
 531        throw new UmlGuiException( 
 532            "\nInvalid Path Error in storeXMLDocument:" + 
 533            "\n   the file path cannot contain back slashes (\"\\\"):  " + 
 534                strFilePath + 
 535            "\n   use only forward slashes (\"/\") in the path specification" ) ;
 536      
 537      // file path cannot contain spaces
 538      if ( strFilePath.indexOf( " " ) != -1 )
 539        throw new UmlGuiException( 
 540            "\nInvalid file path in storeXMLDocument:" + 
 541            "\n   the file path cannot contain spaces" ) ;
 542      
 543      // remove excess characters from host name
 544      if ( strHost != null ) 
 545        strHost = strHost.trim() ;
 546      
 547      ////  send the XML document to the server
 548      ////  reference:  Hall & Brown, pp. 1083-1090
 549      ////  steps referred to are on pp. 1084-1085
 550  
 551      // Step 1
 552      URL urlData ;
 553      String strProtocol = "http" ;
 554      int intPort = -1 ;
 555      
 556      try {
 557        urlData = new URL( strProtocol, strHost, intPort, strServletURI ) ;
 558      } catch ( MalformedURLException murle ) {
 559        throw new UmlGuiException( 
 560            "\nMalformedURLException at Step 1 in storeXMLDocument:" + 
 561            "\n   " + murle.toString() ) ;
 562      }
 563      // System.out.println( "urlData = " + urlData ) ;
 564  
 565      // Step 2 - establish URL connection
 566      URLConnection urlcConn ;
 567      try {
 568        urlcConn = urlData.openConnection() ;
 569      } catch ( IOException ioe ) {
 570        throw new UmlGuiException( 
 571            "\nIOException at Step 2 in storeXMLDocument:" + 
 572            "\n   " + ioe.toString() ) ;
 573      }
 574      // System.out.println( "urlcConn = " + urlcConn ) ;
 575      
 576      // Step 3 - prevent browser from caching results
 577      urlcConn.setUseCaches( false ) ;
 578      
 579      // Step 4 - allow system to send as well as receive data
 580      urlcConn.setDoOutput( true ) ;
 581      
 582      // Step 5 - creating stream to buffer data that will be sent
 583      ByteArrayOutputStream baosByteStream = new ByteArrayOutputStream( 512 ) ;
 584      // System.out.println( "baosByteStream = " + baosByteStream ) ;
 585      
 586      // Step 6a (see p. 1075 Step 2) - attaching an output stream
 587      ObjectOutputStream oosOut ;
 588      try {
 589        oosOut = new ObjectOutputStream( baosByteStream ) ;
 590      } catch ( IOException ioe ) {
 591        throw new UmlGuiException( 
 592            "\nIOException at Step 6a in storeXMLDocument:" + 
 593            "\n   " + ioe.toString() ) ;
 594      }
 595      // System.out.println( "oosOut = " + oosOut ) ;
 596   
 597      // Step 6b - make a serializable version of the XML Document object
 598      // reference:  www-106.ibm.com/developerworks/xml/library/x-injava2/?dwzone=xml
 599      OutputFormat of = new OutputFormat( doc ) ;
 600      of.setIndenting( true ) ;
 601      of.setIndent( 2 ) ;
 602      // of.setPreserveSpace( true ) ;
 603      StringWriter sw = new StringWriter() ;
 604        // use a StringWriter instead of serializing directly to the 
 605        // ObjectOutputStream because serializing directly yields a 
 606        // java.io.OptionalDataException when reading the data with 
 607        // ObjectInputStream.readObject()
 608      XMLSerializer xmlser = new XMLSerializer( sw, of ) ;
 609      try {
 610        xmlser.serialize( doc ) ;
 611      } catch ( IOException ioe ) {
 612         throw new UmlGuiException( 
 613            "\nIOException at Step 6b in storeXMLDocument:" + 
 614            "\n   " + ioe.toString() ) ;
 615      }
 616      // System.out.println( "Serialization done." ) ;
 617      
 618      // Step 7 - put data to be sent into output buffer
 619      try {
 620        oosOut.writeObject( strUserName ) ;
 621        oosOut.writeObject( strFileName ) ;
 622        oosOut.writeObject( strFilePath ) ;
 623        oosOut.writeObject( sw.toString() ) ;
 624        oosOut.flush() ;
 625        oosOut.close() ;
 626      } catch ( IOException ioe ) {
 627        throw new UmlGuiException( 
 628            "\nIOException at Step 7 in storeXMLDocument:" + 
 629            "\n   " + ioe.toString() ) ;
 630      }
 631      // System.out.println( "Buffer loaded." ) ;
 632      
 633      // Step 8 - set length out output buffer
 634      urlcConn.setRequestProperty( 
 635          "Content-Length", String.valueOf( baosByteStream.size() ) ) ;
 636      
 637      // Step 9 "is irrelevant when sending serialized data" (Hall & Brown)
 638      
 639      // Step 10 - actual data send
 640      try {
 641        baosByteStream.writeTo( urlcConn.getOutputStream() ) ;
 642      } catch ( IOException ioe ) {
 643        throw new UmlGuiException( 
 644            "\nIOException at Step 8 in storeXMLDocument:" + 
 645            "\n   " + ioe.toString() ) ;
 646      }
 647      // System.out.println( "Data sent." ) ;
 648     
 649      // begin steps to read response - straight ASCII
 650      
 651      // Step 11 - ASCII version (see p. 1073 Step 5)
 652      
 653      BufferedReader buffIn = null ;
 654      try {
 655        buffIn = new BufferedReader( new InputStreamReader( urlcConn.getInputStream() ) ) ;
 656      } catch ( FileNotFoundException fnfe ) {
 657        throw new UmlGuiException( 
 658            "\nFileNotFoundException at Step 11 in storeXMLDocument:" + 
 659            "\n   " + fnfe.toString() ) ;
 660      } catch ( IOException ioe ) {
 661        throw new UmlGuiException( 
 662            "\nIOException at Step 11 in storeXMLDocument:" + 
 663            "\n   " + ioe.toString() ) ;
 664      }
 665      // System.out.println( "buffIn = " + buffIn ) ;
 666  
 667      // Step 12 - ASCII version (see p. 1073 Step 6)
 668      
 669      String strReturned = "" ;
 670      String strLineRead = "" ;
 671      try {
 672        while ( ( strLineRead = buffIn.readLine() ) != null )
 673        {
 674          strReturned += strLineRead + "\n" ;
 675        }
 676      } catch ( IOException ioe ) {
 677        throw new UmlGuiException( 
 678            "\nIOException at Step 12 in storeXMLDocument:" + 
 679            "\n   " + ioe.toString() ) ;
 680      }
 681      
 682      // Step 13 - ASCII version (see p. 1073 Step 7)
 683      
 684      try {
 685       buffIn.close() ;
 686      } catch ( IOException ioe ) {
 687        throw new UmlGuiException( 
 688            "\nIOException at Step 13 in storeXMLDocument:" + 
 689            "\n   " + ioe.toString() ) ;
 690      }
 691      
 692      // return result
 693      return strReturned ;
 694  
 695    } // private static String storeXMLDocument(...)
 696  
 697  
 698    /** <p>This five-parameter <code>public static</code> method calls 
 699     *  <code>(Applet.getCodeBase()).getHost()</code> to get the name of the 
 700     *  host system on which the calling applet is running, which is required 
 701     *  to store the host on which to the XML document, and then calls the private 
 702     *  version of <code>storeXMLDocument</code> to do the actual save.</p>
 703     *  <p>Note that you do not usually want to call this version of this method
 704     *  because you will typically store your XML documents under the name in the
 705     *  directory from which the applet was run. This name can be extracted from 
 706     *  the applet's code base by the four-parameter version of this method.
 707     *  @param app          the calling applet
 708     *  @param doc          XML document to save
 709     *  @param strFileName  name under which to store the document
 710     *  @param strFilePath  subdirectory of the user area in which to store the 
 711     *                        document
 712     *  @param strUserName  name of user area in which to store the document
 713     *  @return a <code>String</code> indicating the full path to the XML document
 714     *      stored
 715     *  @throws UmlGuiException
 716     */
 717    public static String storeXMLDocument( Applet app, Document doc, 
 718          String strFileName, String strFilePath, String strUserName ) 
 719        throws UmlGuiException
 720    {
 721      return storeXMLDocument( (app.getCodeBase()).getHost(), doc, strFileName, 
 722          strFilePath, strUserName ) ;
 723    }
 724  
 725  
 726    /** This four-parameter <code>public static</code> method parses the user 
 727     *  name from <code>Applet.getCodeBase()</code> and then calls the five-parameter 
 728     *  version of this same method.
 729     *  @param app          the calling applet
 730     *  @param doc          XML document to save
 731     *  @param strFileName  name under which to store the document
 732     *  @param strFilePath  subdirectory of the user area in which to store the 
 733     *                        document
 734     *  @return a <code>String</code> indicating the full path to the XML document
 735     *      stored
 736     *  @throws UmlGuiException
 737     */
 738    public static String storeXMLDocument( Applet app, Document doc, 
 739      String strFileName, String strFilePath ) 
 740      throws UmlGuiException
 741    {
 742      // initialize user name to entire applet source string
 743      String strUserName = app.getCodeBase().toString() ;
 744      
 745      // find the name prefix, either "~", "%7e", or "%7E", and set the name 
 746      // starting position appropriately
 747      int posTilde = strUserName.indexOf( "~" ) ;
 748      if ( posTilde == -1 )
 749      {
 750        posTilde = strUserName.indexOf( "%7e" ) ;
 751        if ( posTilde == -1 )
 752        {
 753          posTilde = strUserName.indexOf( "%7E" ) ;
 754          if ( posTilde != -1 )
 755            posTilde += 3 ;
 756        }
 757        else
 758          posTilde += 3 ;
 759      }
 760      else
 761        posTilde += 1 ;
 762      
 763      // find the slash that marks the name ending position
 764      int posSlash = strUserName.indexOf( "/", posTilde ) ;
 765  
 766      // extract the user name or set to "undefined" if not found
 767      if ( posTilde != -1 && posSlash != -1 )
 768        strUserName = strUserName.substring( posTilde, posSlash ) ;
 769      else
 770        strUserName = "undefined" ;
 771  
 772      // call the five-parameter version of this method
 773      return storeXMLDocument( app, doc, strFileName, strFilePath, strUserName ) ;
 774    }
 775    
 776    
 777    /** This three-parameter <code>public static</code> method calls the 
 778     *  four-parameter version with the file path set to <code>null</code>.
 779     *  @param app          the calling applet
 780     *  @param doc          XML document to save
 781     *  @param strFileName  name under which to store the document
 782     *  @return a <code>String</code> indicating the full path to the XML document
 783     *      stored
 784     *  @throws UmlGuiException
 785     */
 786    public static String storeXMLDocument( Applet app, Document doc, 
 787      String strFileName ) 
 788      throws UmlGuiException
 789    {
 790      // call the four-parameter version of this method with the file path set to null
 791      return storeXMLDocument( app, doc, strFileName, null ) ;
 792    }
 793    
 794    
 795  }
 796  
 797  
 798  ============================================================
 799  edu\uml\gui\UmlGuiException.java
 800  ============================================================
 801  
 802  
 803  package edu.uml.gui ;
 804  
 805  /*
 806   * UmlGuiStoreException.java
 807   *
 808   * Created on September 27, 2002, 1:14 PM
 809   */
 810  
 811  import java.io.* ;
 812  
 813  /** This is the exception class that is thrown for all exceptions that occur in 
 814   *  any UmlGui method.
 815   *
 816   *  @author  Jesse M. Heines, <a href="mailto:heines@cs.uml.edu">heines@cs.uml.edu</a>
 817   *  @version 1.0, updated by JMH on October 05, 2002 at 11:15 AM
 818   */
 819  public class UmlGuiException extends IOException
 820  {
 821    /** Create a new instance with explanatory text. 
 822     *  @param str String explaining exception
 823     */
 824    public UmlGuiException( String str ) {
 825      super( str ) ;
 826    }
 827    
 828    /** Create a new instance with default text. */
 829    public UmlGuiException() {
 830      this( "UmlGuiStoreException: No additional data provided." ) ;
 831    }
 832    
 833  }
 834  
 835  
 836  ============================================================
 837  umlguiStoreXML9.jsp
 838  ============================================================
 839  
 840  
 841  <%--
 842   *  File: umlStoreXML8.jsp
 843   *  Reference:  Hall & Brown, pp. 1075
 844   *  
 845   *  @author  Jesse M. heines, heines@cs.uml.edu
 846   *  @version 1.9, updated by JMH on October 04, 2002 at 07:57 PM
 847  --%>
 848  
 849  <%@page import="java.io.*"     %>   <%-- for ObjectInputStream        --%>
 850  <%@page import="java.util.*"   %>   <%-- for StringTokenizer          --%>
 851  
 852  <%@page import="java.awt.*"    %>   <%-- for base of Swing components --%>
 853  <%@page import="javax.swing.*" %>   <%-- for JOptionPane              --%>
 854  
 855  
 856  <%!
 857    // Note:  Do not initialize member variables here.  Doing so causes them not
 858    // to be reinitialized when the JSP is run repeatedly.  This is, they function
 859    // lick static variables.
 860  
 861    /** the XML document as a string */
 862    private String strDocument ;
 863    
 864    /** name of user to store data for */
 865    private String strUserName ;
 866    
 867    /** name of the file to write (no path allowed) */
 868    private String strFileName ;
 869    
 870    /** path to write file to */
 871    private String strFilePath ;
 872  
 873    /** response to return to caller */
 874    private String strResponse ;
 875    
 876    /** base for student uploads */
 877    private String strBase ;
 878    
 879    /** base that student uses to access his/her uploaded files */
 880    private String strBaseURL ;
 881  %>
 882  <%
 883    // initialize response to send back to user (do this here so that it is 
 884    // reinitialized in each run)
 885    strResponse = "" ;
 886  
 887    // Step 0 - read incoming data
 888    ObjectInputStream oisIn = null ;
 889    try {
 890      oisIn = new ObjectInputStream( request.getInputStream() ) ;
 891    } catch ( IOException ioe ) {
 892        strResponse = "IOException at Step 0 in umlguiStoreXML6 JSP " +
 893            "method umlguiStoreXML:\n" + ioe.toString() ;
 894    }
 895  
 896    try {
 897      // Hall & Brown, p. 1074, Step 6
 898      strUserName = (String) oisIn.readObject() ;
 899      strFileName = (String) oisIn.readObject() ;
 900      strFilePath = (String) oisIn.readObject() ;
 901      strDocument = (String) oisIn.readObject() ;
 902      // p. 1074 Step 7
 903      oisIn.close() ;
 904    } catch ( ClassNotFoundException cnfe ) {
 905      strResponse = "ClassNotFoundException at Step 6 in umlguiStoreXML:\n" + 
 906          cnfe.toString() ;
 907    } catch ( IOException ioe ) {
 908      strResponse = "IOException at Step 6 in umlguiStoreXML:\n" + 
 909          ioe.toString() ;
 910    }
 911  
 912    // initialize location of this student's uploads
 913    if ( System.getProperty( "os.name" ).equals( "Windows 2000" ) )
 914    {
 915      strBase = "C:\\StudentUploads\\" + strUserName + "\\"  ;
 916      strBaseURL = "http://" + request.getServerName() + "/students/" + 
 917            strUserName + "/" ;
 918    }
 919    else if ( System.getProperty( "os.name" ).equals( "Linux" ) )
 920    {
 921      strBase = "/opt/JRun/servers/default/students/" + strUserName + "/" ;
 922      strBaseURL = "http://" + request.getServerName() + "/students/" + 
 923            strUserName + "/" ;
 924    }
 925    
 926    // declare variables for file writing
 927    String strUserPath = "" ;   // path to user file on DOS system
 928    File filePath = null ;      // File object representing directory path
 929    File fileXML = null ;       // File object representing XML file
 930    FileOutputStream fosStream = null ;   // for writing XML file
 931    PrintWriter pwWriter = null ;         // for writing XML file
 932    String strException = "" ;            // exception 
 933  
 934    // if no error at this point, try to write the user's file
 935    if ( strResponse.length() == 0 )
 936    {
 937      StringTokenizer st = new StringTokenizer( strFilePath, "/" ) ;
 938      while ( st.hasMoreTokens() )
 939      {
 940        if ( System.getProperty( "os.name" ).equals( "Windows 2000" ) )
 941          strUserPath += st.nextToken() + "\\" ;
 942        else if ( System.getProperty( "os.name" ).equals( "Linux" ) )
 943          strUserPath += st.nextToken() + "/" ;
 944      }
 945      
 946      // set the path specified by the user, creating it if it does not exist
 947      filePath = new File( strBase, strUserPath ) ;
 948      if ( ! filePath.exists() ) 
 949        if ( ! filePath.mkdirs() )
 950        {
 951          strResponse += "Unable to create directory " ; 
 952          strResponse += strBaseURL ;
 953          if ( strFilePath != null && strFilePath.length() > 0 )
 954              strResponse += strFilePath + "/" ;
 955        }                 
 956  
 957      // if no error at this point ...
 958      // set the file specified by the user, creating it if it does not exist
 959      if ( strResponse.length() == 0 )
 960      {
 961        fileXML = new File( filePath, strFileName ) ;
 962        try {
 963          fosStream = new FileOutputStream ( fileXML ) ;
 964        } catch ( FileNotFoundException fnfe ) {
 965          strException += fnfe.toString() ;
 966        } catch ( SecurityException se ) {
 967          strException += se.toString() ;
 968        }      
 969      }
 970      
 971      // if no error at this point ...
 972      // create a PrintWriter from the FileOutputStream and write the file
 973      if ( strException.length() == 0 )
 974      {
 975        pwWriter = new PrintWriter( fosStream ) ;
 976        pwWriter.print( strDocument ) ;
 977        pwWriter.close() ;
 978      }
 979  
 980      // if no error at this point ...
 981      // construct the URL to the created file to return to the user as the 
 982      //    response
 983      if ( strException.length() == 0 )
 984      {
 985        strResponse += strBaseURL ;
 986        if ( strFilePath != null && strFilePath.length() > 0 )
 987            strResponse += strFilePath + "/" ;
 988        strResponse += strFileName ;
 989      }
 990      // otherwise, return the exception
 991      else
 992      {
 993        strResponse = "Exception: " + strException ;
 994      }
 995    }
 996    
 997    // send the response to the user
 998    out.println( strResponse ) ;
 999  %>
1000  
1001  
1002  ============================================================