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