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;
16:
17: import org.apache.commons.logging.Log;
18: import org.apache.tapestry.ioc.ObjectCreator;
19: import org.apache.tapestry.ioc.def.ServiceDef;
20:
21: /**
22: * Decorator for {@link org.apache.tapestry.ioc.ObjectCreator} that ensures the service is only
23: * created once. This detects a situation where the service builder for a service directly or
24: * indirectly invokes methods on the service itself. This would show up as a second call up the
25: * ServiceCreator stack injected into the proxy, potentially leading to endless recursion. We try to
26: * identify that recursion and produce a useable exception report.
27: */
28: public class RecursiveServiceCreationCheckWrapper implements
29: ObjectCreator {
30: private final ServiceDef _serviceDef;
31:
32: private final ObjectCreator _delegate;
33:
34: private final Log _log;
35:
36: private boolean _locked;
37:
38: public RecursiveServiceCreationCheckWrapper(ServiceDef serviceDef,
39: ObjectCreator delegate, Log log) {
40: _serviceDef = serviceDef;
41: _delegate = delegate;
42: _log = log;
43: }
44:
45: /**
46: * We could make this method synchronized, but in the context of creating a service for a proxy,
47: * it will already be synchronized (inside the proxy).
48: */
49: public Object createObject() {
50: if (_locked)
51: throw new IllegalStateException(IOCMessages
52: .recursiveServiceBuild(_serviceDef));
53:
54: // Set the lock, to ensure that recursive service construction fails.
55:
56: _locked = true;
57:
58: try {
59: return _delegate.createObject();
60: } catch (RuntimeException ex) {
61: _log.error(IOCMessages.serviceConstructionFailed(
62: _serviceDef, ex), ex);
63:
64: // Release the lock on failure; the service is now in an unknown state, but we may
65: // be able to continue from here.
66:
67: _locked = false;
68:
69: throw ex;
70: }
71:
72: }
73: }
|