Clover coverage report - Code Coverage for hivemind release 1.1-beta-3
Coverage timestamp: Mon Aug 22 2005 21:38:15 EDT
file stats: LOC: 622   Methods: 35
NCLOC: 401   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
RegistryInfrastructureImpl.java 92.1% 97.4% 94.3% 95.7%
coverage coverage
 1    // Copyright 2004, 2005 The Apache Software Foundation
 2    //
 3    // Licensed under the Apache License, Version 2.0 (the "License");
 4    // you may not use this file except in compliance with the License.
 5    // You may obtain a copy of the License at
 6    //
 7    // http://www.apache.org/licenses/LICENSE-2.0
 8    //
 9    // Unless required by applicable law or agreed to in writing, software
 10    // distributed under the License is distributed on an "AS IS" BASIS,
 11    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12    // See the License for the specific language governing permissions and
 13    // limitations under the License.
 14   
 15    package org.apache.hivemind.impl;
 16   
 17    import java.util.Collections;
 18    import java.util.HashMap;
 19    import java.util.Iterator;
 20    import java.util.LinkedList;
 21    import java.util.List;
 22    import java.util.Locale;
 23    import java.util.Map;
 24   
 25    import org.apache.commons.logging.LogFactory;
 26    import org.apache.hivemind.ApplicationRuntimeException;
 27    import org.apache.hivemind.ErrorHandler;
 28    import org.apache.hivemind.HiveMindMessages;
 29    import org.apache.hivemind.Location;
 30    import org.apache.hivemind.ShutdownCoordinator;
 31    import org.apache.hivemind.SymbolSource;
 32    import org.apache.hivemind.SymbolSourceContribution;
 33    import org.apache.hivemind.internal.ConfigurationPoint;
 34    import org.apache.hivemind.internal.Module;
 35    import org.apache.hivemind.internal.RegistryInfrastructure;
 36    import org.apache.hivemind.internal.ServiceModelFactory;
 37    import org.apache.hivemind.internal.ServicePoint;
 38    import org.apache.hivemind.internal.ser.ServiceSerializationHelper;
 39    import org.apache.hivemind.internal.ser.ServiceSerializationSupport;
 40    import org.apache.hivemind.internal.ser.ServiceToken;
 41    import org.apache.hivemind.order.Orderer;
 42    import org.apache.hivemind.schema.Translator;
 43    import org.apache.hivemind.service.ThreadEventNotifier;
 44    import org.apache.hivemind.util.Defense;
 45    import org.apache.hivemind.util.PropertyUtils;
 46    import org.apache.hivemind.util.ToStringBuilder;
 47   
 48    /**
 49    * Implementation of {@link RegistryInfrastructure}.
 50    *
 51    * @author Howard Lewis Ship
 52    */
 53    public final class RegistryInfrastructureImpl implements RegistryInfrastructure,
 54    ServiceSerializationSupport
 55    {
 56    private static final String SYMBOL_SOURCES = "hivemind.SymbolSources";
 57   
 58    /**
 59    * Map of {@link ServicePoint} keyed on fully qualified service id.
 60    */
 61    private Map _servicePoints = new HashMap();
 62   
 63    /**
 64    * Map of List (of {@link ServicePoint}, keyed on class name service interface.
 65    */
 66    private Map _servicePointsByInterfaceClassName = new HashMap();
 67   
 68    /**
 69    * Map of {@link ConfigurationPoint} keyed on fully qualified configuration id.
 70    */
 71    private Map _configurationPoints = new HashMap();
 72   
 73    private SymbolSource[] _variableSources;
 74   
 75    private ErrorHandler _errorHandler;
 76   
 77    private Locale _locale;
 78   
 79    private ShutdownCoordinator _shutdownCoordinator;
 80   
 81    /**
 82    * Map of {@link org.apache.hivemind.internal.ser.ServiceToken}, keyed on service id.
 83    *
 84    * @since 1.1
 85    */
 86   
 87    private Map _serviceTokens;
 88   
 89    /**
 90    * Map of {@link ServiceModelFactory}, keyed on service model name, loaded from
 91    * <code>hivemind.ServiceModels</code> configuration point.
 92    */
 93    private Map _serviceModelFactories;
 94   
 95    private boolean _started = false;
 96   
 97    private boolean _shutdown = false;
 98   
 99    private ThreadEventNotifier _threadEventNotifier;
 100   
 101    private TranslatorManager _translatorManager;
 102   
 103    private SymbolExpander _expander;
 104   
 105  145 public RegistryInfrastructureImpl(ErrorHandler errorHandler, Locale locale)
 106    {
 107  145 _errorHandler = errorHandler;
 108  145 _locale = locale;
 109   
 110  145 _translatorManager = new TranslatorManager(this, errorHandler);
 111   
 112  145 _expander = new SymbolExpander(_errorHandler, this);
 113    }
 114   
 115  14 public Locale getLocale()
 116    {
 117  14 return _locale;
 118    }
 119   
 120  2576 public void addServicePoint(ServicePoint point)
 121    {
 122  2576 checkStarted();
 123   
 124  2576 _servicePoints.put(point.getExtensionPointId(), point);
 125   
 126  2576 addServicePointByInterface(point);
 127    }
 128   
 129  2576 private void addServicePointByInterface(ServicePoint point)
 130    {
 131  2576 String key = point.getServiceInterfaceClassName();
 132   
 133  2576 List l = (List) _servicePointsByInterfaceClassName.get(key);
 134   
 135  2576 if (l == null)
 136    {
 137  1572 l = new LinkedList();
 138  1572 _servicePointsByInterfaceClassName.put(key, l);
 139    }
 140   
 141  2576 l.add(point);
 142    }
 143   
 144  1040 public void addConfigurationPoint(ConfigurationPoint point)
 145    {
 146  1040 checkStarted();
 147   
 148  1040 _configurationPoints.put(point.getExtensionPointId(), point);
 149    }
 150   
 151  3768 public ServicePoint getServicePoint(String serviceId, Module module)
 152    {
 153  3768 checkShutdown();
 154  3768 ServicePoint result = (ServicePoint) _servicePoints.get(serviceId);
 155  3768 if (result == null)
 156    {
 157  3 if (serviceId.indexOf('.') == -1)
 158    {
 159  3 final List possibleMatches = getMatchingServiceIds(serviceId);
 160  3 if (!possibleMatches.isEmpty())
 161    {
 162  2 final StringBuffer sb = new StringBuffer();
 163  2 for (Iterator i = possibleMatches.iterator(); i.hasNext();)
 164    {
 165  3 final String matching = (String) i.next();
 166  3 sb.append('\"');
 167  3 sb.append(matching);
 168  3 sb.append('\"');
 169  3 if (i.hasNext())
 170    {
 171  1 sb.append(", ");
 172    }
 173    }
 174  2 throw new ApplicationRuntimeException(ImplMessages.unqualifiedServicePoint(
 175    serviceId,
 176    sb.toString()));
 177    }
 178    }
 179  1 throw new ApplicationRuntimeException(ImplMessages.noSuchServicePoint(serviceId));
 180    }
 181   
 182  3765 if (!result.visibleToModule(module))
 183  2 throw new ApplicationRuntimeException(ImplMessages.serviceNotVisible(serviceId, module));
 184   
 185  3763 return result;
 186    }
 187   
 188  3 private List getMatchingServiceIds(String serviceId)
 189    {
 190  3 final List possibleMatches = new LinkedList();
 191  3 for (Iterator i = _servicePoints.values().iterator(); i.hasNext();)
 192    {
 193  3 final ServicePoint servicePoint = (ServicePoint) i.next();
 194  3 if (servicePoint.getExtensionPointId().equals(
 195    servicePoint.getModule().getModuleId() + "." + serviceId))
 196    {
 197  3 possibleMatches.add(servicePoint.getExtensionPointId());
 198    }
 199    }
 200  3 return possibleMatches;
 201    }
 202   
 203  3251 public Object getService(String serviceId, Class serviceInterface, Module module)
 204    {
 205  3251 ServicePoint point = getServicePoint(serviceId, module);
 206   
 207  3249 return point.getService(serviceInterface);
 208    }
 209   
 210  155 public Object getService(Class serviceInterface, Module module)
 211    {
 212  155 String key = serviceInterface.getName();
 213   
 214  155 List servicePoints = (List) _servicePointsByInterfaceClassName.get(key);
 215   
 216  155 if (servicePoints == null)
 217  1 servicePoints = Collections.EMPTY_LIST;
 218   
 219  155 ServicePoint point = null;
 220  155 int count = 0;
 221   
 222  155 Iterator i = servicePoints.iterator();
 223  155 while (i.hasNext())
 224    {
 225  156 ServicePoint sp = (ServicePoint) i.next();
 226   
 227  156 if (!sp.visibleToModule(module))
 228  1 continue;
 229   
 230  155 point = sp;
 231   
 232  155 count++;
 233    }
 234   
 235  155 if (count == 0)
 236  1 throw new ApplicationRuntimeException(ImplMessages
 237    .noServicePointForInterface(serviceInterface));
 238   
 239  154 if (count > 1)
 240  1 throw new ApplicationRuntimeException(ImplMessages.multipleServicePointsForInterface(
 241    serviceInterface,
 242    servicePoints));
 243   
 244  153 return point.getService(serviceInterface);
 245    }
 246   
 247  792 public ConfigurationPoint getConfigurationPoint(String configurationId, Module module)
 248    {
 249  792 checkShutdown();
 250   
 251  791 ConfigurationPoint result = (ConfigurationPoint) _configurationPoints.get(configurationId);
 252   
 253  791 if (result == null)
 254  1 throw new ApplicationRuntimeException(ImplMessages.noSuchConfiguration(configurationId));
 255   
 256  790 if (!result.visibleToModule(module))
 257  1 throw new ApplicationRuntimeException(ImplMessages.configurationNotVisible(
 258    configurationId,
 259    module));
 260   
 261  789 return result;
 262    }
 263   
 264  543 public List getConfiguration(String configurationId, Module module)
 265    {
 266  543 ConfigurationPoint point = getConfigurationPoint(configurationId, module);
 267   
 268  540 return point.getElements();
 269    }
 270   
 271  0 public boolean isConfigurationMappable(String configurationId, Module module)
 272    {
 273  0 ConfigurationPoint point = getConfigurationPoint(configurationId, module);
 274   
 275  0 return point.areElementsMappable();
 276    }
 277   
 278  0 public Map getConfigurationAsMap(String configurationId, Module module)
 279    {
 280  0 ConfigurationPoint point = getConfigurationPoint(configurationId, module);
 281   
 282  0 return point.getElementsAsMap();
 283    }
 284   
 285  1 public String toString()
 286    {
 287  1 ToStringBuilder builder = new ToStringBuilder(this);
 288   
 289  1 builder.append("locale", _locale);
 290   
 291  1 return builder.toString();
 292    }
 293   
 294  7163 public String expandSymbols(String text, Location location)
 295    {
 296  7163 return _expander.expandSymbols(text, location);
 297    }
 298   
 299  5 public String valueForSymbol(String name)
 300    {
 301  5 checkShutdown();
 302   
 303  5 SymbolSource[] sources = getSymbolSources();
 304   
 305  5 for (int i = 0; i < sources.length; i++)
 306    {
 307  7 String value = sources[i].valueForSymbol(name);
 308   
 309  7 if (value != null)
 310  4 return value;
 311    }
 312   
 313  1 return null;
 314    }
 315   
 316  5 private synchronized SymbolSource[] getSymbolSources()
 317    {
 318  5 if (_variableSources != null)
 319  2 return _variableSources;
 320   
 321  3 List contributions = getConfiguration(SYMBOL_SOURCES, null);
 322   
 323  3 Orderer o = new Orderer(LogFactory.getLog(SYMBOL_SOURCES), _errorHandler, ImplMessages
 324    .symbolSourceContribution());
 325   
 326  3 Iterator i = contributions.iterator();
 327  3 while (i.hasNext())
 328    {
 329  8 SymbolSourceContribution c = (SymbolSourceContribution) i.next();
 330   
 331  8 o.add(c, c.getName(), c.getPrecedingNames(), c.getFollowingNames());
 332    }
 333   
 334  3 List sources = o.getOrderedObjects();
 335   
 336  3 int count = sources.size();
 337   
 338  3 _variableSources = new SymbolSource[count];
 339   
 340  3 for (int j = 0; j < count; j++)
 341    {
 342  8 SymbolSourceContribution c = (SymbolSourceContribution) sources.get(j);
 343  8 _variableSources[j] = c.getSource();
 344    }
 345   
 346  3 return _variableSources;
 347    }
 348   
 349  129 public void setShutdownCoordinator(ShutdownCoordinator coordinator)
 350    {
 351  129 _shutdownCoordinator = coordinator;
 352    }
 353   
 354    /**
 355    * Invokes {@link ShutdownCoordinator#shutdown()}, then releases the coordinator, modules and
 356    * variable sources.
 357    */
 358  29 public synchronized void shutdown()
 359    {
 360  29 checkShutdown();
 361   
 362  28 ServiceSerializationHelper.setServiceSerializationSupport(null);
 363   
 364    // Allow service implementations and such to shutdown.
 365   
 366  28 ShutdownCoordinator coordinatorService = (ShutdownCoordinator) getService(
 367    "hivemind.ShutdownCoordinator",
 368    ShutdownCoordinator.class,
 369    null);
 370   
 371  28 coordinatorService.shutdown();
 372   
 373    // TODO: Shoudl this be moved earlier?
 374   
 375  28 _shutdown = true;
 376   
 377    // Shutdown infrastructure items, such as proxies.
 378   
 379  28 _shutdownCoordinator.shutdown();
 380   
 381  28 _servicePoints = null;
 382  28 _servicePointsByInterfaceClassName = null;
 383  28 _configurationPoints = null;
 384  28 _shutdownCoordinator = null;
 385  28 _variableSources = null;
 386  28 _serviceModelFactories = null;
 387  28 _threadEventNotifier = null;
 388  28 _serviceTokens = null;
 389   
 390    // It is believed that the cache held by PropertyUtils can affect application shutdown
 391    // and reload in some servlet containers (such as Tomcat); this should clear that up.
 392   
 393  28 PropertyUtils.clearCache();
 394    }
 395   
 396    /**
 397    * Technically, this should be a synchronized method, but the _shutdown variable hardly ever
 398    * changes, and the consequences are pretty minimal. See HIVEMIND-104.
 399    */
 400   
 401  4882 private void checkShutdown()
 402    {
 403  4882 if (_shutdown)
 404  2 throw new ApplicationRuntimeException(HiveMindMessages.registryShutdown());
 405    }
 406   
 407  3740 private void checkStarted()
 408    {
 409  3740 if (_started)
 410  1 throw new IllegalStateException(ImplMessages.registryAlreadyStarted());
 411    }
 412   
 413    /**
 414    * Starts up the Registry after all service and configuration points have been defined. This
 415    * locks down the Registry so that no further extension points may be added. This method may
 416    * only be invoked once.
 417    * <p>
 418    * This instance is stored into
 419    * {@link ServiceSerializationHelper#setServiceSerializationSupport(ServiceSerializationSupport)}.
 420    * This may cause errors (and incorrect behavior) if multiple Registries exist in a single JVM.
 421    * <p>
 422    * In addition, the service <code>hivemind.Startup</code> is obtained and <code>run()</code>
 423    * is invoked on it. This allows additional startup, provided in the
 424    * <code>hivemind.Startup</code> configuration point, to be executed.
 425    */
 426  124 public void startup()
 427    {
 428  124 checkStarted();
 429   
 430  123 ServiceSerializationHelper.setServiceSerializationSupport(this);
 431   
 432  123 _started = true;
 433   
 434  123 Runnable startup = (Runnable) getService("hivemind.Startup", Runnable.class, null);
 435   
 436  123 startup.run();
 437    }
 438   
 439  1414 public synchronized ServiceModelFactory getServiceModelFactory(String name)
 440    {
 441  1414 if (_serviceModelFactories == null)
 442  123 readServiceModelFactories();
 443   
 444  1414 ServiceModelFactory result = (ServiceModelFactory) _serviceModelFactories.get(name);
 445   
 446  1414 if (result == null)
 447  1 throw new ApplicationRuntimeException(ImplMessages.unknownServiceModel(name));
 448   
 449  1413 return result;
 450    }
 451   
 452  123 private void readServiceModelFactories()
 453    {
 454  123 List l = getConfiguration("hivemind.ServiceModels", null);
 455   
 456  123 _serviceModelFactories = new HashMap();
 457   
 458  123 Iterator i = l.iterator();
 459   
 460  123 while (i.hasNext())
 461    {
 462  488 ServiceModelContribution smc = (ServiceModelContribution) i.next();
 463   
 464  488 String name = smc.getName();
 465   
 466  488 _serviceModelFactories.put(name, smc.getFactory());
 467    }
 468    }
 469   
 470  803 public synchronized void cleanupThread()
 471    {
 472  803 if (_threadEventNotifier == null)
 473  7 _threadEventNotifier = (ThreadEventNotifier) getService(
 474    "hivemind.ThreadEventNotifier",
 475    ThreadEventNotifier.class,
 476    null);
 477   
 478  803 _threadEventNotifier.fireThreadCleanup();
 479    }
 480   
 481  2 public boolean containsConfiguration(String configurationId, Module module)
 482    {
 483  2 checkShutdown();
 484   
 485  2 ConfigurationPoint result = (ConfigurationPoint) _configurationPoints.get(configurationId);
 486   
 487  2 return result != null && result.visibleToModule(module);
 488    }
 489   
 490  281 public boolean containsService(Class serviceInterface, Module module)
 491    {
 492  281 checkShutdown();
 493   
 494  281 String key = serviceInterface.getName();
 495   
 496  281 List servicePoints = (List) _servicePointsByInterfaceClassName.get(key);
 497   
 498  281 if (servicePoints == null)
 499  147 return false;
 500   
 501  134 int count = 0;
 502   
 503  134 Iterator i = servicePoints.iterator();
 504  134 while (i.hasNext())
 505    {
 506  135 ServicePoint point = (ServicePoint) i.next();
 507   
 508  135 if (point.visibleToModule(module))
 509  135 count++;
 510    }
 511   
 512  134 return count == 1;
 513    }
 514   
 515  3 public boolean containsService(String serviceId, Class serviceInterface, Module module)
 516    {
 517  3 checkShutdown();
 518   
 519  3 ServicePoint point = (ServicePoint) _servicePoints.get(serviceId);
 520   
 521  3 if (point == null)
 522  1 return false;
 523   
 524  2 return point.visibleToModule(module)
 525    && point.getServiceInterface().equals(serviceInterface);
 526    }
 527   
 528  1051 public ErrorHandler getErrorHander()
 529    {
 530  1051 return _errorHandler;
 531    }
 532   
 533  8903 public Translator getTranslator(String constructor)
 534    {
 535  8903 return _translatorManager.getTranslator(constructor);
 536    }
 537   
 538  1 public Object getServiceFromToken(ServiceToken token)
 539    {
 540  1 Defense.notNull(token, "token");
 541   
 542  1 checkShutdown();
 543   
 544  1 String serviceId = token.getServiceId();
 545   
 546  1 ServicePoint sp = (ServicePoint) _servicePoints.get(serviceId);
 547   
 548  1 return sp.getService(Object.class);
 549    }
 550   
 551  1 public synchronized ServiceToken getServiceTokenForService(String serviceId)
 552    {
 553  1 Defense.notNull(serviceId, "serviceId");
 554   
 555  1 checkShutdown();
 556   
 557  1 if (_serviceTokens == null)
 558  1 _serviceTokens = new HashMap();
 559   
 560  1 ServiceToken result = (ServiceToken) _serviceTokens.get(serviceId);
 561   
 562  1 if (result == null)
 563    {
 564  1 result = new ServiceToken(serviceId);
 565  1 _serviceTokens.put(serviceId, result);
 566    }
 567   
 568  1 return result;
 569    }
 570   
 571    /**
 572    * Sets the current RI up as the ServiceSerializationSupport. Any service proxy tokens that are
 573    * de-serialized will find their proxies within this Registry.
 574    *
 575    * @since 1.1
 576    */
 577   
 578  2 public void setupThread()
 579    {
 580  2 ServiceSerializationHelper.setServiceSerializationSupport(this);
 581    }
 582   
 583  1 public Module getModule(String moduleId)
 584    {
 585  7 for (Iterator i = _servicePoints.values().iterator(); i.hasNext();)
 586    {
 587  7 final ServicePoint servicePoint = (ServicePoint) i.next();
 588   
 589  7 if (servicePoint.getModule().getModuleId().equals(moduleId))
 590    {
 591  1 return servicePoint.getModule();
 592    }
 593    }
 594  0 return null;
 595    }
 596   
 597    /*
 598    * (non-Javadoc)
 599    *
 600    * @see org.apache.hivemind.internal.RegistryInfrastructure#getServiceIds(java.lang.Class)
 601    */
 602  6 public List getServiceIds(Class serviceInterface)
 603    {
 604  6 final List serviceIds = new LinkedList();
 605  6 if( serviceInterface == null )
 606    {
 607  1 return serviceIds;
 608    }
 609  5 for (Iterator i = _servicePoints.values().iterator(); i.hasNext();)
 610    {
 611  9 final ServicePoint servicePoint = (ServicePoint) i.next();
 612   
 613  9 if (serviceInterface.getName().equals( servicePoint.getServiceInterfaceClassName() )
 614    && servicePoint.visibleToModule(null))
 615    {
 616  3 serviceIds.add(servicePoint.getExtensionPointId());
 617    }
 618   
 619    }
 620  5 return serviceIds;
 621    }
 622    }