Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/vrspace/client/VrmlUploader.java


1   package org.vrspace.client;
2   
3   import org.vrspace.util.*;
4   
5   import java.io.*;
6   import java.net.*;
7   import java.util.*;
8   
9   /** 
10   * Recursively uploads files to the server.<p>
11   *
12   * The uploader recursively searches the files that have .wrl extensions, looking 
13   * for url lists in url tags, and in EXTERNPROTOs.  Each list found is searched for
14   * for files existing on the local file system.  If a discovered file has a .wrl extension, 
15   * then it will be searched as well.  This recursion continues up to the level maxRecursion 
16   * ( defaults to zero ).<p>
17   *  
18   * After a VrmlUploader is instantiated, various options
19   * can be set for the transfer (see below).  The upload method is used to initiate the
20   * transfer.  Files sent to this method with a .wrl extension will be uploaded as
21   * VrmlFiles, unless uploadAllAsFile is false.  In that case, all .wrl files are uploaded
22   * as Files.  If includeNonWrl is false, then all non-vrml files encountered while 
23   * searching (see below) are not uploaded.<p>
24   *
25   * Example 1: upload( "sample.wrl" ) with maxRecursion level 0, and 
26   * includeNonWrl set to false.  In this case, only sample.wrl is uploaded.<p>
27   *
28   * Example 2: now includeNonWrl is set to true.  This causes sample.wrl to be searched for 
29   * all url list.  Every non .wrl file found will be uploaded.<p>
30   *
31   * Example 3: includeNonWrl false, maxRecusion 1.  Sample.wrl and every .wrl file discovered within
32   * it is uploaded.<p>
33   * 
34   * Various options are available for the upload:<p>
35   *
36   * inputStream - an InputStream for providing upload parameters, used in conjunction
37   * with useInputStream.  Defaults to System.in.<p>
38   * outputStream - a PrintStream, defaulting to System.out, that writes the responses to the
39   * upload commands sent to the server.<p>
40   * silent - turns outputStream off.<p>
41   * uploadAllAsFile - files normally uploaded as VrmlFile are uploaded as File.<p>
42   * logger - turns the logger on and off<p>
43   *
44   * Warning: All files uploaded with .wrl extensions are expected to be uncompresssed.<p>
45   *
46   */
47  public class VrmlUploader implements Observer {
48    protected Connection connection = null;
49    protected boolean stopLoggerOnCompletion = false;
50    protected PrintStream outputStream = new PrintStream ( System.out, true );
51    protected InputStream inputStream = System.in;
52    
53    protected String       host;
54    protected int          port;
55    protected String       login;
56    protected String       password;
57    protected int          maxRecursion       = 0;
58    protected boolean      includeNonWrl     = false;
59    protected boolean      excludeExternProto = false;
60    protected boolean      silent             = false;
61    protected int          numberLeftToUpload = Integer.MAX_VALUE;
62    protected boolean      uploadAllAsFile    = false;
63    protected boolean      useInputStream     = false;
64    
65    // Files to be uploaded as VrmlFile
66    protected Collection uploadAsVrmlFile;
67    
68    // Files to upload that are cached as parsing takes place.
69    protected HashMap cachedFiles;
70    
71    // Files to upload that are not cached.
72    protected HashMap files;
73    
74    public VrmlUploader() {
75      uploadAsVrmlFile   = new ArrayList();
76      cachedFiles        = new HashMap();
77      files              = new HashMap();
78      
79      // Loggers may have been stopped on previous completion of 
80      // an uploader.
81      Logger.startStaticLogger();
82    } // Console
83    
84    /**
85     * 
86     */
87    public VrmlUploader( String host, int port, String login, String password ) {
88      this();
89      
90      this.host = host;
91      this.port = port;
92      this.login = login;
93      this.password = password;
94    }
95    
96    /**
97     * 
98     */
99    public VrmlUploader( Connection connection, String login, String password ) {
100     this( connection.getHostName(), connection.getHostPort(), login, password );
101     
102     this.connection = connection;
103     connection.addObserver( this );
104   }
105  
106   public void setMaxRecursion( int maxRecursion ) {
107     this.maxRecursion = maxRecursion;
108   }
109   
110   public void setIncludeNonWrl( boolean includeNonWrl ) {
111     this.includeNonWrl = includeNonWrl;
112   }
113   
114   public void setExcludeExternProto( boolean excludeExternProto ) {
115     this.excludeExternProto = excludeExternProto;
116   }
117   
118   public void setSilent( boolean silent ) {
119     this.silent = silent;
120   }
121   
122   public void setStopLoggerOnCompletion( boolean stopLoggerOnCompletion ) {
123     this.stopLoggerOnCompletion = stopLoggerOnCompletion;
124   }
125   
126   public void setUploadAllAsFile( boolean uploadAllAsFile ) {
127     this.uploadAllAsFile = uploadAllAsFile;
128   }
129   
130   public void setLogging( boolean logging ) {
131     Logger.logInfo(     logging );
132     Logger.logWarning(  logging );
133     Logger.logHeader(   logging );
134     Logger.logDebug(    logging );
135     Logger.logError(    logging );
136     
137     Logger.stopOnError( false   );
138   } // setLogging
139   
140   public void setUseInputStream( boolean useInputStream ) {
141     this.useInputStream = useInputStream;
142   } // setUseInputStream
143   
144   public void setInputStream( InputStream inputStream ) {
145     this.inputStream = inputStream;
146   } // setInputStream
147   
148   public OutputStream getOutputStream() {
149     return outputStream;
150   } // getOutputStream
151  
152   public void setOutputStream( OutputStream outputStream ) {
153     outputStream = new PrintStream( outputStream, true );
154   } // setOutputStream
155   
156   /**
157    * Uploads the file specified.  The file is parsed
158    * for the urls it contains, and then each of these files are recursively
159    * searched.  Once parsing is completed, the server is sent requests for file
160    * upload.  The update method handles the actual uploading.
161    * Note that File.getAbsolutePath() is called on the file to determine the path
162    * to upload.
163    */
164   public void upload( String path ) throws ConnectionException {
165     ArrayList toUpload = new ArrayList();
166     toUpload.add( path );
167     upload( toUpload );
168   } // upload
169   
170   /**
171    * Uploads the list of files specified.  Each individual file is parsed
172    * for the urls they contain, and then each of these files are recursively
173    * searched.  Once parsing is completed, the server is sent requests for file
174    * upload.  The update method handles the actual uploading.
175    * Note that File.getAbsolutePath() is called on each file to determine the path
176    * to upload.
177    */
178   public void upload( List paths ) throws ConnectionException {
179     Logger.logDebug( "upload() called" );
180     
181     // Login
182     try {
183       if ( useInputStream ) {
184         consoleLogin();
185       } else {
186         if ( connection != null ) {
187           connection.addObserver( this );
188         } else {
189           connection = new Connection();
190           connection.addObserver( this );
191           connection.setMaxTries( 1 );
192           connection.login( host, port, login, password );
193         }
194       }
195     } catch ( ConnectionException e ) {
196       println( e.getMessage() );
197       shutdown();
198       throw e;
199     }
200     
201     URLParser urlParser = new URLParser( cachedFiles, files, maxRecursion );
202     Iterator i = paths.iterator();
203     while ( i.hasNext() ) {
204       String absolutePath = new File( (String) i.next() ).getAbsolutePath();
205       
206       if ( hasVrmlExtension( absolutePath ) && ! uploadAllAsFile )
207         uploadAsVrmlFile.add( Util.checkPath( login + "/" + absolutePath ) );
208       
209       urlParser.parseFile( absolutePath );
210     }
211     
212     // Check the paths and add login name as a prefix
213     HashMap oldCachedFiles = cachedFiles;
214     HashMap oldFiles = files;
215     cachedFiles = new HashMap();
216     files = new HashMap();
217     
218     i = oldCachedFiles.keySet().iterator();
219     while ( i.hasNext() ) {
220       String key = (String) i.next();
221       cachedFiles.put( Util.checkPath( login + "/" + key ),
222                        oldCachedFiles.get( key ) );
223     }
224     
225     i = oldFiles.keySet().iterator();
226     while ( i.hasNext() ) {
227       String key = (String) i.next();
228       files.put( Util.checkPath( login + "/" + key ),
229                  oldFiles.get( key ) );
230     }
231     
232     // Request that files in cachedFiles and files be uploaded to the server.
233     requestUploads();
234   } // upload
235   
236   /**
237    * true if the file has the extension .wrl (not e.g. .wrl.gz)
238    */
239   public static boolean hasVrmlExtension( String path ) {
240     String fileName = new File( path ).getName();
241     int pos = fileName.lastIndexOf(".");
242  
243     if ( ( pos >= 0 ) && 
244          ( fileName.substring( pos + 1, fileName.length() ).equals( "wrl" ) ) )
245       return true;
246     else
247       return false;
248   }
249   
250   /**
251    * Retrieves all upload information from input via a Console
252    * (except for the file name).  A console is created, but its thread is 
253    * not started.  The console retrieves host, port, username, password 
254    * if they haven't already been set in the System properties.
255    */
256   protected void consoleLogin() throws ConnectionException {
257     Console con = new Console();
258     
259     connection = con.connection;
260     connection.setMaxTries( 1 );
261     con.input = new BufferedReader( new InputStreamReader( inputStream ) );
262     try {
263       con.attemptLogin();
264     } catch ( IOException e ) {
265       throw new ConnectionException( e.getMessage() );
266     }
267       
268     host       = con.host;
269     login      = con.login;
270     password   = con.password;
271        
272     connection.addObserver( this );
273     connection.deleteObserver( con );
274   } // consoleLogin
275   
276   /**
277    * Request that the cachedFiles and files be uploaded to the server.
278    * Exits if these lists are both empty.
279    */ 
280   protected void requestUploads() { 
281     Logger.logDebug( "requestUploads()" );
282     
283     // ensure that there exist files to upload, 
284     // i.e. it is possible, for example, that all files were suppressed.
285     if ( cachedFiles.size() + files.size() == 0 ) {
286       shutdown();
287       return;
288     }
289     
290     String path;
291     Iterator i = cachedFiles.keySet().iterator();
292     while ( i.hasNext() ) {
293       path = (String) i.next();
294       
295       try {
296         if ( ! requestUpload( path ) )
297           i.remove();
298       } catch ( IOException e ) {
299         Logger.logWarning( "An error occurred while requesting upload " + path );
300         i.remove();
301       }
302     }
303     i = files.keySet().iterator();
304     while ( i.hasNext() ) {
305       path = (String) i.next();
306       
307       try {
308         if ( ! requestUpload( path  ) )
309           i.remove();
310       } catch ( IOException e ) {
311         Logger.logWarning( "An error occurred while requestion upload " + path );
312         i.remove();
313       }
314     }
315     
316      // Store the number of files to be uploaded
317     numberLeftToUpload = files.size() + cachedFiles.size();
318   } // requestUploads
319   
320   /**
321    * Request for the given file to be uploaded.  If the file has a wrl 
322    * extension, request as a VrmlFile, otherwise request File.
323    * VrmlFile upload is overidden by uploadAllAsFile.
324    */ 
325   protected boolean requestUpload( String checkedPath ) throws IOException {
326     Logger.logDebug( "requestUpload( " + checkedPath + " )" );
327     
328     boolean uploadRequested = true;
329     
330     // Check to see if the file is in the uploadAsVrmlFile list
331     boolean foundPath = false;
332     Iterator i = uploadAsVrmlFile.iterator();
333     while ( i.hasNext() ) {
334       if ( ( (String) i.next() ).equals( checkedPath ) )
335         foundPath = true;
336     }
337     
338     if ( foundPath ) {
339       connection.send( "upload VrmlFile " + checkedPath );
340     } else if ( VrmlUploader.hasVrmlExtension( checkedPath) ) {
341       connection.send( "upload File " + checkedPath );
342     } else if ( includeNonWrl ) {
343       connection.send( "upload File " + checkedPath );
344     } else {
345       uploadRequested = false;
346     }
347     
348     return uploadRequested;
349   } // requestUpload
350   
351   /**
352    * Implements the observer interface.  The VrmlUploader has been 
353    * added as an observer of its Connection.  The purpose of this 
354    * observing is to ignore all messages sent except upload commands
355    * and responses.  Those messages implement the actual uploading.
356    * The responses are printed to outputStream.
357    */
358   public void update( Observable conn, Object cmd ) {
359     //Logger.logDebug( "Message: "+cmd );
360     
361     if ( cmd instanceof String ) {
362       Message msg = new Message( (String) cmd );
363       String className = msg.getClassName();
364       
365       // Upload message
366       if ( className.equals( "upload" ) ) { 
367            
368         // Received the upload command from the server.
369         // Message format:
370         //     upload <port> <blocksize> <filename>
371         if ( ! msg.isResponse()) {
372           // Retrieve the file name and port to upload to
373           int port = new Long( msg.getId() ).intValue();
374           String destFile = msg.getEventValue();
375           
376           // Initiate file transfer.
377           Logger.logInfo( "Uploading "+destFile+" to "+host+":"+port+
378                           " - "+( cachedFiles.size() + files.size()-1 )+
379                           " left");
380           try {
381             BinaryConnection dest = new BinaryConnection( host, port, login, password );
382             
383             // attempt to retrieve the file from the cached files listing.
384             String file = (String) cachedFiles.get( destFile );
385        
386             // The file is cached.
387             if ( file != null ) {
388               dest.write( file.getBytes( "UTF8" ) );
389               cachedFiles.remove( destFile );
390               System.gc();
391               Logger.logInfo( "Wrote "+destFile+" "+file.length() );
392              
393             // The file is not cached.
394             } else {
395               String sourceFile = (String) files.get( destFile );
396                 
397               if ( sourceFile == null ) {
398                 Logger.logError( "Unable to find requested file: "+destFile );
399               } else {
400                 copyURL( sourceFile, destFile, dest.getOutputStream() );
401                 Logger.logInfo( "Wrote "+destFile );
402                 files.remove( destFile );
403               }
404             }
405             
406             // Close the binary connection.
407             try {
408               dest.close();
409             } catch ( Exception e ) {}
410   
411           } catch ( IOException ioe ) {
412             Logger.logError( ioe );
413           } catch ( ConnectionException e ) {
414             Logger.logError( e );
415           } catch ( Throwable t ) {
416             Logger.logError( t );
417           }
418         }
419         
420       } else if ( ( className.equals( "File" ) || 
421                     className.equals( "VrmlFile" ) ) 
422                   && msg.getEventName().equals( "upload" ) ) {
423         if ( msg.isResponse() ) {
424           // Display response to user
425           // Note: cannot use msg.toString() because it is only 
426           // designed for non-command responses.
427           println( (String) cmd );
428           
429           numberLeftToUpload--;
430           if ( numberLeftToUpload == 0 ) {
431             Logger.logDebug("All uploaded");
432             
433             //setChanged();
434             //notifyObservers();
435             
436             shutdown();
437           }
438         }
439       }  
440     }
441   } // update
442   
443   /**
444    * Copy file/url <i>path</i> to <i>destpath</i>
445   */
446   protected void copyURL( String path, String destPath, OutputStream out ) {
447     Logger.logDebug( "copyURL("+path+","+destPath+","+out+")" );
448     try {
449       File file = new File( path );
450       InputStream fIn = null;
451       fIn = new FileInputStream( file );
452       //fIn = url.openStream();
453       // copy file to new location
454       OutputStream fOut=null;
455       if ( out == null ) {
456         fOut = Util.createFileOutputStream( destPath );
457       } else {
458         fOut = out;
459       }
460       byte[] buffer = new byte [4096];
461       int len=0;
462       int pos=0;
463       while ( (pos=fIn.read(buffer)) != -1 ) {
464         fOut.write(buffer, 0, pos);
465         len+=pos;
466       }
467       fIn.close();
468       fOut.close();
469       Logger.logDebug( "Wrote "+path+" /"+len );
470     } catch ( IOException e ) {
471       Logger.logError( e );
472     }
473   }
474   
475   /**
476    * Shutdown the connection, and turn the Logger thread off if 
477    * shutdownOnCompletion is true.
478    */
479   public void shutdown() {
480     Logger.logDebug( "shutdown()" );
481     try {
482       connection.close();
483     } catch ( Exception e ) {
484     }
485     if ( stopLoggerOnCompletion ) {
486       Logger.stopStaticLogger();
487     }
488   } // shutdown
489   
490   /**
491    * Printlns the string to outputStream if silent is false.
492    */
493   public void println( String string ) {
494     if ( ! silent )
495       outputStream.println( string );
496   } // println
497   
498   /**
499    * Recursively parses given files, searching for url lists, in particular,
500    * other files on the local files system.
501    */
502   public class URLParser extends VrmlParser {
503     // Files to upload that are cached as parsing takes place.
504     protected HashMap cachedFiles;
505   
506     // Files to upload that are not cached.
507     protected HashMap files;
508     
509     protected int maxRecursion;
510     
511     public URLParser( int maxRecursion ) {
512       this.maxRecursion = maxRecursion;
513       cachedFiles = new HashMap();
514       files = new HashMap();
515     }
516     
517     /**
518      * Constructor designed for the recursive creation of this parser.  
519      */ 
520     protected URLParser( HashMap cachedFiles, HashMap files, int maxRecursion ) { 
521       this.cachedFiles      = cachedFiles;
522       this.files            = files;
523       this.maxRecursion     = maxRecursion;
524     }
525   
526     public HashMap getCachedFiles() {
527       return cachedFiles;
528     }
529     
530     public HashMap getFiles() {
531       return files;
532     }
533     
534     /**
535      * Parses the given file for all instances of urls.  When these are found,
536      * if they reference .wrl files, then those files are recursively parsed.  This
537      * recursion occurs up to the level set by maxRecursion.  If the file is 
538      * non-vrml, it is simply added to the list of uncached files.<p>
539      *
540      * VRML97 spec url is not java url - TODO
541      */
542     public void parseFile( String path ) {
543       parseFile( path, 0 );
544     } // parseFile
545   
546     /**
547      * Resolves path against relRefPath and calls parseFile on the result.
548      */
549     protected void parseFile( String path, String relRefPath, int recursionLevel ) {
550       String absolutePath = resolvePath( path, relRefPath );
551       parseFile( absolutePath, recursionLevel );
552     } // parseFile
553   
554     /**
555      * Resolves the given path against relRefPath and returns the result.
556      */
557     protected String resolvePath( String path, String relRefPath ) {
558       // Determine the location of the file.
559       // If the path isn't absolute, then use the path of relRefFile for 
560       // relative addressing.
561       if ( ! new File( path ).isAbsolute() ) {
562         Logger.logDebug( "Relative path detected: " + path );
563         return new File( relRefPath ).getParent() + File.separator + path;
564       } else {
565         return path;
566       }
567     } // resolvePath
568   
569     /**
570      * The actual file parsing workhorse.  ParseFile is called recursively
571      * on each file found in the url tags. Then the file being parsed is cached.
572      * If the file specified does not have a vrml extension, it simply stores 
573      * the file reference in files.  If recursionLevel > maxRecursion the method
574      * returns.  
575      */
576     protected void parseFile( String path, int recursionLevel ) {
577       boolean processingURLList     = false;
578       boolean processingExternProto = false;
579       boolean processingMFString    = false;
580     
581       // Non Vrml File
582       if ( ! VrmlUploader.hasVrmlExtension( path ) ) {
583         if ( includeNonWrl ) 
584           storeFileReference( path );
585         return;
586       }
587     
588       if ( recursionLevel > maxRecursion ) {
589         return;
590       }
591     
592       try {
593         // Obtain a buffered reader for the file to upload.
594         File destFile = new File( path );
595         BufferedReader reader = new BufferedReader( new FileReader( path ));
596       
597         // Parse the contents of the file, looking for instances of the url tag.
598         String line;
599         while ( (line = reader.readLine()) != null ) {
600           //Logger.logDebug( line );
601           output.append( line );
602           output.append( "\n" );
603         
604           // Parse the line
605           StringTokenizer st = new StringTokenizer( line, " {}[],", true );
606           while ( st.hasMoreTokens() ) {
607             String token = st.nextToken();
608             //Logger.logDebug( token );
609              
610             // Process the url SFString / MFString
611             if ( processingURLList ) { 
612               char firstChar = token.charAt(0);
613             
614               if ( firstChar == '[' ) {
615                 processingMFString = true;
616               } else if ( firstChar == ']' ) {
617                 processingMFString = false;
618                 processingURLList  = false;
619               } else if ( firstChar == '"' ) {
620                 //Logger.logDebug( token );
621                 parseURL( token, path, recursionLevel );
622               
623                 if ( ! processingMFString )
624                   processingURLList = false;
625               }  
626             }
627           
628             // ExternProto [] URLList.  Must loop until the final ]
629             // is found, then beging parsing SF/MFString.
630             if ( processingExternProto ) {
631               if ( token.charAt(0) == ']' ) {
632                 processingURLList = true;
633                 processingExternProto = false;
634               }
635             }
636           
637             // url URLList, ExternProto [...] URLList
638             // immediately process after url, wait after EXTERNPROTO
639             if ( token.equals( "url" ) ) {
640               processingURLList = true;
641             } else if ( token.equals( "EXTERNPROTO" ) &&
642                         ! excludeExternProto ) {
643               processingExternProto = true;
644             }
645           } // while
646         } // while
647       
648         // Cache the file
649         cacheFile( path );
650     
651       } catch ( Exception e ) {
652         Logger.logError( e );
653       }
654   
655     } // parseFile
656   
657     /**
658      * Determines if the given urlString is a .wrl file, and continues recursive
659      * search if it is.
660      */
661     protected void parseURL( String urlString, String path, int recursionLevel ) {
662       // Retrieve the url 
663       int quoteStart = urlString.indexOf( "\"" );
664       int quoteEnd   = urlString.lastIndexOf( "\"" );
665     
666     
667       // If vrmlfile is well-formed, attempt to determine if the 
668       // the specified url is a network object or a local file.
669       if ( quoteStart >= 0 && quoteEnd > 0 ) {
670         urlString = urlString.substring( quoteStart + 1, quoteEnd );
671       
672         // This could contain an anchor.  Remove that part.
673         int hashIndex = urlString.indexOf('#');
674         if ( hashIndex > 0 )
675           urlString = urlString.substring( 0, hashIndex );
676               
677         // If the construction of  a java.net.URL object passes 
678         // then the url is a network object.
679               
680         try {
681           URL url = new URL( urlString );
682         } catch ( MalformedURLException protoExc ) {
683                 
684           // otherwise it is a local file
685           try {
686             URL url = new URL( "file", "", urlString );
687                   
688             // Given that the url is a file, resolve against the 
689             // current path and parse its contents.
690             new URLParser( cachedFiles, files, maxRecursion ).parseFile( 
691               urlString, path, recursionLevel + 1
692             );
693           } catch ( MalformedURLException urlExc ) {
694             Logger.logError( urlExc.getMessage() );
695           }
696         }
697       } // if
698     } // parseURL
699   
700     /**
701      * Stores an entry in cachedFiles with key = path, and
702      * value = output.toString(), and resets the parser.  The path is
703      * expected to be absolute.
704      */
705     protected void cacheFile( String path ) {
706       cachedFiles.put( path, output.toString() );
707     
708       // Reset the VrmlParser member variables (in particular, output)
709       reset();
710     } // cacheFile
711   
712     /**
713      * Checks to see if the absolute path exists and if so,
714      * stores an entry in files with key = path, and 
715      * value = path.
716      */
717     protected void storeFileReference( String path ) {
718       if ( ! new File( path ).exists() ) {
719         Logger.logInfo( "File does not exist: " + path );
720       
721       // otherwise schedule the file for upload
722       } else {
723         files.put( path, path );
724       }    
725     } // storeFileReference
726     
727   } // URLParser
728   
729   /**
730    * Command Line Usage: java VrmlUploader [options] file
731    * <pre>
732    * options:
733    * -h=<i>host</i>
734    * -p=<i>port</i> 
735    * -l=<i>username</i>
736    * -pw=<i>password</i>
737    * -r=<i>max recursion level</i>   Default: 0
738    * -Files                          Upload all as File
739    * -includeNonWrl                  Upload non .wrl files (including .wrl.gz)
740    * -excludeExternProto             Do not upload EXTERNPROTO urls
741    * -silent                         Silence output
742    * -logger                         Debug
743    * </pre>
744    */
745   public static void main ( String[] args ) {
746     // command line options
747     boolean paramParseFile          = false;
748     boolean paramSilent             = false;
749     boolean paramLogger             = false;
750     int     paramMaxRecursion       = 0;
751     boolean paramIncludeNonWrl      = false;
752     boolean paramExcludeExternProto = false;
753     boolean paramUploadAllAsFile    = false;
754     
755     // the file to upload
756     ArrayList filesToUpload = new ArrayList();
757     
758     // record succesful command parsing
759     boolean parseError = false;
760     
761     if ( args.length == 0 ) {
762       parseError = true;
763     
764     // Parse the command line
765     } else {
766       try {
767         for (int i = 0; i < args.length; i++) {
768           if ( parseError ) 
769             break;
770           
771           // A file to upload
772           if ( args[ i ].charAt( 0 ) != '-' ) {
773             filesToUpload.add( args[ i ] );
774             
775           // An option
776           } else {
777             // Remove preceding -
778             StringTokenizer optionTokens = new StringTokenizer( args[ i ], "=" );
779             String option = optionTokens.nextToken();
780         
781             // Host
782             if        ( option.equals( "-h" ) ) {
783               System.setProperty( "vrspace.host", optionTokens.nextToken() );
784             // Port
785             } else if ( option.equals( "-p" ) ) {
786               System.setProperty( "vrspace.port", optionTokens.nextToken() );
787             // Username
788             } else if ( option.equals( "-l" ) ) {
789               System.setProperty( "vrspace.login", optionTokens.nextToken() );
790             // Password
791             } else if ( option.equals( "-pw" ) ) {
792               System.setProperty( "vrspace.password", optionTokens.nextToken() );
793             } else if ( option.equals( "-r" ) ) {
794               paramMaxRecursion = Integer.parseInt( (String) optionTokens.nextToken() );
795             } else if ( option.equals( "-Files" ) ) {
796               paramUploadAllAsFile = true;
797             } else if ( option.equals( "-includeNonWrl" ) ) {
798               paramIncludeNonWrl = true;
799             } else if ( option.equals( "-excludeExternProto" ) ) {
800               paramExcludeExternProto = true;
801             } else if ( option.equals( "-silent" ) ) {
802               paramSilent = true;
803             } else if ( option.equals( "-logger" ) ) {
804               paramLogger = true;
805             } else {
806               parseError = true;
807             }
808           }
809         }
810       } catch ( Exception e ) {
811         parseError = true;
812       }
813     }
814     
815     // Display usage if an error occurred while parsing
816     if ( parseError ) {
817       System.out.println( "Usage: java VrmlUploader [options] <file>" );
818       System.out.println( "Options:" );
819       System.out.println( "  -h=<host>" );
820       System.out.println( "  -p=<port>" );
821       System.out.println( "  -l=<username>" );
822       System.out.println( "  -pw=<password>" );
823       System.out.println( "  -r=<recursion-level>   recursively upload vrml files Default: 0" );
824       System.out.println( "  -includeNonWrl         include non .wrl files in upload" );
825       System.out.println( "  -excludeExternProto    do not upload EXTERNPROTO urls" );
826       System.out.println( "  -Files                 upload all as File " );
827       System.out.println( "  -silent                silence output" );
828       System.out.println( "  -logger                debug" );
829       System.out.println( "Warning: All files uploaded with .wrl extensions are expected to" );
830       System.out.println( "be uncompressed." );
831 
832       System.exit(-1);
833     } 
834     
835     // Ensure that all of the files specified actually exist
836     Iterator i = filesToUpload.iterator();
837     while ( i.hasNext() ) {
838       String path = (String) i.next();
839       if ( ! new File( path ).exists() ) { 
840         System.out.println( "File " + path + " does not exist." );
841         System.exit(-1);
842       }
843     } 
844     
845     VrmlUploader uploader = new VrmlUploader();
846     uploader.setStopLoggerOnCompletion( true );
847     
848     // Process command line options:
849     // Information Display 
850     uploader.setLogging( paramLogger );
851     uploader.setSilent( paramSilent );
852     
853     uploader.setMaxRecursion( paramMaxRecursion );
854     uploader.setIncludeNonWrl( paramIncludeNonWrl );
855     uploader.setExcludeExternProto( paramExcludeExternProto );
856     uploader.setUploadAllAsFile( paramUploadAllAsFile );
857     uploader.setUseInputStream( true );
858     
859     try {
860       uploader.upload( filesToUpload ); 
861     } catch ( ConnectionException e ) {
862     }
863   } // main
864   
865 } // VrmlUploader