1 21 22 package org.apache.derby.impl.services.reflect; 23 24 import org.apache.derby.iapi.services.context.ContextService; 25 import org.apache.derby.iapi.services.monitor.Monitor; 26 import org.apache.derby.iapi.services.monitor.Monitor; 27 import org.apache.derby.iapi.services.stream.HeaderPrintWriter; 28 import org.apache.derby.iapi.util.IdUtil; 29 import org.apache.derby.iapi.error.StandardException; 30 import org.apache.derby.iapi.services.locks.ShExLockable; 31 import org.apache.derby.iapi.services.locks.ShExQual; 32 import org.apache.derby.iapi.services.locks.LockFactory; 33 import org.apache.derby.iapi.services.locks.Latch; 34 import org.apache.derby.iapi.services.locks.C_LockFactory; 35 import org.apache.derby.iapi.services.loader.ClassFactoryContext; 36 import org.apache.derby.iapi.services.loader.JarReader; 37 import org.apache.derby.iapi.services.property.PersistentSet; 38 39 import org.apache.derby.iapi.services.property.PropertyUtil; 40 import org.apache.derby.iapi.reference.Property; 41 42 import java.io.InputStream ; 43 44 import org.apache.derby.iapi.reference.MessageId; 45 import org.apache.derby.iapi.reference.Module; 46 import org.apache.derby.iapi.services.i18n.MessageService; 47 48 public class UpdateLoader { 49 50 private JarLoader[] jarList; 51 private HeaderPrintWriter vs; 52 private final ClassLoader myLoader; 53 private boolean initDone; 54 private String thisClasspath; 55 private final LockFactory lf; 56 private final ShExLockable classLoaderLock; 57 private int version; 58 private boolean normalizeToUpper; 59 private DatabaseClasses parent; 60 61 private boolean needReload; 62 private JarReader jarReader; 63 64 public UpdateLoader(String classpath, DatabaseClasses parent, boolean verbose, boolean normalizeToUpper) 65 throws StandardException { 66 67 this.normalizeToUpper = normalizeToUpper; 68 this.parent = parent; 69 lf = (LockFactory) Monitor.getServiceModule(parent, Module.LockFactory); 70 71 if (verbose) { 72 vs = Monitor.getStream(); 73 } 74 75 myLoader = getClass().getClassLoader(); 76 77 this.classLoaderLock = new ClassLoaderLock(this); 78 79 initializeFromClassPath(classpath); 80 } 81 82 private void initializeFromClassPath(String classpath) throws StandardException { 83 84 String [][] elements = IdUtil.parseDbClassPath(classpath, normalizeToUpper); 85 86 int jarCount = elements.length; 87 jarList = new JarLoader[jarCount]; 88 89 for (int i = 0; i < jarCount; i++) { 90 jarList[i] = new JarLoader(this, elements[i], vs); 91 } 92 93 if (vs != null) { 94 vs.println(MessageService.getTextMessage(MessageId.CM_CLASS_LOADER_START, classpath)); 95 } 96 97 thisClasspath = classpath; 98 initDone = false; 99 } 100 101 106 public Class loadClass(String className, boolean resolve) 107 throws ClassNotFoundException { 108 109 110 JarLoader jl = null; 111 112 boolean unlockLoader = false; 113 try { 114 unlockLoader = lockClassLoader(ShExQual.SH); 115 116 synchronized (this) { 117 118 if (needReload) { 119 reload(); 120 } 121 122 Class clazz = checkLoaded(className, resolve); 123 if (clazz != null) 124 return clazz; 125 126 String jvmClassName = className.replace('.', '/').concat(".class"); 127 128 if (!initDone) 129 initLoaders(); 130 131 for (int i = 0; i < jarList.length; i++) { 132 133 jl = jarList[i]; 134 135 Class c = jl.loadClassData(className, jvmClassName, resolve); 136 if (c != null) { 137 if (vs != null) 138 vs.println(MessageService.getTextMessage(MessageId.CM_CLASS_LOAD, className, jl.getJarName())); 139 140 return c; 141 } 142 } 143 } 144 145 return null; 146 147 148 } catch (StandardException se) { 149 throw new ClassNotFoundException (MessageService.getTextMessage(MessageId.CM_CLASS_LOAD_EXCEPTION, className, jl == null ? null : jl.getJarName(), se)); 150 } finally { 151 if (unlockLoader) { 152 lf.unlock(this, this, classLoaderLock, ShExQual.SH); 153 } 154 } 155 } 156 157 public InputStream getResourceAsStream(String name) { 158 159 InputStream is = (myLoader == null) ? 160 ClassLoader.getSystemResourceAsStream(name) : 161 myLoader.getResourceAsStream(name); 162 163 if (is != null) 164 return is; 165 166 if (name.endsWith(".class")) 168 return null; 169 170 boolean unlockLoader = false; 171 try { 172 unlockLoader = lockClassLoader(ShExQual.SH); 173 174 synchronized (this) { 175 176 if (needReload) { 177 reload(); 178 } 179 180 if (!initDone) 181 initLoaders(); 182 183 for (int i = 0; i < jarList.length; i++) { 184 185 JarLoader jl = jarList[i]; 186 187 is = jl.getStream(name); 188 if (is != null) { 189 return is; 190 } 191 } 192 } 193 return null; 194 195 } catch (StandardException se) { 196 return null; 197 } finally { 198 if (unlockLoader) { 199 lf.unlock(this, this, classLoaderLock, ShExQual.SH); 200 } 201 } 202 } 203 204 public synchronized void modifyClasspath(String classpath) 205 throws StandardException { 206 207 lockClassLoader(ShExQual.EX); 209 version++; 210 211 212 modifyJar(false); 213 initializeFromClassPath(classpath); 214 } 215 216 217 public synchronized void modifyJar(boolean reload) throws StandardException { 218 219 lockClassLoader(ShExQual.EX); 221 version++; 222 223 if (!initDone) 224 return; 225 226 if (reload) { 227 close(); 229 initializeFromClassPath(thisClasspath); 230 return; 231 } 232 233 synchronized (this) { 236 237 for (int i = 0; i < jarList.length; i++) { 238 239 JarLoader jl = jarList[i]; 240 241 JarFile newJarFile = jl.setInvalid(reload); 242 } 243 } 244 } 245 246 private boolean lockClassLoader(ShExQual qualifier) 247 throws StandardException { 248 249 if (lf == null) 250 return false; 251 252 ClassFactoryContext cfc = (ClassFactoryContext) ContextService.getContextOrNull(ClassFactoryContext.CONTEXT_ID); 253 254 Object lockSpace = null; 259 260 if (cfc != null) { 261 lockSpace = cfc.getLockSpace(); 262 } 263 if (lockSpace == null) 264 lockSpace = this; 265 266 lf.lockObject(lockSpace, lockSpace, classLoaderLock, qualifier, C_LockFactory.TIMED_WAIT); 267 268 return (lockSpace == this); 269 } 270 271 Class checkLoaded(String className, boolean resolve) { 272 273 for (int i = 0; i < jarList.length; i++) { 274 Class c = jarList[i].checkLoaded(className, resolve); 275 if (c != null) 276 return c; 277 } 278 return null; 279 } 280 281 public void close() { 282 283 for (int i = 0; i < jarList.length; i++) { 284 jarList[i].setInvalid(false); 285 } 286 287 } 288 289 private void initLoaders() { 290 291 if (initDone) 292 return; 293 294 for (int i = 0; i < jarList.length; i++) { 295 jarList[i].initialize(); 296 } 297 initDone = true; 298 } 299 300 public int getClassLoaderVersion() { 301 return version; 302 } 303 304 synchronized void needReload() { 305 version++; 306 needReload = true; 307 } 308 309 private void reload() throws StandardException { 310 thisClasspath = getClasspath(); 311 close(); 313 initializeFromClassPath(thisClasspath); 314 needReload = false; 315 } 316 317 318 private String getClasspath() 319 throws StandardException { 320 321 ClassFactoryContext cfc = (ClassFactoryContext) ContextService.getContextOrNull(ClassFactoryContext.CONTEXT_ID); 322 323 PersistentSet ps = cfc.getPersistentSet(); 324 325 String classpath = PropertyUtil.getServiceProperty(ps, Property.DATABASE_CLASSPATH); 326 327 if (classpath==null) 331 classpath=""; 332 333 334 return classpath; 335 } 336 337 JarReader getJarReader() { 338 if (jarReader == null) { 339 340 ClassFactoryContext cfc = (ClassFactoryContext) ContextService.getContextOrNull(ClassFactoryContext.CONTEXT_ID); 341 342 jarReader = cfc.getJarReader(); 343 } 344 return jarReader; 345 } 346 } 347 348 349 class ClassLoaderLock extends ShExLockable { 350 351 private UpdateLoader myLoader; 352 353 ClassLoaderLock(UpdateLoader myLoader) { 354 this.myLoader = myLoader; 355 } 356 357 public void unlockEvent(Latch lockInfo) 358 { 359 super.unlockEvent(lockInfo); 360 361 if (lockInfo.getQualifier().equals(ShExQual.EX)) { 362 myLoader.needReload(); 364 } 365 } 366 } 367 | Popular Tags |