Clover coverage report - Code Coverage for hivemind release 1.0-rc-1
Coverage timestamp: Wed Aug 25 2004 13:06:02 EDT
file stats: LOC: 572   Methods: 30
NCLOC: 366   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
RegistryImpl.java 81.8% 91.3% 96.7% 89.6%
coverage coverage
 1   
 //  Copyright 2004 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.Collection;
 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.Log;
 26   
 import org.apache.commons.logging.LogFactory;
 27   
 import org.apache.hivemind.ApplicationRuntimeException;
 28   
 import org.apache.hivemind.ErrorHandler;
 29   
 import org.apache.hivemind.HiveMind;
 30   
 import org.apache.hivemind.HiveMindMessages;
 31   
 import org.apache.hivemind.Location;
 32   
 import org.apache.hivemind.Registry;
 33   
 import org.apache.hivemind.ShutdownCoordinator;
 34   
 import org.apache.hivemind.SymbolSource;
 35   
 import org.apache.hivemind.SymbolSourceContribution;
 36   
 import org.apache.hivemind.internal.ConfigurationPoint;
 37   
 import org.apache.hivemind.internal.RegistryInfrastructure;
 38   
 import org.apache.hivemind.internal.ServiceModelFactory;
 39   
 import org.apache.hivemind.internal.ServicePoint;
 40   
 import org.apache.hivemind.order.Orderer;
 41   
 import org.apache.hivemind.schema.Translator;
 42   
 import org.apache.hivemind.service.ThreadEventNotifier;
 43   
 import org.apache.hivemind.util.ToStringBuilder;
 44   
 
 45   
 /**
 46   
  * Implementation of {@link org.apache.hivemind.Registry}.
 47   
  *
 48   
  * @author Howard Lewis Ship
 49   
  */
 50   
 public final class RegistryImpl implements Registry, RegistryInfrastructure
 51   
 {
 52   
     private static final String SYMBOL_SOURCES = "hivemind.SymbolSources";
 53   
     private static final Log LOG = LogFactory.getLog(RegistryImpl.class);
 54   
 
 55   
     /**
 56   
      * Map of {@link ServicePoint} keyed on fully qualified service id.
 57   
      */
 58   
     private Map _servicePoints = new HashMap();
 59   
 
 60   
     /**
 61   
      * Map of List (of {@link ServicePoint}, keyed on service interface.
 62   
      */
 63   
     private Map _servicePointsByInterface = new HashMap();
 64   
 
 65   
     /**
 66   
      * Map of {@link ConfigurationPoint} keyed on fully qualified configuration id.
 67   
      */
 68   
     private Map _configurationPoints = new HashMap();
 69   
 
 70   
     private SymbolSource[] _variableSources;
 71   
     private ErrorHandler _errorHandler;
 72   
     private Locale _locale;
 73   
     private ShutdownCoordinator _shutdownCoordinator;
 74   
 
 75   
     /**
 76   
      * Map of {@link ServiceModelFactory}, keyed on service model name,
 77   
      * loaded from <code>hivemind.ServiceModels</code> configuration point.
 78   
      */
 79   
     private Map _serviceModelFactories;
 80   
 
 81   
     private boolean _started = false;
 82   
     private boolean _shutdown = false;
 83   
 
 84   
     private ThreadEventNotifier _threadEventNotifier;
 85   
     private TranslatorManager _translatorManager;
 86   
 
 87  97
     public RegistryImpl(ErrorHandler errorHandler, Locale locale)
 88   
     {
 89  97
         _errorHandler = errorHandler;
 90  97
         _locale = locale;
 91   
 
 92  97
         _translatorManager = new TranslatorManager(this, errorHandler);
 93   
     }
 94   
 
 95  11
     public Locale getLocale()
 96   
     {
 97  11
         return _locale;
 98   
     }
 99   
 
 100  1544
     public void addServicePoint(ServicePoint point)
 101   
     {
 102  1544
         checkStarted();
 103   
 
 104  1544
         _servicePoints.put(point.getExtensionPointId(), point);
 105   
 
 106  1544
         addServicePointByInterface(point);
 107   
     }
 108   
 
 109  1544
     private void addServicePointByInterface(ServicePoint point)
 110   
     {
 111  1544
         Class key = point.getServiceInterface();
 112   
 
 113  1544
         List l = (List) _servicePointsByInterface.get(key);
 114   
 
 115  1544
         if (l == null)
 116   
         {
 117  1017
             l = new LinkedList();
 118  1017
             _servicePointsByInterface.put(key, l);
 119   
         }
 120   
 
 121  1544
         l.add(point);
 122   
     }
 123   
 
 124  819
     public void addConfigurationPoint(ConfigurationPoint point)
 125   
     {
 126  819
         checkStarted();
 127   
 
 128  819
         _configurationPoints.put(point.getExtensionPointId(), point);
 129   
     }
 130   
 
 131  2529
     public ServicePoint getServicePoint(String serviceId)
 132   
     {
 133  2529
         checkShutdown();
 134   
 
 135  2529
         ServicePoint result = (ServicePoint) _servicePoints.get(serviceId);
 136   
 
 137  2529
         if (result == null)
 138  0
             throw new ApplicationRuntimeException(ImplMessages.noSuchServicePoint(serviceId));
 139   
 
 140  2529
         return result;
 141   
     }
 142   
 
 143  2141
     public Object getService(String serviceId, Class serviceInterface)
 144   
     {
 145  2141
         ServicePoint point = getServicePoint(serviceId);
 146   
 
 147  2141
         return point.getService(serviceInterface);
 148   
     }
 149   
 
 150  134
     public Object getService(Class serviceInterface)
 151   
     {
 152  134
         List servicePoints = (List) _servicePointsByInterface.get(serviceInterface);
 153   
 
 154  134
         if (servicePoints == null)
 155  1
             throw new ApplicationRuntimeException(
 156   
                 ImplMessages.noServicePointForInterface(serviceInterface));
 157   
 
 158  133
         if (servicePoints.size() > 1)
 159  1
             throw new ApplicationRuntimeException(
 160   
                 ImplMessages.multipleServicePointsForInterface(serviceInterface, servicePoints));
 161   
 
 162  132
         ServicePoint sp = (ServicePoint) servicePoints.get(0);
 163   
 
 164  132
         return sp.getService(serviceInterface);
 165   
     }
 166   
 
 167  528
     public ConfigurationPoint getConfigurationPoint(String configurationId)
 168   
     {
 169  528
         checkShutdown();
 170   
 
 171  527
         ConfigurationPoint result = (ConfigurationPoint) _configurationPoints.get(configurationId);
 172   
 
 173  527
         if (result == null)
 174  1
             throw new ApplicationRuntimeException(
 175   
                 ImplMessages.noSuchConfiguration(configurationId));
 176   
 
 177  526
         return result;
 178   
     }
 179   
 
 180  527
     public List getConfiguration(String configurationId)
 181   
     {
 182  527
         ConfigurationPoint point = getConfigurationPoint(configurationId);
 183   
 
 184  525
         return point.getElements();
 185   
     }
 186   
 
 187  4
     public String toString()
 188   
     {
 189  4
         ToStringBuilder builder = new ToStringBuilder(this);
 190   
 
 191  4
         builder.append("locale", _locale);
 192   
 
 193  4
         return builder.toString();
 194   
     }
 195   
 
 196   
     private static final int STATE_START = 0;
 197   
     private static final int STATE_DOLLAR = 1;
 198   
     private static final int STATE_COLLECT_SYMBOL_NAME = 2;
 199   
 
 200   
     /**
 201   
      * 
 202   
      * Note: a little cut-n-paste from {@link org.apache.tapestry.script.AbstractTokenRule}.
 203   
      */
 204  4915
     public String expandSymbols(String text, Location location)
 205   
     {
 206  4915
         StringBuffer result = new StringBuffer(text.length());
 207  4915
         char[] buffer = text.toCharArray();
 208  4915
         int state = STATE_START;
 209  4915
         int blockStart = 0;
 210  4915
         int blockLength = 0;
 211  4915
         int symbolStart = -1;
 212  4915
         int symbolLength = 0;
 213  4915
         int i = 0;
 214  4915
         int braceDepth = 0;
 215  4915
         boolean anySymbols = false;
 216   
 
 217  4915
         while (i < buffer.length)
 218   
         {
 219  127910
             char ch = buffer[i];
 220   
 
 221  127910
             switch (state)
 222   
             {
 223   
                 case STATE_START :
 224   
 
 225  127877
                     if (ch == '$')
 226   
                     {
 227  5
                         state = STATE_DOLLAR;
 228  5
                         i++;
 229  5
                         continue;
 230   
                     }
 231   
 
 232  127872
                     blockLength++;
 233  127872
                     i++;
 234  127872
                     continue;
 235   
 
 236   
                 case STATE_DOLLAR :
 237   
 
 238  5
                     if (ch == '{')
 239   
                     {
 240  5
                         state = STATE_COLLECT_SYMBOL_NAME;
 241  5
                         i++;
 242   
 
 243  5
                         symbolStart = i;
 244  5
                         symbolLength = 0;
 245  5
                         braceDepth = 1;
 246   
 
 247  5
                         continue;
 248   
                     }
 249   
 
 250   
                     // The '$' was just what it was, not the start of a ${} expression
 251   
                     // block, so include it as part of the static text block.
 252   
 
 253  0
                     blockLength++;
 254   
 
 255  0
                     state = STATE_START;
 256  0
                     continue;
 257   
 
 258   
                 case STATE_COLLECT_SYMBOL_NAME :
 259   
 
 260  28
                     if (ch != '}')
 261   
                     {
 262  23
                         if (ch == '{')
 263  0
                             braceDepth++;
 264   
 
 265  23
                         i++;
 266  23
                         symbolLength++;
 267  23
                         continue;
 268   
                     }
 269   
 
 270  5
                     braceDepth--;
 271   
 
 272  5
                     if (braceDepth > 0)
 273   
                     {
 274  0
                         i++;
 275  0
                         symbolLength++;
 276  0
                         continue;
 277   
                     }
 278   
 
 279   
                     // Hit the closing brace of a symbol.
 280   
 
 281   
                     // Degenerate case:  the string "${}".
 282   
 
 283  5
                     if (symbolLength == 0)
 284  0
                         blockLength += 3;
 285   
 
 286   
                     // Append anything up to the start of the sequence (this is static
 287   
                     // text between symbol references).
 288   
 
 289  5
                     if (blockLength > 0)
 290  1
                         result.append(buffer, blockStart, blockLength);
 291   
 
 292  5
                     if (symbolLength > 0)
 293   
                     {
 294  5
                         String variableName =
 295   
                             text.substring(symbolStart, symbolStart + symbolLength);
 296   
 
 297  5
                         result.append(expandSymbol(variableName, location));
 298   
 
 299  5
                         anySymbols = true;
 300   
                     }
 301   
 
 302  5
                     i++;
 303  5
                     blockStart = i;
 304  5
                     blockLength = 0;
 305   
 
 306   
                     // And drop into state start
 307   
 
 308  5
                     state = STATE_START;
 309   
 
 310  5
                     continue;
 311   
             }
 312   
 
 313   
         }
 314   
 
 315   
         // If get this far without seeing any variables, then just pass
 316   
         // the input back.
 317   
 
 318  4915
         if (!anySymbols)
 319  4910
             return text;
 320   
 
 321   
         // OK, to handle the end.  Couple of degenerate cases where
 322   
         // a ${...} was incomplete, so we adust the block length.
 323   
 
 324  5
         if (state == STATE_DOLLAR)
 325  0
             blockLength++;
 326   
 
 327  5
         if (state == STATE_COLLECT_SYMBOL_NAME)
 328  0
             blockLength += symbolLength + 2;
 329   
 
 330  5
         if (blockLength > 0)
 331  1
             result.append(buffer, blockStart, blockLength);
 332   
 
 333  5
         return result.toString();
 334   
     }
 335   
 
 336  5
     private String expandSymbol(String name, Location location)
 337   
     {
 338  5
         String value = valueForSymbol(name);
 339   
 
 340  5
         if (value != null)
 341  4
             return value;
 342   
 
 343  1
         _errorHandler.error(LOG, ImplMessages.noSuchSymbol(name), location, null);
 344   
 
 345  1
         return "${" + name + "}";
 346   
     }
 347   
 
 348  5
     public String valueForSymbol(String name)
 349   
     {
 350  5
         checkShutdown();
 351   
 
 352  5
         SymbolSource[] sources = getSymbolSources();
 353   
 
 354  5
         for (int i = 0; i < sources.length; i++)
 355   
         {
 356  7
             String value = sources[i].valueForSymbol(name);
 357   
 
 358  7
             if (value != null)
 359  4
                 return value;
 360   
         }
 361   
 
 362  1
         return null;
 363   
     }
 364   
 
 365  5
     private synchronized SymbolSource[] getSymbolSources()
 366   
     {
 367  5
         if (_variableSources != null)
 368  2
             return _variableSources;
 369   
 
 370  3
         List contributions = getConfiguration(SYMBOL_SOURCES);
 371   
 
 372  3
         Orderer o =
 373   
             new Orderer(
 374   
                 LogFactory.getLog(SYMBOL_SOURCES),
 375   
                 _errorHandler,
 376   
                 ImplMessages.symbolSourceContribution());
 377   
 
 378  3
         Iterator i = contributions.iterator();
 379  3
         while (i.hasNext())
 380   
         {
 381  8
             SymbolSourceContribution c = (SymbolSourceContribution) i.next();
 382   
 
 383  8
             o.add(c, c.getName(), c.getPrecedingNames(), c.getFollowingNames());
 384   
         }
 385   
 
 386  3
         List sources = o.getOrderedObjects();
 387   
 
 388  3
         int count = sources.size();
 389   
 
 390  3
         _variableSources = new SymbolSource[count];
 391   
 
 392  3
         for (int j = 0; j < count; j++)
 393   
         {
 394  8
             SymbolSourceContribution c = (SymbolSourceContribution) sources.get(j);
 395  8
             _variableSources[j] = c.getSource();
 396   
         }
 397   
 
 398  3
         return _variableSources;
 399   
     }
 400   
 
 401  96
     public void setShutdownCoordinator(ShutdownCoordinator coordinator)
 402   
     {
 403  96
         _shutdownCoordinator = coordinator;
 404   
     }
 405   
 
 406   
     /**
 407   
      * Invokes {@link ShutdownCoordinator#shutdown()}, then releases
 408   
      * the coordinator, modules and variable sources.
 409   
      */
 410  19
     public synchronized void shutdown()
 411   
     {
 412  19
         checkShutdown();
 413   
         // Allow service implementations and such to shutdown.
 414   
 
 415  18
         ShutdownCoordinator coordinatorService =
 416   
             (ShutdownCoordinator) getService("hivemind.ShutdownCoordinator",
 417   
                 ShutdownCoordinator.class);
 418   
 
 419  18
         coordinatorService.shutdown();
 420   
 
 421  18
         _shutdown = true;
 422   
 
 423   
         // Shutdown infrastructure items, such as proxies.
 424   
 
 425  18
         _shutdownCoordinator.shutdown();
 426   
 
 427  18
         _servicePoints = null;
 428  18
         _servicePointsByInterface = null;
 429  18
         _configurationPoints = null;
 430  18
         _shutdownCoordinator = null;
 431  18
         _variableSources = null;
 432  18
         _serviceModelFactories = null;
 433  18
         _threadEventNotifier = null;
 434   
     }
 435   
 
 436  3088
     private synchronized void checkShutdown()
 437   
     {
 438  3088
         if (_shutdown)
 439  2
             throw new ApplicationRuntimeException(HiveMindMessages.registryShutdown());
 440   
     }
 441   
 
 442  2459
     private void checkStarted()
 443   
     {
 444  2459
         if (_started)
 445  0
             throw new IllegalStateException(ImplMessages.registryAlreadyStarted());
 446   
     }
 447   
 
 448   
     /**
 449   
      * Starts up the Registry after all service and configuration points have been defined.
 450   
      * This locks down the Registry so that no further extension points may be added.
 451   
      * This method may only be invoked once.
 452   
      * 
 453   
      * <p>
 454   
      * In addition, the service <code>hivemind.Startup</code> is obtained and 
 455   
      * <code>run()</code> is invoked on it. This allows additional startup, provided
 456   
      * in the <code>hivemind.Startup</code> configuration point, to be executed.
 457   
      */
 458  96
     public void startup()
 459   
     {
 460  96
         checkStarted();
 461   
 
 462  96
         _started = true;
 463   
 
 464  96
         Runnable startup = (Runnable) getService("hivemind.Startup", Runnable.class);
 465   
 
 466  96
         startup.run();
 467   
     }
 468   
 
 469  981
     public synchronized ServiceModelFactory getServiceModelFactory(String name)
 470   
     {
 471  981
         if (_serviceModelFactories == null)
 472  96
             readServiceModelFactories();
 473   
 
 474  981
         ServiceModelFactory result = (ServiceModelFactory) _serviceModelFactories.get(name);
 475   
 
 476  981
         if (result == null)
 477  0
             throw new ApplicationRuntimeException(ImplMessages.unknownServiceModel(name));
 478   
 
 479  981
         return result;
 480   
     }
 481   
 
 482  96
     private void readServiceModelFactories()
 483   
     {
 484  96
         List l = getConfiguration("hivemind.ServiceModels");
 485   
 
 486  96
         _serviceModelFactories = new HashMap();
 487   
 
 488  96
         Iterator i = l.iterator();
 489   
 
 490  96
         while (i.hasNext())
 491   
         {
 492  384
             ServiceModelContribution smc = (ServiceModelContribution) i.next();
 493   
 
 494  384
             String name = smc.getName();
 495   
 
 496  384
             ServiceModelFactory old = (ServiceModelFactory) _serviceModelFactories.get(name);
 497   
 
 498  384
             if (old != null)
 499   
             {
 500  0
                 _errorHandler.error(
 501   
                     LOG,
 502   
                     ImplMessages.dupeServiceModelName(name, HiveMind.getLocation(old)),
 503   
                     HiveMind.getLocation(smc),
 504   
                     null);
 505   
 
 506  0
                 continue;
 507   
             }
 508   
 
 509  384
             _serviceModelFactories.put(name, smc.getFactory());
 510   
         }
 511   
     }
 512   
 
 513  802
     public synchronized void cleanupThread()
 514   
     {
 515  802
         if (_threadEventNotifier == null)
 516  6
             _threadEventNotifier =
 517   
                 (ThreadEventNotifier) getService("hivemind.ThreadEventNotifier",
 518   
                     ThreadEventNotifier.class);
 519   
 
 520  802
         _threadEventNotifier.fireThreadCleanup();
 521   
     }
 522   
 
 523  2
     public boolean containsConfiguration(String configurationId)
 524   
     {
 525  2
         checkShutdown();
 526   
 
 527  2
         return _configurationPoints.containsKey(configurationId);
 528   
     }
 529   
 
 530  2
     public boolean containsService(Class serviceInterface)
 531   
     {
 532  2
         checkShutdown();
 533   
         
 534  2
         List servicePoints = (List) _servicePointsByInterface.get(serviceInterface);
 535   
 
 536  2
         return size(servicePoints) == 1;
 537   
     }
 538   
 
 539  3
     public boolean containsService(String serviceId, Class serviceInterface)
 540   
     {
 541  3
         checkShutdown();
 542   
 
 543  3
         ServicePoint point = (ServicePoint) _servicePoints.get(serviceId);
 544   
 
 545  3
         if (point == null)
 546  1
             return false;
 547   
 
 548  2
         return point.getServiceInterface().equals(serviceInterface);
 549   
     }
 550   
 
 551  0
     public void setLocale(Locale locale)
 552   
     {
 553  0
         _locale = locale;
 554   
     }
 555   
 
 556  936
     public ErrorHandler getErrorHander()
 557   
     {
 558  936
         return _errorHandler;
 559   
     }
 560   
 
 561  5375
     public Translator getTranslator(String translator)
 562   
     {
 563  5375
         return _translatorManager.getTranslator(translator);
 564   
     }
 565   
 
 566  2
     private int size(Collection c)
 567   
     {
 568  2
         return c == null ? 0 : c.size();
 569   
     }
 570   
 
 571   
 }
 572