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