01: // Copyright 2006, 2007 The Apache Software Foundation
02: //
03: // Licensed under the Apache License, Version 2.0 (the "License");
04: // you may not use this file except in compliance with the License.
05: // You may obtain a copy of the License at
06: //
07: // http://www.apache.org/licenses/LICENSE-2.0
08: //
09: // 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.tapestry.ioc.internal.services;
16:
17: import java.lang.reflect.Modifier;
18:
19: import org.apache.tapestry.ioc.annotations.InjectService;
20: import org.apache.tapestry.ioc.services.ClassFab;
21: import org.apache.tapestry.ioc.services.ClassFactory;
22: import org.apache.tapestry.ioc.services.MethodIterator;
23: import org.apache.tapestry.ioc.services.MethodSignature;
24: import org.apache.tapestry.ioc.services.StrategyBuilder;
25: import org.apache.tapestry.ioc.util.BodyBuilder;
26: import org.apache.tapestry.ioc.util.StrategyRegistry;
27:
28: public class StrategyBuilderImpl implements StrategyBuilder {
29: private final ClassFactory _classFactory;
30:
31: public StrategyBuilderImpl(@InjectService("ClassFactory")
32: ClassFactory classFactory) {
33: _classFactory = classFactory;
34: }
35:
36: public <S> S build(StrategyRegistry<S> registry) {
37: Class<S> interfaceClass = registry.getAdapterType();
38:
39: // TODO: Could cache the implClass by interfaceClass ...
40:
41: Class implClass = createImplClass(interfaceClass);
42:
43: try {
44: Object raw = implClass.getConstructors()[0]
45: .newInstance(registry);
46:
47: return interfaceClass.cast(raw);
48: } catch (Exception ex) {
49: throw new RuntimeException(ex);
50: }
51: }
52:
53: private Class createImplClass(Class interfaceClass) {
54: ClassFab cf = _classFactory.newClass(interfaceClass);
55:
56: String interfaceClassName = interfaceClass.getName();
57:
58: cf.addField("_registry", Modifier.PRIVATE | Modifier.FINAL,
59: StrategyRegistry.class);
60: cf.addConstructor(new Class[] { StrategyRegistry.class }, null,
61: "_registry = $1;");
62:
63: BodyBuilder builder = new BodyBuilder();
64:
65: MethodIterator mi = new MethodIterator(interfaceClass);
66:
67: while (mi.hasNext()) {
68: MethodSignature sig = mi.next();
69:
70: // TODO: Checks for methods that don't have at least one parameter, or don't have a
71: // compatible 1st parameter. Currently, we'll get a Javassist exception.
72:
73: builder.clear();
74: builder.begin();
75:
76: builder.addln("Object selector = $1;");
77: builder
78: .addln(
79: "%s adapter = (%<s) _registry.getByInstance(selector);",
80: interfaceClassName);
81: builder.addln("return ($r) adapter.%s($$);", sig.getName());
82:
83: builder.end();
84:
85: cf.addMethod(Modifier.PUBLIC, sig, builder.toString());
86:
87: }
88:
89: if (!mi.getToString())
90: cf.addToString(String.format("<Strategy for %s>",
91: interfaceClassName));
92:
93: return cf.createClass();
94: }
95: }
|