001: // Copyright 2006, 2007 The Apache Software Foundation
002: //
003: // Licensed under the Apache License, Version 2.0 (the "License");
004: // you may not use this file except in compliance with the License.
005: // You may obtain a copy of the License at
006: //
007: // http://www.apache.org/licenses/LICENSE-2.0
008: //
009: // Unless required by applicable law or agreed to in writing, software
010: // distributed under the License is distributed on an "AS IS" BASIS,
011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: // See the License for the specific language governing permissions and
013: // limitations under the License.
014:
015: package org.apache.tapestry.ioc;
016:
017: import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
018:
019: import java.lang.reflect.AnnotatedElement;
020: import java.util.Arrays;
021: import java.util.List;
022:
023: import org.apache.commons.logging.Log;
024: import org.apache.tapestry.ioc.annotations.SubModule;
025: import org.apache.tapestry.ioc.def.ModuleDef;
026: import org.apache.tapestry.ioc.internal.DefaultModuleDefImpl;
027: import org.apache.tapestry.ioc.internal.LogSourceImpl;
028: import org.apache.tapestry.ioc.internal.RegistryImpl;
029: import org.apache.tapestry.ioc.internal.RegistryWrapper;
030: import org.apache.tapestry.ioc.internal.services.ClassFactoryImpl;
031: import org.apache.tapestry.ioc.internal.util.OneShotLock;
032: import org.apache.tapestry.ioc.services.ClassFactory;
033: import org.apache.tapestry.ioc.services.TapestryIOCModule;
034:
035: /**
036: * Used to construct the IoC {@link org.apache.tapestry.ioc.Registry}. This class is <em>not</em>
037: * threadsafe. The Registry, once created, <em>is</em> threadsafe.
038: */
039: public final class RegistryBuilder {
040: private final OneShotLock _lock = new OneShotLock();
041:
042: /** Module defs, keyed on module id. */
043: final List<ModuleDef> _modules = newList();
044:
045: private final ClassLoader _classLoader;
046:
047: private final Log _log;
048:
049: private final LogSource _logSource;
050:
051: private final ClassFactory _classFactory;
052:
053: public RegistryBuilder() {
054: this (Thread.currentThread().getContextClassLoader());
055: }
056:
057: public RegistryBuilder(ClassLoader classLoader) {
058: this (classLoader, new LogSourceImpl());
059: }
060:
061: public RegistryBuilder(ClassLoader classLoader, LogSource logSource) {
062: _classLoader = classLoader;
063: _logSource = logSource;
064: _log = logSource.getLog(RegistryBuilder.class);
065:
066: // Make the ClassFactory appear to be a service inside TapestryIOCModule, even before that
067: // module exists.
068:
069: Log classFactoryLog = logSource.getLog(TapestryIOCModule.class
070: .getName()
071: + ".ClassFactory");
072:
073: _classFactory = new ClassFactoryImpl(_classLoader,
074: classFactoryLog);
075:
076: add(TapestryIOCModule.class);
077: }
078:
079: public void add(ModuleDef moduleDef) {
080: _lock.check();
081:
082: // TODO: Some way to ensure that duplicate modules are not being added.
083:
084: _modules.add(moduleDef);
085: }
086:
087: public void add(Class... moduleBuilderClasses) {
088: _lock.check();
089:
090: List<Class> queue = newList(Arrays.asList(moduleBuilderClasses));
091:
092: while (!queue.isEmpty()) {
093: Class c = queue.remove(0);
094:
095: ModuleDef def = new DefaultModuleDefImpl(c, _log,
096: _classFactory);
097: add(def);
098:
099: SubModule annotation = ((AnnotatedElement) c)
100: .getAnnotation(SubModule.class);
101:
102: if (annotation == null)
103: continue;
104:
105: for (Class sub : annotation.value())
106: queue.add(sub);
107: }
108: }
109:
110: public void add(String classname) {
111: _lock.check();
112:
113: try {
114: Class builderClass = Class.forName(classname, true,
115: _classLoader);
116:
117: add(builderClass);
118: } catch (ClassNotFoundException ex) {
119: throw new IllegalArgumentException(ex);
120: }
121: }
122:
123: public Registry build() {
124: _lock.lock();
125:
126: RegistryImpl registry = new RegistryImpl(_modules,
127: _classFactory, _logSource);
128:
129: return new RegistryWrapper(registry);
130: }
131:
132: public ClassLoader getClassLoader() {
133: _lock.check();
134:
135: return _classLoader;
136: }
137:
138: public Log getLog() {
139: _lock.check();
140:
141: return _log;
142: }
143: }
|