001    // Copyright 2004, 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.hivemind.impl;
016    
017    import org.apache.commons.logging.Log;
018    import org.apache.hivemind.ApplicationRuntimeException;
019    import org.apache.hivemind.InterceptorStack;
020    import org.apache.hivemind.internal.Module;
021    import org.apache.hivemind.internal.ServiceInterceptorContribution;
022    import org.apache.hivemind.internal.ServicePoint;
023    import org.apache.hivemind.util.ToStringBuilder;
024    
025    /**
026     * Implementation of the {@link org.apache.hivemind.InterceptorStack} interface; localizes
027     * error checking in one place.
028     *
029     * @author Howard Lewis Ship
030     */
031    public final class InterceptorStackImpl implements InterceptorStack
032    {
033        private final Log _log;
034    
035        private ServiceInterceptorContribution _contribution;
036        private ServicePoint _sep;
037        private Class _interfaceClass;
038        private Object _top;
039    
040        public InterceptorStackImpl(Log log, ServicePoint sep, Object root)
041        {
042            _log = log;
043            _sep = sep;
044            _top = root;
045            _interfaceClass = sep.getServiceInterface();
046        }
047    
048        public String toString()
049        {
050            ToStringBuilder builder = new ToStringBuilder(this);
051            builder.append("contribution", _contribution);
052            builder.append("interfaceClass", _interfaceClass);
053            builder.append("top", _top);
054    
055            return builder.toString();
056        }
057    
058        public String getServiceExtensionPointId()
059        {
060            return _sep.getExtensionPointId();
061        }
062    
063        public Module getServiceModule()
064        {
065            return _sep.getModule();
066        }
067    
068        public Class getServiceInterface()
069        {
070            return _interfaceClass;
071        }
072    
073        public Object peek()
074        {
075            return _top;
076        }
077    
078        public void push(Object interceptor)
079        {
080            if (interceptor == null)
081                throw new ApplicationRuntimeException(
082                    ImplMessages.nullInterceptor(_contribution, _sep),
083                    _contribution.getLocation(),
084                    null);
085    
086            if (!_interfaceClass.isAssignableFrom(interceptor.getClass()))
087                throw new ApplicationRuntimeException(
088                    ImplMessages.interceptorDoesNotImplementInterface(
089                        interceptor,
090                        _contribution,
091                        _sep,
092                        _interfaceClass),
093                    _contribution.getLocation(),
094                    null);
095    
096            _top = interceptor;
097        }
098    
099        /**
100         * Invoked to process the next interceptor contribution; these should
101         * be processed in ascending order.
102         * 
103         */
104    
105        public void process(ServiceInterceptorContribution contribution)
106        {
107            if (_log.isDebugEnabled())
108                _log.debug("Applying interceptor factory " + contribution.getFactoryServiceId());
109    
110            // And now we can finally do this!
111    
112            try
113            {
114                _contribution = contribution;
115    
116                contribution.createInterceptor(this);
117            }
118            finally
119            {
120                _contribution = null;
121            }
122        }
123    
124            public Log getServiceLog()
125            {
126                    return _log;
127            }
128    }