KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > hivemind > impl > servicemodel > AbstractServiceModelImpl


1 // Copyright 2004, 2005 The Apache Software Foundation
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// 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.hivemind.impl.servicemodel;
16
17 import java.util.List JavaDoc;
18
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21 import org.apache.hivemind.ApplicationRuntimeException;
22 import org.apache.hivemind.HiveMind;
23 import org.apache.hivemind.ShutdownCoordinator;
24 import org.apache.hivemind.definition.ImplementationConstructionContext;
25 import org.apache.hivemind.definition.ImplementationConstructor;
26 import org.apache.hivemind.definition.ImplementationDefinition;
27 import org.apache.hivemind.definition.InterceptorDefinition;
28 import org.apache.hivemind.events.RegistryShutdownListener;
29 import org.apache.hivemind.impl.ConstructableServicePoint;
30 import org.apache.hivemind.impl.InterceptorStackImpl;
31 import org.apache.hivemind.impl.ProxyBuilder;
32 import org.apache.hivemind.internal.ImplementationConstructionContextImpl;
33 import org.apache.hivemind.internal.Module;
34 import org.apache.hivemind.internal.RegistryInfrastructure;
35 import org.apache.hivemind.internal.ServiceModel;
36 import org.apache.hivemind.service.ClassFab;
37 import org.apache.hivemind.util.ConstructorUtils;
38
39 /**
40  * Base class for implementing {@link org.apache.hivemind.internal.ServiceModel}.
41  *
42  * @author Howard Lewis Ship
43  */

44 public abstract class AbstractServiceModelImpl implements ServiceModel
45 {
46     /**
47      * This log is created from the log's service id, which is the appropriate place to log any
48      * messages related to creating (or managing) the service implementation, proxy, etc. Subclasses
49      * should make use of this Log as well.
50      */

51     protected final Log _log;
52
53     private ConstructableServicePoint _servicePoint;
54
55     /** @since 1.1 */
56     private Class JavaDoc _bridgeProxyClass;
57
58     public AbstractServiceModelImpl(ConstructableServicePoint servicePoint)
59     {
60         _log = LogFactory.getLog(servicePoint.getExtensionPointId());
61
62         _servicePoint = servicePoint;
63     }
64
65     protected Object JavaDoc addInterceptors(Object JavaDoc core)
66     {
67         List JavaDoc interceptors = _servicePoint.getOrderedInterceptorContributions();
68
69         int count = interceptors == null ? 0 : interceptors.size();
70
71         if (count == 0)
72             return core;
73
74         InterceptorStackImpl stack = new InterceptorStackImpl(_log, _servicePoint, core);
75
76         // They are sorted into runtime execution order. Since we build from the
77
// core service impl outwarads, we have to reverse the runtime execution
78
// order to get the build order.
79
// That is, if user expects interceptors in order A B C (perhaps using
80
// the rules: A before B, C after B).
81
// Then that's the order for interceptors list: A B C
82
// To get that runtime execution order, we wrap C around the core,
83
// wrap B around C, and wrap A around B.
84

85         for (int i = count - 1; i >= 0; i--)
86         {
87             InterceptorDefinition id = (InterceptorDefinition) interceptors
88                     .get(i);
89
90             stack.process(id);
91         }
92
93         // Whatever's on top is the final service.
94

95         return stack.peek();
96     }
97
98     /**
99      * Constructs the core service implementation (by invoking the
100      * {@link ImplementationConstructor}), and checks that the result is non-null and
101      * assignable to the service interface.
102      */

103     protected Object JavaDoc constructCoreServiceImplementation()
104     {
105         if (_log.isDebugEnabled())
106             _log.debug("Constructing core service implementation for service "
107                     + _servicePoint.getExtensionPointId());
108
109         Class JavaDoc serviceInterface = _servicePoint.getServiceInterface();
110         Class JavaDoc declaredInterface = _servicePoint.getDeclaredInterface();
111
112         ImplementationDefinition implementationDefinition = _servicePoint.getImplementationDefinition();
113         ImplementationConstructor constructor = implementationDefinition.getServiceConstructor();
114         // Get a reference to the module that provided the implementation
115
String JavaDoc definingModuleId = implementationDefinition.getModuleId();
116         
117         Module definingModule = getRegistry().getModule(definingModuleId);
118         ImplementationConstructionContext context = new ImplementationConstructionContextImpl(definingModule,
119                 _servicePoint);
120         Object JavaDoc result = constructor.constructCoreServiceImplementation(context);
121
122         if (result == null)
123             throw new ApplicationRuntimeException(ServiceModelMessages
124                     .factoryReturnedNull(_servicePoint), constructor.getLocation(), null);
125
126         // The factory should provice something that either implements the service interface
127
// or the declared interface. Again, they are normally the same, but with services
128
// defined in terms of a class (not an interface), the service interface is
129
// synthetic, and the declared interface is the actual class.
130

131         if (!(serviceInterface.isInstance(result) || declaredInterface.isInstance(result)))
132             throw new ApplicationRuntimeException(ServiceModelMessages.factoryWrongInterface(
133                     _servicePoint,
134                     result,
135                     serviceInterface), constructor.getLocation(), null);
136
137         HiveMind.setLocation(result, constructor.getLocation());
138
139         return result;
140     }
141
142     private RegistryInfrastructure getRegistry()
143     {
144         return _servicePoint.getModule().getRegistry();
145     }
146
147     /**
148      * Constructs the service implementation; this is invoked from
149      * {@link org.apache.hivemind.internal.ServicePoint#getService(Class)} (for singletons), or from
150      * the generated deferrable proxy (for most service models). Primarily, invokes
151      * {@link #constructNewServiceImplementation()} from within a block that checks for recursive
152      * builds.
153      */

154
155     protected Object JavaDoc constructServiceImplementation()
156     {
157         Object JavaDoc result = constructNewServiceImplementation();
158
159         // After succesfully building, we don't need
160
// some of the definition stuff again.
161

162         _servicePoint.clearConstructorInformation();
163
164         return result;
165     }
166
167     /**
168      * Constructs a new implementation of the service, starting with a core implementation, then
169      * adding any interceptors.
170      */

171     protected Object JavaDoc constructNewServiceImplementation()
172     {
173         try
174         {
175             Object JavaDoc core = constructCoreServiceImplementation();
176
177             Object JavaDoc intercepted = addInterceptors(core);
178
179             return intercepted;
180         }
181         catch (Exception JavaDoc ex)
182         {
183             throw new ApplicationRuntimeException(ServiceModelMessages.unableToConstructService(
184                     _servicePoint,
185                     ex), ex);
186         }
187
188     }
189
190     public ConstructableServicePoint getServicePoint()
191     {
192         return _servicePoint;
193     }
194
195     /**
196      * Need to bridge from the service interface to the actual type.
197      *
198      * @since 1.1
199      */

200     protected Object JavaDoc constructBridgeProxy(Object JavaDoc service)
201     {
202         Class JavaDoc bridgeProxyClass = getBridgeProxyClass(service);
203
204         return ConstructorUtils.invokeConstructor(bridgeProxyClass, new Object JavaDoc[]
205         { getServicePoint().getExtensionPointId(), service });
206     }
207
208     /**
209      * Factored out of {@link #constructBridgeProxy(Object)} to keep the synchronized block as small
210      * as possible.
211      *
212      * @since 1.2
213      */

214     private synchronized Class JavaDoc getBridgeProxyClass(Object JavaDoc service)
215     {
216         if (_bridgeProxyClass == null)
217             _bridgeProxyClass = constructBridgeProxyClass(service);
218
219         return _bridgeProxyClass;
220     }
221
222     /**
223      * Assumes that the factory will keep cranking out instances of the same class.
224      *
225      * @since 1.1
226      */

227
228     private Class JavaDoc constructBridgeProxyClass(Object JavaDoc service)
229     {
230         ProxyBuilder builder = new ProxyBuilder("BridgeProxy", getServicePoint().getModule(),
231                 getServicePoint().getServiceInterface(), getServicePoint().getDeclaredInterface(), false);
232
233         ClassFab cf = builder.getClassFab();
234
235         Class JavaDoc serviceType = service.getClass();
236
237         cf.addField("_service", serviceType);
238
239         cf.addConstructor(new Class JavaDoc[]
240         { String JavaDoc.class, serviceType }, null, "{ this($1); _service = $2; }");
241
242         builder.addServiceMethods("_service");
243
244         return cf.createClass();
245     }
246
247     /**
248      * Invoked after creating a service implementation object; if the object implements
249      * {@link org.apache.hivemind.events.RegistryShutdownListener}, then the object is added as a
250      * listener.
251      *
252      * @param service
253      * the service implementation
254      * @see ShutdownCoordinator
255      * @since 1.2
256      */

257     protected void registerWithShutdownCoordinator(Object JavaDoc service)
258     {
259         if (service instanceof RegistryShutdownListener)
260         {
261             ShutdownCoordinator coordinator = ((ShutdownCoordinator) getServicePoint().getModule()
262                     .getService(ShutdownCoordinator.class));
263
264             RegistryShutdownListener asListener = (RegistryShutdownListener) service;
265             coordinator.addRegistryShutdownListener(asListener);
266         }
267     }
268 }
Popular Tags