| Constructor: |
public RegistryImpl(Collection<ModuleDef> moduleDefs,
ClassFactory classFactory,
LoggerSource loggerSource) {
this.loggerSource = loggerSource;
operationTracker = new PerThreadOperationTracker(loggerSource.getLogger(Registry.class));
final ServiceActivityTrackerImpl scoreboardAndTracker = new ServiceActivityTrackerImpl();
tracker = scoreboardAndTracker;
this.classFactory = classFactory;
Logger logger = loggerForBuiltinService(PERTHREAD_MANAGER_SERVICE_ID);
perthreadManager = new PerthreadManagerImpl(logger);
logger = loggerForBuiltinService(REGISTRY_SHUTDOWN_HUB_SERVICE_ID);
registryShutdownHub = new RegistryShutdownHubImpl(logger);
lifecycles.put("singleton", new SingletonServiceLifecycle());
registryShutdownHub.addRegistryShutdownListener(new RegistryShutdownListener()
{
public void registryDidShutdown()
{
scoreboardAndTracker.shutdown();
}
});
for (ModuleDef def : moduleDefs)
{
logger = this.loggerSource.getLogger(def.getLoggerName());
Module module = new ModuleImpl(this, tracker, def, classFactory, logger);
Set< ServiceDef > moduleServiceDefs = CollectionFactory.newSet();
for (String serviceId : def.getServiceIds())
{
ServiceDef serviceDef = module.getServiceDef(serviceId);
moduleServiceDefs.add(serviceDef);
allServiceDefs.add(serviceDef);
Module existing = serviceIdToModule.get(serviceId);
if (existing != null) throw new RuntimeException(IOCMessages.serviceIdConflict(serviceId, existing
.getServiceDef(serviceId), serviceDef));
serviceIdToModule.put(serviceId, module);
// The service is defined but will not have gone further than that.
tracker.define(serviceDef, Status.DEFINED);
for (Class marker : serviceDef.getMarkers())
InternalUtils.addToMapList(markerToServiceDef, marker, serviceDef);
}
moduleToServiceDefs.put(module, moduleServiceDefs);
}
addBuiltin(SERVICE_ACTIVITY_SCOREBOARD_SERVICE_ID, ServiceActivityScoreboard.class, scoreboardAndTracker);
addBuiltin(LOGGER_SOURCE_SERVICE_ID, LoggerSource.class, this.loggerSource);
addBuiltin(CLASS_FACTORY_SERVICE_ID, ClassFactory.class, this.classFactory);
addBuiltin(PERTHREAD_MANAGER_SERVICE_ID, PerthreadManager.class, perthreadManager);
addBuiltin(REGISTRY_SHUTDOWN_HUB_SERVICE_ID, RegistryShutdownHub.class, registryShutdownHub);
scoreboardAndTracker.startup();
SerializationSupport.setProvider(this);
}
Constructs the registry from a set of module definitions and other resources. Parameters:
moduleDefs - defines the modules (and builders, decorators, etc., within)
classFactory - TODO
loggerSource - used to obtain Logger instances
|
| Method from org.apache.tapestry5.ioc.internal.RegistryImpl Detail: |
public void addRegistryShutdownListener(RegistryShutdownListener listener) {
lock.check();
registryShutdownHub.addRegistryShutdownListener(listener);
}
|
public T autobuild(Class<T> clazz) {
Defense.notNull(clazz, "clazz");
final Constructor constructor = InternalUtils.findAutobuildConstructor(clazz);
if (constructor == null) throw new RuntimeException(IOCMessages.noAutobuildConstructor(clazz));
final ObjectLocator locator = this;
final OperationTracker tracker = this;
final Invokable< T > operation = new Invokable< T >()
{
public T invoke()
{
Throwable failure;
// An empty map, because when performing autobuilding outside the context of building a
// service, we don't have defaults for Log, service id, etc.
Map< Class, Object > empty = Collections.emptyMap();
try
{
InternalUtils.validateConstructorForAutobuild(constructor);
Object[] parameters = InternalUtils.calculateParametersForConstructor(constructor,
locator,
empty,
tracker);
Object result = constructor.newInstance(parameters);
InternalUtils.injectIntoFields(result, locator, tracker);
return clazz.cast(result);
}
catch (InvocationTargetException ite)
{
failure = ite.getTargetException();
}
catch (Exception ex)
{
failure = ex;
}
String description = classFactory.getConstructorLocation(constructor).toString();
throw new RuntimeException(IOCMessages.autobuildConstructorError(description, failure),
failure);
}
};
return invoke("Autobuilding instance of class " + clazz.getName(),
operation);
}
|
public void cleanupThread() {
lock.check();
perthreadManager.cleanup();
}
|
public String expandSymbols(String input) {
lock.check();
// Again, a bit of work to avoid instantiating the SymbolSource until absolutely necessary.
if (!InternalUtils.containsSymbols(input)) return input;
return getSymbolSource().expandSymbols(input);
}
|
public List<ServiceDecorator> findDecoratorsForService(ServiceDef serviceDef) {
lock.check();
assert serviceDef != null;
Logger logger = getServiceLogger(serviceDef.getServiceId());
Orderer< ServiceDecorator > orderer = new Orderer< ServiceDecorator >(logger);
for (Module module : moduleToServiceDefs.keySet())
{
Set< DecoratorDef > decorators = module.findMatchingDecoratorDefs(serviceDef);
if (decorators.isEmpty()) continue;
ServiceResources resources = new ServiceResourcesImpl(this, module, serviceDef, classFactory, logger);
for (DecoratorDef dd : decorators)
{
ServiceDecorator sd = dd.createDecorator(module, resources);
orderer.add(dd.getDecoratorId(), sd, dd.getConstraints());
}
}
return orderer.getOrdered();
}
|
public Map<K, V> getMappedConfiguration(ServiceDef serviceDef,
Class<K> keyType,
Class<V> objectType) {
lock.check();
// When the key type is String, then a case insensitive map is used for both cases.
final Map< K, V > result = newConfigurationMap(keyType);
Map< K, ContributionDef > keyToContribution = newConfigurationMap(keyType);
MappedConfiguration< K, V > configuration = new MappedConfiguration< K, V >()
{
public void add(K key, V value)
{
result.put(key, value);
}
};
for (Module m : moduleToServiceDefs.keySet())
addToMappedConfiguration(configuration, keyToContribution, keyType, objectType, serviceDef, m);
return result;
}
|
public T getObject(Class<T> objectType,
AnnotationProvider annotationProvider) {
return getObject(objectType, annotationProvider, this, null);
}
|
public T getObject(Class<T> objectType,
AnnotationProvider annotationProvider,
Module localModule) {
return getObject(objectType, annotationProvider, this, localModule);
}
|
public List<T> getOrderedConfiguration(ServiceDef serviceDef,
Class<T> objectType) {
lock.check();
String serviceId = serviceDef.getServiceId();
Logger logger = getServiceLogger(serviceId);
final Orderer< T > orderer = new Orderer< T >(logger);
OrderedConfiguration< T > configuration = new OrderedConfigurationToOrdererAdaptor< T >(orderer);
for (Module m : moduleToServiceDefs.keySet())
addToOrderedConfiguration(configuration, objectType, serviceDef, m);
// An ugly hack ... perhaps we should introduce a new builtin service so that this can be
// accomplished in the normal way?
if (serviceId.equals("MasterObjectProvider"))
{
ObjectProvider contribution = new ObjectProvider()
{
public < T > T provide(Class< T > objectType, AnnotationProvider annotationProvider, ObjectLocator locator)
{
return findServiceByMarkerAndType(objectType, annotationProvider, null);
}
};
configuration.add("ServiceByMarker", (T) contribution);
}
return orderer.getOrdered();
}
|
public T getService(Class<T> serviceInterface) {
lock.check();
List< String > serviceIds = findServiceIdsForInterface(serviceInterface);
if (serviceIds == null) serviceIds = Collections.emptyList();
switch (serviceIds.size())
{
case 0:
throw new RuntimeException(IOCMessages.noServiceMatchesType(serviceInterface));
case 1:
String serviceId = serviceIds.get(0);
return getService(serviceId, serviceInterface);
default:
Collections.sort(serviceIds);
throw new RuntimeException(IOCMessages.manyServiceMatches(serviceInterface, serviceIds));
}
}
|
public T getService(String serviceId,
Class<T> serviceInterface) {
lock.check();
T result = checkForBuiltinService(serviceId, serviceInterface);
if (result != null) return result;
// Checking serviceId and serviceInterface is overkill; they have been checked and rechecked
// all the way to here.
Module containingModule = locateModuleForService(serviceId);
return containingModule.getService(serviceId, serviceInterface);
}
|
public ServiceLifecycle getServiceLifecycle(String scope) {
lock.check();
ServiceLifecycle result = lifecycles.get(scope);
if (result == null)
{
ServiceLifecycleSource source = getService("ServiceLifecycleSource", ServiceLifecycleSource.class);
result = source.get(scope);
}
if (result == null) throw new RuntimeException(IOCMessages.unknownScope(scope));
return result;
}
|
public Logger getServiceLogger(String serviceId) {
Module module = serviceIdToModule.get(serviceId);
assert module != null;
return loggerSource.getLogger(module.getLoggerName() + "." + serviceId);
}
|
public Collection<T> getUnorderedConfiguration(ServiceDef serviceDef,
Class<T> objectType) {
lock.check();
final Collection< T > result = CollectionFactory.newList();
Configuration< T > configuration = new Configuration< T >()
{
public void add(T object)
{
result.add(object);
}
};
for (Module m : moduleToServiceDefs.keySet())
addToUnorderedConfiguration(configuration, objectType, serviceDef, m);
return result;
}
|
public T invoke(String description,
Invokable<T> operation) {
return operationTracker.invoke(description, operation);
}
|
public ClassFab newClass(Class serviceInterface) {
lock.check();
return classFactory.newClass(serviceInterface);
}
|
public void performRegistryStartup() {
eagerLoadLock.lock();
List< EagerLoadServiceProxy > proxies = CollectionFactory.newList();
for (Module m : moduleToServiceDefs.keySet())
m.collectEagerLoadServices(proxies);
// TAPESTRY-2267: Gather up all the proxies before instantiating any of them.
for (EagerLoadServiceProxy proxy : proxies)
proxy.eagerLoadService();
getService("RegistryStartup", Runnable.class).run();
cleanupThread();
}
It's not unreasonable for an eagerly-loaded service to decide to start a thread, at which point we raise issues
about improper publishing of the Registry instance from the RegistryImpl constructor. Moving eager loading of
services out to its own method should ensure thread safety. |
public Object provideServiceProxy(String serviceId) {
return getService(serviceId, Object.class);
}
|
public T proxy(Class<T> interfaceClass,
Class<? extends T> implementationClass) {
Defense.notNull(interfaceClass, "interfaceClass");
Defense.notNull(implementationClass, "implementationClass");
// TODO: Check really an interface
// TODO: Check impl class extends interfaceClass and is concrete
final ObjectCreator autobuildCreator = new ObjectCreator()
{
public Object createObject()
{
return autobuild(implementationClass);
}
};
ObjectCreator justInTime = new ObjectCreator()
{
private Object delegate;
public synchronized Object createObject()
{
if (delegate == null) delegate = autobuildCreator.createObject();
return delegate;
}
};
ClassFab cf = classFactory.newClass(interfaceClass);
String description = String.format("< Autobuild proxy %s(%s) >", implementationClass
.getName(), interfaceClass.getName());
return ClassFabUtils.createObjectCreatorProxy(cf, interfaceClass, justInTime, description);
}
|
public void run(String description,
Runnable operation) {
operationTracker.run(description, operation);
}
|
public synchronized void shutdown() {
lock.lock();
registryShutdownHub.fireRegistryDidShutdown();
SerializationSupport.clearProvider(this);
}
|