001 package railo.commons.lang; 002 003 import java.io.ByteArrayOutputStream; 004 import java.io.IOException; 005 import java.io.InputStream; 006 import java.net.URL; 007 008 import railo.commons.io.IOUtil; 009 import railo.commons.io.SystemUtil; 010 import railo.commons.io.res.Resource; 011 import railo.runtime.type.Sizeable; 012 013 /** 014 * Directory ClassLoader 015 */ 016 public final class PCLBlock extends ClassLoader implements Sizeable { 017 018 private Resource directory; 019 private ClassLoader pcl; 020 private int size=0; 021 private int count; 022 023 024 /** 025 * Constructor of the class 026 * @param directory 027 * @param parent 028 * @throws IOException 029 */ 030 public PCLBlock(Resource directory, ClassLoader parent) { 031 super(parent); 032 this.pcl=parent; 033 this.directory=directory; 034 } 035 036 /** 037 * Loads the class with the specified name. This method searches for 038 * classes in the same manner as the {@link #loadClass(String, boolean)} 039 * method. It is called by the Java virtual machine to resolve class 040 * references. Calling this method is equivalent to calling 041 * <code>loadClass(name, false)</code>. 042 * 043 * @param name the name of the class 044 * @return the resulting <code>Class</code> object 045 * @exception ClassNotFoundException if the class was not found 046 */ 047 public Class<?> loadClass(String name) throws ClassNotFoundException { 048 return loadClass(name, false); 049 }//15075171 050 051 /** 052 * Loads the class with the specified name. The default implementation of 053 * this method searches for classes in the following order:<p> 054 * 055 * <ol> 056 * <li> Call {@link #findLoadedClass(String)} to check if the class has 057 * already been loaded. <p> 058 * <li> Call the <code>loadClass</code> method on the parent class 059 * loader. If the parent is <code>null</code> the class loader 060 * built-in to the virtual machine is used, instead. <p> 061 * <li> Call the {@link #findClass(String)} method to find the class. <p> 062 * </ol> 063 * 064 * If the class was found using the above steps, and the 065 * <code>resolve</code> flag is true, this method will then call the 066 * {@link #resolveClass(Class)} method on the resulting class object. 067 * <p> 068 * From the Java 2 SDK, v1.2, subclasses of ClassLoader are 069 * encouraged to override 070 * {@link #findClass(String)}, rather than this method.<p> 071 * 072 * @param name the name of the class 073 * @param resolve if <code>true</code> then resolve the class 074 * @return the resulting <code>Class</code> object 075 * @exception ClassNotFoundException if the class could not be found 076 */ 077 protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { 078 //if(!name.endsWith("$cf")) return super.loadClass(name, resolve); this break Webervices 079 // First, check if the class has already been loaded 080 Class<?> c = findLoadedClass(name); 081 //print.o("load:"+name+" -> "+c); 082 if (c == null) { 083 try { 084 c =pcl.loadClass(name);//if(name.indexOf("sub")!=-1)print.ds(name); 085 } 086 catch (Throwable t) { 087 c = findClass(name); 088 } 089 } 090 if (resolve) { 091 resolveClass(c); 092 } 093 return c; 094 } 095 096 097 098 099 public static long lastModified(Resource res, long defaultValue) { 100 InputStream in = null; 101 try{ 102 in=res.getInputStream(); 103 byte[] buffer = new byte[10]; 104 in.read(buffer); 105 if(!ClassUtil.hasCF33Prefix(buffer)) return defaultValue; 106 107 byte[] _buffer = new byte[]{ 108 buffer[2], 109 buffer[3], 110 buffer[4], 111 buffer[5], 112 buffer[6], 113 buffer[7], 114 buffer[8], 115 buffer[9], 116 }; 117 118 119 return NumberUtil.byteArrayToLong(_buffer); 120 } 121 catch(IOException ioe){ 122 return defaultValue; 123 } 124 finally { 125 IOUtil.closeEL(in); 126 } 127 128 } 129 130 /** 131 * @see java.lang.ClassLoader#findClass(java.lang.String) 132 */ 133 protected Class<?> findClass(String name) throws ClassNotFoundException {//if(name.indexOf("sub")!=-1)print.ds(name); 134 //if(!name.endsWith("$cf")) return super.findClass(name); this break Webervices 135 //File f = getFile(name.replace('.',File.separatorChar).concat(".class")); 136 //print.e("directory:"+directory+"->"+name); 137 Resource res=directory 138 .getRealResource( 139 name.replace('.','/') 140 .concat(".class")); 141 //File f = new File(directory,name.replace('.',File.separatorChar).concat(".class")); 142 //if(f==null) throw new ClassNotFoundException("class "+name+" not found"); 143 144 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 145 try { 146 IOUtil.copy(res,baos,false); 147 } 148 catch (IOException e) { 149 throw new ClassNotFoundException("class "+name+" is invalid or doesn't exists"); 150 } 151 152 byte[] barr=baos.toByteArray(); 153 size+=barr.length; 154 count++; 155 //print.o(name+":"+count+" -> "+(size/1024)); 156 IOUtil.closeEL(baos); 157 return loadClass(name, barr); 158 //return defineClass(name,barr,0,barr.length); 159 } 160 161 162 public Class<?> loadClass(String name, byte[] barr) throws ClassNotFoundException { 163 int start=0; 164 //if(ClassUtil.hasCF33Prefix(barr)) start=10; 165 size+=barr.length-start; 166 count++; 167 try { 168 return defineClass(name,barr,start,barr.length-start); 169 } 170 catch (Throwable t) { 171 SystemUtil.sleep(1); 172 try { 173 return defineClass(name,barr,start,barr.length-start); 174 } 175 catch (Throwable t2) { 176 SystemUtil.sleep(1); 177 return defineClass(name,barr,start,barr.length-start); 178 } 179 } 180 //return loadClass(name,false); 181 } 182 183 /** 184 * @see java.lang.ClassLoader#getResource(java.lang.String) 185 */ 186 public URL getResource(String name) { 187 /*URL url=super.getResource(name); 188 if(url!=null) return url; 189 190 Resource f =_getResource(name); 191 if(f!=null) { 192 try { 193 return f.toURL(); 194 } 195 catch (MalformedURLException e) {} 196 }*/ 197 return null; 198 } 199 200 /** 201 * @see java.lang.ClassLoader#getResourceAsStream(java.lang.String) 202 */ 203 public InputStream getResourceAsStream(String name) { 204 InputStream is = super.getResourceAsStream(name); 205 if(is!=null) return is; 206 207 Resource f = _getResource(name); 208 if(f!=null) { 209 try { 210 return IOUtil.toBufferedInputStream(f.getInputStream()); 211 } 212 catch (IOException e) {} 213 } 214 return null; 215 } 216 217 /** 218 * returns matching File Object or null if file not exust 219 * @param name 220 * @return matching file 221 */ 222 public Resource _getResource(String name) { 223 Resource f = directory.getRealResource(name); 224 if(f!=null && f.exists() && f.isFile()) return f; 225 return null; 226 } 227 228 /** 229 * @see railo.commons.lang.ClassLoaderControl#hasClass(java.lang.String) 230 */ 231 public boolean hasClass(String className) { 232 return hasResource(className.replace('.','/').concat(".class")); 233 } 234 235 public boolean isClassLoaded(String className) { 236 //print.o("isClassLoaded:"+className+"-"+(findLoadedClass(className)!=null)); 237 return findLoadedClass(className)!=null; 238 } 239 240 /** 241 * @see railo.commons.lang.ClassLoaderControl#hasResource(java.lang.String) 242 */ 243 public boolean hasResource(String name) { 244 return _getResource(name)!=null; 245 } 246 247 /** 248 * @return the directory 249 */ 250 public Resource getDirectory() { 251 return directory; 252 } 253 254 /** 255 * @see railo.runtime.type.Sizeable#sizeOf() 256 */ 257 public long sizeOf() { 258 return 0; 259 } 260 261 public int count() { 262 return count; 263 } 264 265 }