001         package com.croftsoft.core.lang.classloader;
002    
003         import java.io.*;
004         import java.lang.reflect.*;
005         import java.net.*;
006    
007         /*********************************************************************
008         * The Boot ClassLoader bootstraps a main class downloaded directly off
009         * of a web site.  The argument to this program is the URL of the
010         * main class bytecode file.  Any additional arguments are passed to
011         * the downloaded class.
012         *
013         * <P>
014         *
015         * The Boot class can be readily distributed to a wide audience since
016         * it is small and simple.  With a little customization, it can be
017         * hard-coded to download from a particular URL.  It can also be used
018         * as a "seed" class by having it invoke a persistent resource loader.
019         *
020         * <P>
021         *
022         * @version
023         *   1999-11-27
024         * @author
025         *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
026         *********************************************************************/
027    
028         public class  Boot extends ClassLoader
029         //////////////////////////////////////////////////////////////////////
030         //////////////////////////////////////////////////////////////////////
031         {
032    
033         public static void  main ( String [ ]  args )
034           throws Exception
035         //////////////////////////////////////////////////////////////////////
036         {
037           if ( args.length < 1 )
038           {
039             System.out.println (
040               "\nBoot (1999-11-27) David Wallace Croft (croft@orbs.com)" );
041             System.out.println (
042               "Updates available from \"http://www.orbs.com/\".\n" );
043             System.out.println (
044               "Bootstraps the main(args) method of a class available "
045               + "from a web site." );
046             System.out.println (
047               "Arguments:  URL [other...]" );
048             System.out.println ( "Example:  java -jar boot.jar "
049               + "http://www.orbs.com/lib/Main.class username password" );
050             return;
051           }
052    
053           byte [ ]  data = downloadBytes ( new URL ( args [ 0 ] ) );
054           if ( data == null )
055           {
056             System.out.println (
057               "Unable to download \"" + args [ 0 ] + "\"." );
058             return;
059           }
060    
061           String [ ]  shiftedArgs = new String [ args.length - 1 ];
062           for ( int  i = 0; i < shiftedArgs.length; i++ )
063           {
064             shiftedArgs [ i ] = args [ i + 1 ];
065           }
066    
067           new Boot ( ).bootstrap ( data, shiftedArgs );
068         }
069    
070         //////////////////////////////////////////////////////////////////////
071         //////////////////////////////////////////////////////////////////////
072    
073         /*********************************************************************
074         * Returns null upon failure.
075         *********************************************************************/
076         public static byte [ ]  downloadBytes ( URL  url )
077         //////////////////////////////////////////////////////////////////////
078         {
079           InputStream            inputStream = null;
080           BufferedInputStream    in          = null;
081           ByteArrayOutputStream  out         = null;
082    
083           try
084           {
085             inputStream = downloadStream ( url );
086             if ( inputStream == null ) return null;
087             in = new BufferedInputStream ( inputStream );
088             out = new ByteArrayOutputStream ( );
089             int  i;
090             while ( ( i = in.read ( ) ) > -1 ) out.write ( i );
091             out.close ( );
092             in.close ( );
093             return out.toByteArray ( );
094           }
095           catch ( Exception  ex )
096           {
097             try { in.close          ( ); } catch ( Exception  ex1 ) { }
098             try { inputStream.close ( ); } catch ( Exception  ex1 ) { }
099             try { out.close         ( ); } catch ( Exception  ex1 ) { }
100             return null;
101           }
102         }
103    
104         /*********************************************************************
105         * Returns null upon failure.
106         *********************************************************************/
107         public static InputStream  downloadStream ( URL  url )
108         //////////////////////////////////////////////////////////////////////
109         {
110           InputStream  inputStream = null;
111           try
112           {
113             URLConnection  urlConnection = url.openConnection ( );
114             if ( urlConnection instanceof HttpURLConnection )
115             {
116               HttpURLConnection  httpURLConnection
117                 = ( HttpURLConnection ) urlConnection;
118               httpURLConnection.setFollowRedirects ( true );
119               httpURLConnection.setRequestMethod ( "GET" );
120               int  responseCode = httpURLConnection.getResponseCode ( );
121               if ( responseCode != HttpURLConnection.HTTP_OK ) return null;
122             }
123             return urlConnection.getInputStream ( );
124           }
125           catch ( Exception  ex )
126           {
127             try { inputStream.close ( ); } catch ( Exception  ex1 ) { }
128             return null;
129           }
130         }
131    
132         /*********************************************************************
133         * Uses reflection to invoke the main(args) method of a class.
134         *********************************************************************/
135         public static void  invokeMain ( Class  c, String [ ]  args )
136           throws IllegalAccessException
137         //////////////////////////////////////////////////////////////////////
138         {
139           Method  method;
140           try
141           {
142             method = c.getMethod (
143               "main", new Class [ ] { String [ ].class } );
144           }
145           catch ( NoSuchMethodException  ex )
146           {
147             System.out.println ( "No \"main(args)\" method in class \""
148               + c.getName ( ) + "\"." );
149             return;
150           }
151           try
152           {
153             method.invoke ( null, new Object [ ] { args } );
154           }
155           catch ( InvocationTargetException  ex )
156           {
157             Throwable  t = ex.getTargetException ( );
158             System.err.println (
159               "\"main()\" method exited with exception \"" + t + "\"." );
160             t.printStackTrace ( );
161           }
162         }
163    
164         //////////////////////////////////////////////////////////////////////
165         //////////////////////////////////////////////////////////////////////
166    
167         /*********************************************************************
168         * Converts the data to a Class and then invokes its main(args) method.
169         *********************************************************************/
170         public void  bootstrap ( byte [ ]  data, String [ ]  args )
171           throws IllegalAccessException
172         //////////////////////////////////////////////////////////////////////
173         {
174           Class  c = defineClass ( data, 0, data.length );
175           invokeMain ( c, args );
176         }
177    
178         /*********************************************************************
179         * Returns the Class of the given name.
180         *********************************************************************/
181         public Class  loadClass ( String  name,  boolean resolve )
182         //////////////////////////////////////////////////////////////////////
183         {
184           Class  c = findLoadedClass ( name );
185           if ( c != null ) return c;
186    
187           try
188           {
189             return findSystemClass ( name );
190           }
191           catch ( ClassNotFoundException  ex )
192           {
193             return null;
194           }
195         }
196    
197         //////////////////////////////////////////////////////////////////////
198         //////////////////////////////////////////////////////////////////////
199         }