KickJava   Java API By Example, From Geeks To Geeks.

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


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.lang.reflect.Constructor JavaDoc;
18 import java.lang.reflect.Modifier JavaDoc;
19
20 import org.apache.hivemind.ApplicationRuntimeException;
21 import org.apache.hivemind.events.RegistryShutdownListener;
22 import org.apache.hivemind.impl.ConstructableServicePoint;
23 import org.apache.hivemind.impl.ProxyBuilder;
24 import org.apache.hivemind.internal.ServicePoint;
25 import org.apache.hivemind.service.BodyBuilder;
26 import org.apache.hivemind.service.ClassFab;
27 import org.apache.hivemind.service.MethodSignature;
28
29 /**
30  * Subclass of {@link org.apache.hivemind.impl.servicemodel.AbstractServiceModelImpl} which supports
31  * creation of a singleton service proxy (deferring the actual construction of the service until
32  * absolutely necessary). This is used with the singleton service type, which is the default.
33  *
34  * @author Howard Lewis Ship
35  */

36 public final class SingletonServiceModel extends AbstractServiceModelImpl
37 {
38     /**
39      * Name of a method in the deferred proxy that is used to obtain the constructed service.
40      */

41     protected static final String JavaDoc SERVICE_ACCESSOR_METHOD_NAME = "_service";
42
43     private Object JavaDoc _serviceProxy;
44
45     private SingletonInnerProxy _innerProxy;
46
47     private Object JavaDoc _constructedService;
48
49     public SingletonServiceModel(ConstructableServicePoint servicePoint)
50     {
51         super(servicePoint);
52     }
53
54     public synchronized Object JavaDoc getService()
55     {
56         if (_serviceProxy == null)
57             _serviceProxy = createSingletonProxy();
58
59         return _serviceProxy;
60     }
61
62     /**
63      * This is invoked by the proxy to create the actual implementation.
64      */

65     public synchronized Object JavaDoc getActualServiceImplementation()
66     {
67         if (_constructedService == null)
68         {
69             _constructedService = constructServiceImplementation();
70             registerWithShutdownCoordinator(_constructedService);
71         }
72
73         // The inner proxy needs the service to implement the service interface.
74
// For bean services (not interface services) with no interceptors,
75
// the implementation may be the bean provided by the factory ... which
76
// does not implement the service interface (which was created at runtime).
77
// So we introduce a "bridge" between the two.
78

79         Class JavaDoc serviceInterface = getServicePoint().getServiceInterface();
80
81         if (!serviceInterface.isInstance(_constructedService))
82             _constructedService = constructBridgeProxy(_constructedService);
83
84         return _constructedService;
85     }
86
87     /**
88      * Creates a proxy class for the service and then construct the class itself.
89      */

90     private Object JavaDoc createSingletonProxy()
91     {
92         if (_log.isDebugEnabled())
93             _log.debug("Creating SingletonProxy for service "
94                     + getServicePoint().getExtensionPointId());
95
96         try
97         {
98
99             // Create the outer proxy, the one visible to client code (including
100
// other services). It is dependent on an inner proxy.
101

102             Class JavaDoc proxyClass = createSingletonProxyClass();
103
104             // Create the inner proxy, whose job is to replace itself
105
// when the first service method is invoked.
106

107             Class JavaDoc innerProxyClass = createInnerProxyClass(proxyClass);
108
109             // Create the outer proxy.
110

111             Constructor JavaDoc co = proxyClass.getConstructor(new Class JavaDoc[] { String JavaDoc.class });
112
113             Object JavaDoc result = co.newInstance(new Object JavaDoc[] { getServicePoint().getExtensionPointId() });
114             
115             // The inner proxy's construct invokes a method on the
116
// outer proxy to connect the two.
117

118             Constructor JavaDoc c = innerProxyClass.getConstructor(new Class JavaDoc[]
119             { String JavaDoc.class, proxyClass, getClass() });
120
121             _innerProxy = (SingletonInnerProxy) c.newInstance(new Object JavaDoc[]
122             { getServicePoint().getExtensionPointId(), result, this });
123
124             RegistryShutdownListener asListener = (RegistryShutdownListener) result;
125
126             getServicePoint().addRegistryShutdownListener(asListener);
127
128             return result;
129         }
130         catch (Exception JavaDoc ex)
131         {
132             throw new ApplicationRuntimeException(ex);
133         }
134
135     }
136
137     /**
138      * Creates a class that implements the service interface. Implements a private synchronized
139      * method, _service(), that constructs the service as needed, and has each service interface
140      * method re-invoke on _service(). Adds a toString() method if the service interface does not
141      * define toString().
142      */

143     private Class JavaDoc createSingletonProxyClass()
144     {
145         ConstructableServicePoint servicePoint = getServicePoint();
146
147         ProxyBuilder proxyBuilder = new ProxyBuilder("SingletonProxy", servicePoint.getModule(),
148                 servicePoint.getServiceInterface(), servicePoint.getDeclaredInterface(), true);
149
150         ClassFab classFab = proxyBuilder.getClassFab();
151
152         Class JavaDoc serviceInterface = servicePoint.getServiceInterface();
153
154         // This will initally be the inner proxy, then switch over to the
155
// service implementation.
156

157         classFab.addField("_inner", serviceInterface);
158         classFab.addField("_shutdown", boolean.class);
159         if (!RegistryShutdownListener.class.isAssignableFrom(serviceInterface))
160         {
161             classFab.addInterface(RegistryShutdownListener.class);
162
163             classFab.addMethod(Modifier.PUBLIC | Modifier.FINAL, new MethodSignature(void.class,
164                     "registryDidShutdown", null, null), "{ _shutdown = true; }");
165         }
166         classFab.addMethod(
167                 Modifier.PUBLIC | Modifier.SYNCHRONIZED | Modifier.FINAL,
168                 new MethodSignature(void.class, "_setInner", new Class JavaDoc[]
169                 { serviceInterface }, null),
170                 "{ _inner = $1; }");
171
172         BodyBuilder builder = new BodyBuilder();
173         builder.begin();
174         builder.addln("if (_shutdown)");
175         builder.begin();
176         builder.addln("_inner = null;");
177         builder.addln("throw org.apache.hivemind.HiveMind#createRegistryShutdownException();");
178         builder.end();
179
180         builder.addln("return _inner;");
181         builder.end();
182
183         classFab.addMethod(Modifier.PRIVATE, new MethodSignature(serviceInterface, "_getInner",
184                 null, null), builder.toString());
185
186         proxyBuilder.addServiceMethods("_getInner()");
187
188         return classFab.createClass();
189     }
190
191     private Class JavaDoc createInnerProxyClass(Class JavaDoc deferredProxyClass)
192     {
193         ServicePoint servicePoint = getServicePoint();
194
195         Class JavaDoc serviceInterface = servicePoint.getServiceInterface();
196         
197         ProxyBuilder builder = new ProxyBuilder("InnerProxy", servicePoint.getModule(),
198                 serviceInterface, servicePoint.getDeclaredInterface(), false);
199
200         ClassFab classFab = builder.getClassFab();
201
202         classFab.addField("_deferredProxy", deferredProxyClass);
203         classFab.addField("_service", serviceInterface);
204         classFab.addField("_serviceModel", getClass());
205
206         BodyBuilder body = new BodyBuilder();
207
208         // The constructor remembers the outer proxy and registers itself
209
// with the outer proxy.
210

211         body.begin();
212
213         body.addln("this($1);");
214         body.addln("_deferredProxy = $2;");
215         body.addln("_serviceModel = $3;");
216         body.addln("_deferredProxy._setInner(this);");
217
218         body.end();
219
220         classFab.addConstructor(new Class JavaDoc[]
221         { String JavaDoc.class, deferredProxyClass, getClass() }, null, body.toString());
222
223         // Method _service() will look up the service implementation,
224
// then update the deferred proxy to go directly to the
225
// service implementation, bypassing itself!
226

227         body.clear();
228         body.begin();
229
230         body.add("if (_service == null)");
231         body.begin();
232
233         body.add("_service = (");
234         body.add(serviceInterface.getName());
235         body.addln(") _serviceModel.getActualServiceImplementation();");
236
237         body.add("_deferredProxy._setInner(_service);");
238
239         body.end();
240
241         body.add("return _service;");
242
243         body.end();
244
245         classFab.addMethod(
246                 Modifier.PRIVATE | Modifier.FINAL | Modifier.SYNCHRONIZED,
247                 new MethodSignature(serviceInterface, "_service", null, null),
248                 body.toString());
249
250         builder.addServiceMethods("_service()");
251
252         // Build the implementation of interface SingletonInnerProxy
253

254         body.clear();
255         body.begin();
256
257         body.add("_service();");
258
259         body.end();
260
261         classFab.addMethod(Modifier.PUBLIC | Modifier.FINAL, new MethodSignature(void.class,
262                 "_instantiateServiceImplementation", null, null), body.toString());
263
264         classFab.addInterface(SingletonInnerProxy.class);
265
266         return classFab.createClass();
267     }
268
269     public void instantiateService()
270     {
271         // Ensure that the outer and inner proxies have been created
272

273         getService();
274
275         // Force the inner proxy to resolve the service and install the result into
276
// the outer proxy.
277

278         _innerProxy._instantiateServiceImplementation();
279     }
280
281 }
Popular Tags