01: // Copyright 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.internal.services;
16:
17: import static java.lang.String.format;
18:
19: import java.lang.reflect.Constructor;
20: import java.lang.reflect.Modifier;
21:
22: import org.apache.tapestry.ioc.annotations.InjectService;
23: import org.apache.tapestry.ioc.services.ClassFab;
24: import org.apache.tapestry.ioc.services.ClassFactory;
25: import org.apache.tapestry.ioc.services.MethodSignature;
26: import org.apache.tapestry.services.Environment;
27: import org.apache.tapestry.services.EnvironmentalShadowBuilder;
28:
29: public class EnvironmentalShadowBuilderImpl implements
30: EnvironmentalShadowBuilder {
31: private final ClassFactory _classFactory;
32:
33: private final Environment _environment;
34:
35: public EnvironmentalShadowBuilderImpl(
36: @InjectService("ClassFactory")
37: ClassFactory classFactory,
38:
39: Environment environment) {
40: _classFactory = classFactory;
41: _environment = environment;
42: }
43:
44: public <T> T build(Class<T> serviceType) {
45: // TODO: Check that serviceType is an interface?
46:
47: Class proxyClass = buildProxyClass(serviceType);
48:
49: try {
50: Constructor cons = proxyClass.getConstructors()[0];
51:
52: Object raw = cons.newInstance(_environment, serviceType);
53:
54: return serviceType.cast(raw);
55: } catch (Exception ex) {
56: throw new RuntimeException(ex);
57: }
58: }
59:
60: private Class buildProxyClass(Class serviceType) {
61: ClassFab classFab = _classFactory.newClass(serviceType);
62:
63: classFab.addField("_environment", Environment.class);
64: classFab.addField("_serviceType", Class.class);
65:
66: classFab.addConstructor(new Class[] { Environment.class,
67: Class.class }, null,
68: "{ _environment = $1; _serviceType = $2; }");
69:
70: classFab
71: .addMethod(Modifier.PRIVATE, new MethodSignature(
72: serviceType, "_delegate", null, null),
73: "return ($r) _environment.peekRequired(_serviceType); ");
74:
75: classFab.proxyMethodsToDelegate(serviceType, "_delegate()",
76: format("<EnvironmentalProxy for %s>", serviceType
77: .getName()));
78:
79: return classFab.createClass();
80: }
81:
82: }
|