01: // Copyright 2006 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 java.lang.reflect.Constructor;
18:
19: import org.apache.tapestry.internal.InternalComponentResources;
20: import org.apache.tapestry.model.ComponentModel;
21: import org.apache.tapestry.runtime.Component;
22:
23: /**
24: * Implementation of {@link Instantiator} based on a class, a list of parameters to the class'
25: * constructor, and a instance of {@link org.apache.tapestry.internal.InternalComponentResources}.
26: * This implementation uses a little reflection to instantiate the instance.
27: */
28: public class ReflectiveInstantiator implements Instantiator {
29: private final ComponentModel _componentModel;
30:
31: private final Constructor _constructor;
32:
33: private final Object[] _constructorParameters;
34:
35: /**
36: * Creates a new instance that will instantiate the given class. The
37: *
38: * @param componentModel
39: * model defining the behavior of the component
40: * @param instanceClass
41: * class to instantiate
42: * @param parameters
43: * passed to the constructor; the first instance is ignored (and overriden) as the
44: * {@link org.apache.tapestry.internal.InternalComponentResources} instance.
45: */
46: ReflectiveInstantiator(ComponentModel componentModel,
47: Class instanceClass, Object[] constructorParameters) {
48: _componentModel = componentModel;
49: _constructorParameters = constructorParameters;
50:
51: _constructor = findConstructor(instanceClass,
52: constructorParameters.length);
53:
54: }
55:
56: @Override
57: public String toString() {
58: return String
59: .format("ReflectiveInstantiator[%s]", _constructor);
60: }
61:
62: static Constructor findConstructor(Class instanceClass,
63: int parameterCount) {
64: for (Constructor c : instanceClass.getConstructors()) {
65: if (c.getParameterTypes().length == parameterCount)
66: return c;
67: }
68:
69: throw new RuntimeException(ServicesMessages
70: .noConstructorFound(instanceClass));
71: }
72:
73: public Component newInstance(InternalComponentResources resources) {
74: // Hm. Is it faster to clone the parameters, or to synchronize this method?
75:
76: Object[] parameters = _constructorParameters.clone();
77:
78: parameters[0] = resources;
79:
80: try {
81: return (Component) _constructor.newInstance(parameters);
82: } catch (Exception ex) {
83: throw new RuntimeException(ex);
84: }
85: }
86:
87: public ComponentModel getModel() {
88: return _componentModel;
89: }
90:
91: }
|