1 52 53 package com.go.teaservlet; 54 55 import java.util.*; 56 import java.lang.reflect.*; 57 import javax.servlet.ServletContext ; 58 import javax.servlet.ServletException ; 59 import com.go.trove.log.Log; 60 import com.go.trove.util.IdentityMap; 61 import com.go.trove.util.MapBackedSet; 62 import com.go.trove.util.ClassInjector; 63 import com.go.trove.util.DelegateClassLoader; 64 import com.go.trove.util.MergedClass; 65 import com.go.trove.util.PropertyMap; 66 import com.go.trove.util.plugin.Plugin; 67 68 74 class MergedApplication implements Application { 75 82 private static String cleanName(String name) { 83 int index = name.indexOf('-'); 84 if (index > 0) { 85 name = name.substring(0, index); 86 } 87 88 int length = name.length(); 89 StringBuffer buf = new StringBuffer (length + 1); 90 91 if (!Character.isJavaIdentifierStart(name.charAt(0))) { 92 buf.append('_'); 93 } 94 else if (Character.isJavaIdentifierPart(name.charAt(0))) { 95 buf.append(name.charAt(0)); 96 } 97 98 for (int i=1; i<length; i++) { 99 char c = name.charAt(i); 100 if (Character.isJavaIdentifierPart(c)) { 101 buf.append(c); 102 } 103 else { 104 buf.append('$'); 105 } 106 } 107 108 return buf.toString(); 109 } 110 111 private ApplicationConfig mBaseConfig; 112 private ServletContext mServletContext; 113 private Log mLog; 114 private PropertyMap mProperties; 115 116 private Application[] mApps; 118 119 private Application[] mAppsWithContexts; 121 122 private Map mAppNameMap; 124 125 private Constructor mContextConstructor; 126 127 public void init(ApplicationConfig config) throws ServletException { 128 mBaseConfig = config; 129 mServletContext = config.getServletContext(); 130 mLog = config.getLog(); 131 mProperties = config.getProperties().subMap("applications"); 132 133 mLog.debug("Loading Applications"); 135 Set appNames = mProperties.subMapKeySet(); 136 List apps = new ArrayList(appNames.size()); 137 List appsWithContexts = new ArrayList(appNames.size()); 138 Map appNameMap = new IdentityMap(appNames.size() * 2 + 1); 139 140 if (appNames.size() == 0) { 141 mLog.warn("No Applications specified"); 142 } 143 144 Set contextCLSet = new MapBackedSet(new IdentityMap()); 145 List contextCLList = new ArrayList(); 146 147 Iterator it = appNames.iterator(); 148 while (it.hasNext()) { 149 String name = (String )it.next(); 150 Application app = loadApplication(name, config.getPlugins()); 151 if (app != null) { 152 apps.add(app); 153 appNameMap.put(app, name); 154 155 Class contextType = app.getContextType(); 156 if (contextType != null) { 157 appsWithContexts.add(app); 158 159 ClassLoader contextCL = contextType.getClassLoader(); 161 if (contextCL != null) { 162 contextCLSet.add(contextCL); 163 contextCLList.add(contextCL); 164 } 165 } 166 } 167 } 168 169 mApps = (Application[])apps.toArray(new Application[apps.size()]); 170 mAppsWithContexts = (Application[])appsWithContexts.toArray 171 (new Application[appsWithContexts.size()]); 172 mAppNameMap = appNameMap; 173 174 ClassLoader [] contextClassLoaders = 175 new ClassLoader [contextCLSet.size()]; 176 int i = 0; 177 it = contextCLList.iterator(); 178 while (it.hasNext()) { 179 Object contextClassLoader = it.next(); 180 if (contextCLSet.contains(contextClassLoader)) { 181 contextCLSet.remove(contextClassLoader); 182 contextClassLoaders[i++] = (ClassLoader )contextClassLoader; 183 } 184 } 185 186 188 ClassLoader baseClassLoader = this.getClass().getClassLoader(); 189 if (contextClassLoaders.length > 0) { 190 baseClassLoader = new DelegateClassLoader 191 (baseClassLoader, contextClassLoaders); 192 } 193 194 ClassInjector contextInjector = new ClassInjector 195 (baseClassLoader, (java.io.File [])null, null); 196 197 Class [] contexts = new Class [1 + mAppsWithContexts.length]; 198 contexts[0] = HttpContext.class; 199 String [] prefixes = new String [contexts.length]; 200 201 for (i=0; i<mAppsWithContexts.length; i++) { 202 Application app = mAppsWithContexts[i]; 203 contexts[i + 1] = app.getContextType(); 204 prefixes[i + 1] = cleanName((String )mAppNameMap.get(app)) + '$'; 205 } 206 207 mContextConstructor = 208 MergedClass.getConstructor2(contextInjector, contexts, prefixes); 209 } 210 211 public void destroy() { 212 for (int i=0; i<mApps.length; i++) { 213 mApps[i].destroy(); 214 } 215 } 216 217 220 public Object createContext(ApplicationRequest request, 221 ApplicationResponse response) { 222 ApplicationResponseImpl responseImpl = 223 (ApplicationResponseImpl)response; 224 responseImpl.setAppAndRequest(this, request); 225 226 HttpContext httpContext = 227 new HttpContextImpl(mServletContext, mLog, request, response, 228 response.getResponseBuffer()); 229 responseImpl.setHttpContext(httpContext); 230 231 ContextFactory factory = 232 new ContextFactory(httpContext, request, response); 233 234 try { 235 httpContext = (HttpContext)mContextConstructor.newInstance 236 (new Object []{factory}); 237 responseImpl.setHttpContext(httpContext); 238 return httpContext; 239 } 240 catch (InvocationTargetException e) { 241 mLog.error("Error constructing context"); 242 mLog.error(e.getTargetException()); 243 } 244 catch (InstantiationException e) { 245 mLog.error("Error constructing context"); 246 mLog.error(e); 247 } 248 catch (IllegalAccessException e) { 249 mLog.error("Error constructing context"); 250 mLog.error(e); 251 } 252 253 return httpContext; 256 } 257 258 public Class getContextType() { 259 return mContextConstructor.getDeclaringClass(); 260 } 261 262 public Application[] getApplications() { 263 return (Application[])mApps.clone(); 264 } 265 266 public String [] getApplicationNames() { 267 int length = mApps.length; 268 String [] names = new String [length]; 269 for (int i=0; i<length; i++) { 270 names[i] = (String )mAppNameMap.get(mApps[i]); 271 } 272 return names; 273 } 274 275 public String [] getContextPrefixNames() { 276 int length = mApps.length; 277 String [] names = new String [length]; 278 for (int i=0; i<length; i++) { 279 names[i] = cleanName((String )mAppNameMap.get(mApps[i])); 280 } 281 return names; 282 } 283 284 private Application loadApplication(String name, Map plugins) 285 throws ServletException  286 { 287 mLog.info("Loading \"" + name + '"'); 288 289 PropertyMap properties = mProperties.subMap(name); 290 String className = properties.getString("class"); 291 if (className == null) { 292 mLog.error("No class specified for " + name); 293 return null; 294 } 295 296 Class appClass; 298 try { 299 appClass = Class.forName(className); 300 } 301 catch (ClassNotFoundException e) { 302 mLog.error(e); 303 return null; 304 } 305 catch (LinkageError e) { 306 mLog.error(e); 307 return null; 308 } 309 310 Application app; 311 try { 312 app = (Application)appClass.newInstance(); 313 } 314 catch (ClassCastException e) { 315 mLog.error("Class is not an Application: " + appClass); 316 return null; 317 } 318 catch (Exception e) { 319 mLog.error(e); 320 return null; 321 } 322 323 mLog.info("Initializing \"" + name + '"'); 325 326 ApplicationConfig appConfig = 327 new InternalApplicationConfig(mBaseConfig, properties, plugins, name); 328 329 try { 330 app.init(appConfig); 331 return app; 332 } 333 catch (ServletException e) { 334 Throwable rootCause = e.getRootCause(); 335 if (rootCause != null) { 336 String message = e.getMessage(); 337 if (message != null && message.length() > 0) { 338 mLog.error(message); 339 } 340 mLog.error(rootCause); 341 } 342 else { 343 mLog.error(e); 344 } 345 } 346 catch (LinkageError e) { 347 mLog.error(e); 348 } 349 catch (Exception e) { 350 mLog.error(e); 351 } 352 353 return null; 354 } 355 356 private class ContextFactory implements MergedClass.InstanceFactory { 357 private final HttpContext mHttpContext; 358 private final ApplicationRequest mRequest; 359 private final ApplicationResponse mResponse; 360 361 ContextFactory(HttpContext httpContext, 362 ApplicationRequest request, 363 ApplicationResponse response) { 364 mHttpContext = httpContext; 365 mRequest = request; 366 mResponse = response; 367 } 368 369 public Object getInstance(int i) { 370 Object context; 371 if (i == 0) { 372 context = mHttpContext; 373 } 374 else { 375 context = mAppsWithContexts[i - 1].createContext 376 (mRequest, mResponse); 377 if (context == null) { 378 mLog.warn("Null context created by " + 379 mAppsWithContexts[i - 1]); 380 } 381 } 382 return context; 383 } 384 } 385 } 386
| Popular Tags
|