1 15 package org.apache.hivemind.impl; 16 17 import java.lang.reflect.Constructor ; 18 import java.lang.reflect.Modifier ; 19 import java.util.ArrayList ; 20 import java.util.Collection ; 21 import java.util.HashMap ; 22 import java.util.Iterator ; 23 import java.util.List ; 24 import java.util.Map ; 25 26 import org.apache.commons.logging.Log; 27 import org.apache.commons.logging.LogFactory; 28 import org.apache.hivemind.ApplicationRuntimeException; 29 import org.apache.hivemind.ShutdownCoordinator; 30 import org.apache.hivemind.definition.ConfigurationPointDefinition; 31 import org.apache.hivemind.definition.Contribution; 32 import org.apache.hivemind.definition.ContributionContext; 33 import org.apache.hivemind.definition.ContributionDefinition; 34 import org.apache.hivemind.definition.Occurances; 35 import org.apache.hivemind.impl.servicemodel.SingletonInnerProxy; 36 import org.apache.hivemind.internal.AbstractConstructionContext; 37 import org.apache.hivemind.internal.ConfigurationPoint; 38 import org.apache.hivemind.internal.Module; 39 import org.apache.hivemind.service.BodyBuilder; 40 import org.apache.hivemind.service.ClassFab; 41 import org.apache.hivemind.service.MethodSignature; 42 import org.apache.hivemind.util.ToStringBuilder; 43 44 50 public final class ConfigurationPointImpl extends AbstractExtensionPoint implements 51 ConfigurationPoint 52 { 53 private static final Log LOG = LogFactory.getLog(ConfigurationPointImpl.class); 54 55 58 private Object _configuration; 59 60 private Class _configurationInterface; 61 62 private Object _configurationProxy; 63 64 private Occurances _expectedCount; 65 66 private boolean _building; 67 68 private ShutdownCoordinator _shutdownCoordinator; 70 71 public ConfigurationPointImpl(Module module, ConfigurationPointDefinition definition) 72 { 73 super(module, definition); 74 } 75 76 public ConfigurationPointDefinition getConfigurationPointDefinition() 77 { 78 return (ConfigurationPointDefinition) super.getDefinition(); 79 } 80 81 protected void extendDescription(ToStringBuilder builder) 82 { 83 builder.append("type", getConfigurationTypeName()); 84 builder.append("expectedCount", _expectedCount); 85 } 86 87 public Collection getContributions() 88 { 89 return getConfigurationPointDefinition().getContributions(); 90 } 91 92 98 public int getContributionCount() 99 { 100 if (getConfigurationPointDefinition() == null) 101 return 0; 102 103 return getContributions().size(); 104 } 105 106 public Occurances getExpectedCount() 107 { 108 return getConfigurationPointDefinition().getExpectedContributions(); 109 } 110 111 114 public boolean isLazy() 115 { 116 return !getExtensionPointId().equals("hivemind.ServiceModels") && 120 getConfigurationType().isInterface() && 121 !Modifier.isFinal(getConfigurationType().getModifiers()); 122 } 123 124 127 public synchronized Object getConfiguration() 128 { 129 if (_configuration != null) 130 return _configuration; 131 132 if (isLazy()) { 133 if (_configurationProxy == null) 136 { 137 _configurationProxy = createSingletonProxy(); 138 } 139 return _configurationProxy; 140 141 } else { 142 _configuration = constructConfiguration(); 144 return _configuration; 145 } 146 } 147 148 154 public synchronized Object constructConfiguration() 155 { 156 160 if (_building) 161 throw new ApplicationRuntimeException(ImplMessages 162 .recursiveConfiguration(getExtensionPointId())); 163 164 try 165 { 166 if (_configuration == null) 167 { 168 _building = true; 169 170 processContributions(); 171 } 172 173 175 _configurationProxy = null; 176 177 return _configuration; 178 } 179 finally 180 { 181 _building = false; 182 } 183 } 184 185 188 private void processContributions() 189 { 190 if (LOG.isDebugEnabled()) 191 LOG.debug("Constructing extension point " + getExtensionPointId()); 192 193 Collection contributions = getContributions(); 194 195 if (contributions == null) 196 return; 197 198 try 199 { 200 for (Iterator iterContrib = contributions.iterator(); iterContrib.hasNext();) 201 { 202 ContributionDefinition cd = (ContributionDefinition) iterContrib.next(); 203 Module definingModule = getModule().getRegistry().getModule(cd.getModuleId()); 204 ContributionContext context = new ContributionContextImpl(definingModule, this); 205 cd.getContribution().contribute(context); 206 } 207 if (_configuration == null) { 209 initEmptyCollection(); 210 } 211 } 212 catch (Exception ex) 213 { 214 throw new ApplicationRuntimeException(ImplMessages.unableToConstructConfiguration( 215 getExtensionPointId(), 216 ex), ex); 217 } 218 219 } 220 221 225 class ContributionContextImpl extends AbstractConstructionContext implements ContributionContext 226 { 227 private ConfigurationPoint _configurationPoint; 228 229 public ContributionContextImpl(Module definingModule, ConfigurationPoint configurationPoint) 230 { 231 super(definingModule); 232 _configurationPoint = configurationPoint; 233 } 234 235 public Object getConfigurationData() 236 { 237 return _configuration; 238 } 239 240 public void mergeContribution(Object contributionData) 241 { 242 ConfigurationPointImpl.this.mergeContribution(contributionData); 243 } 244 245 public void setConfigurationData(Object data) 246 { 247 _configuration = data; 248 } 249 250 public ConfigurationPoint getConfigurationPoint() 251 { 252 return _configurationPoint; 253 } 254 } 255 256 private void initEmptyCollection() 257 { 258 if (List .class.equals(getConfigurationType())) { 262 _configuration = new ArrayList (); 263 } 264 else if (Map .class.equals(getConfigurationType())) { 265 _configuration = new HashMap (); 266 } 267 } 268 269 274 private void mergeContribution(Object contribution) 275 { 276 if (!getConfigurationType().isAssignableFrom(contribution.getClass())) { 277 throw new ApplicationRuntimeException("contribution of of type " + 278 contribution.getClass().getName() + " is not compatible to configuration type " + 279 getConfigurationType().getName()); 280 } 281 if (_configuration == null) { 282 _configuration = contribution; 283 } else { 284 if (_configuration instanceof Collection ) { 285 ((Collection ) _configuration).addAll((Collection ) contribution); 286 } 287 else if (_configuration instanceof Map ) { 288 ((Map ) _configuration).putAll((Map ) contribution); 289 } 290 } 291 292 293 } 294 295 public void setShutdownCoordinator(ShutdownCoordinator coordinator) 296 { 297 _shutdownCoordinator = coordinator; 298 } 299 300 public String getConfigurationTypeName() 301 { 302 return getConfigurationPointDefinition().getConfigurationTypeName(); 303 } 304 305 308 public Class getConfigurationType() 309 { 310 if (_configurationInterface == null) 311 _configurationInterface = getModule().resolveType(getConfigurationTypeName()); 312 313 return _configurationInterface; 314 } 315 316 319 private Object createSingletonProxy() 320 { 321 if (LOG.isDebugEnabled()) 322 LOG.debug("Creating LazyConstructionProxy for configuration " 323 + getExtensionPointId()); 324 325 try 326 { 327 328 331 Class proxyClass = getSingletonProxyClass(); 332 333 336 Class innerProxyClass = getInnerProxyClass(proxyClass); 337 338 340 Constructor co = proxyClass.getConstructor(new Class [] 341 { String .class }); 342 343 Object result = co.newInstance(new Object [] { getExtensionPointId() }); 344 345 348 Constructor ci = innerProxyClass.getConstructor(new Class [] 349 { String .class, proxyClass, getClass() }); 350 351 ci.newInstance(new Object [] { getExtensionPointId(), result, this }); 352 353 return result; 354 } 355 catch (Exception ex) 356 { 357 throw new ApplicationRuntimeException(ex); 358 } 359 360 } 361 362 private final static Map SINGLETON_PROXY_CACHE = new HashMap (); 363 private final static Map INNER_PROXY_CACHE = new HashMap (); 364 365 private Class getSingletonProxyClass() 366 { 367 Class configurationInterface = getConfigurationType(); 368 Class result = (Class ) SINGLETON_PROXY_CACHE.get(configurationInterface); 369 if (result == null) { 370 result = createSingletonProxyClass(); 371 SINGLETON_PROXY_CACHE.put(configurationInterface, result); 372 } 373 return result; 374 } 375 376 private Class getInnerProxyClass(Class deferredProxyClass) 377 { 378 Class result = (Class ) INNER_PROXY_CACHE.get(deferredProxyClass); 379 if (result == null) { 380 result = createInnerProxyClass(deferredProxyClass); 381 INNER_PROXY_CACHE.put(deferredProxyClass, result); 382 } 383 return result; 384 } 385 386 392 private Class createSingletonProxyClass() 393 { 394 ProxyBuilder proxyBuilder = new ProxyBuilder("LazyConstructionProxy", getModule(), getConfigurationType(), 395 getConfigurationType(), true); 396 397 ClassFab classFab = proxyBuilder.getClassFab(); 398 399 400 403 classFab.addField("_inner", getConfigurationType()); 404 classFab.addMethod( 405 Modifier.PUBLIC | Modifier.SYNCHRONIZED | Modifier.FINAL, 406 new MethodSignature(void.class, "_setInner", new Class [] 407 { getConfigurationType() }, null), 408 "{ _inner = $1; }"); 409 410 BodyBuilder builder = new BodyBuilder(); 411 builder.begin(); 412 413 builder.addln("return _inner;"); 414 builder.end(); 415 416 classFab.addMethod(Modifier.PRIVATE, new MethodSignature(getConfigurationType(), "_getInner", 417 null, null), builder.toString()); 418 419 proxyBuilder.addServiceMethods("_getInner()", false); 420 421 builder.clear(); 427 builder.begin(); 428 builder.addln(" return _inner.toString();"); 429 builder.end(); 430 431 MethodSignature toStringSignature = new MethodSignature(String .class, "toString", null, 432 null); 433 if (!classFab.containsMethod(toStringSignature)) { 434 classFab.addMethod(Modifier.PUBLIC, toStringSignature, builder.toString()); 435 } 436 437 return classFab.createClass(); 438 } 439 440 private Class createInnerProxyClass(Class deferredProxyClass) 441 { 442 ProxyBuilder builder = new ProxyBuilder("InnerProxy", getModule(), getConfigurationType(), 443 getConfigurationType(), false); 444 445 ClassFab classFab = builder.getClassFab(); 446 447 classFab.addField("_deferredProxy", deferredProxyClass); 448 classFab.addField("_configuration", getConfigurationType()); 449 classFab.addField("_configurationPoint", ConfigurationPointImpl.class); 450 451 BodyBuilder body = new BodyBuilder(); 452 453 456 body.begin(); 457 458 body.addln("this($1);"); 459 body.addln("_deferredProxy = $2;"); 460 body.addln("_configurationPoint = $3;"); 461 body.addln("_deferredProxy._setInner(this);"); 462 463 body.end(); 464 465 classFab.addConstructor(new Class [] 466 { String .class, deferredProxyClass, ConfigurationPointImpl.class }, null, body.toString()); 467 468 472 body.clear(); 473 body.begin(); 474 475 body.add("if (_configuration == null)"); 476 body.begin(); 477 478 body.add("_configuration = ("); 479 body.add(getConfigurationType().getName()); 480 body.addln(") _configurationPoint.constructConfiguration();"); 481 482 body.add("_deferredProxy._setInner(_configuration);"); 483 484 body.end(); 485 486 body.add("return _configuration;"); 487 488 body.end(); 489 490 classFab.addMethod( 491 Modifier.PRIVATE | Modifier.FINAL | Modifier.SYNCHRONIZED, 492 new MethodSignature(getConfigurationType(), "_configuration", null, null), 493 body.toString()); 494 495 builder.addServiceMethods("_configuration()"); 496 497 499 body.clear(); 500 body.begin(); 501 502 body.add("_configuration();"); 503 504 body.end(); 505 506 classFab.addMethod(Modifier.PUBLIC | Modifier.FINAL, new MethodSignature(void.class, 507 "_instantiateServiceImplementation", null, null), body.toString()); 508 509 classFab.addInterface(SingletonInnerProxy.class); 510 511 return classFab.createClass(); 512 } 513 514 } | Popular Tags |