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 }