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="http://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 }