001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.activemq.ra;
018    
019    import java.lang.reflect.Method;
020    
021    import javax.jms.Message;
022    import javax.jms.MessageListener;
023    import javax.resource.ResourceException;
024    import javax.resource.spi.endpoint.MessageEndpoint;
025    import org.slf4j.Logger;
026    import org.slf4j.LoggerFactory;
027    
028    /**
029     * @author <a href="mailto:michael.gaffney@panacya.com">Michael Gaffney </a>
030     */
031    public class MessageEndpointProxy implements MessageListener, MessageEndpoint {
032    
033        private static final MessageEndpointState ALIVE = new MessageEndpointAlive();
034        private static final MessageEndpointState DEAD = new MessageEndpointDead();
035        private static final Logger LOG = LoggerFactory.getLogger(MessageEndpointProxy.class);
036    
037        private static int proxyCount;
038        private final int proxyID;
039    
040        private final MessageEndpoint endpoint;
041        private final MessageListener messageListener;
042        private MessageEndpointState state = ALIVE;
043    
044        public MessageEndpointProxy(MessageEndpoint endpoint) {
045            if (!(endpoint instanceof MessageListener)) {
046                throw new IllegalArgumentException("MessageEndpoint is not a MessageListener");
047            }
048            messageListener = (MessageListener)endpoint;
049            proxyID = getID();
050            this.endpoint = endpoint;
051        }
052    
053        private static int getID() {
054            return ++proxyCount;
055        }
056    
057        public void beforeDelivery(Method method) throws NoSuchMethodException, ResourceException {
058            LOG.trace("Invoking MessageEndpoint.beforeDelivery()");
059            state.beforeDelivery(this, method);
060        }
061    
062        public void onMessage(Message message) {
063            LOG.trace("Invoking MessageEndpoint.onMethod()");
064            state.onMessage(this, message);
065        }
066    
067        public void afterDelivery() throws ResourceException {
068            LOG.trace("Invoking MessageEndpoint.afterDelivery()");
069            state.afterDelivery(this);
070        }
071    
072        public void release() {
073            LOG.trace("Invoking MessageEndpoint.release()");
074            state.release(this);
075        }
076    
077        public String toString() {
078            return "MessageEndpointProxy{ " + "proxyID: " + proxyID + ", endpoint: " + endpoint + " }";
079        }
080    
081        private abstract static class MessageEndpointState {
082    
083            public void beforeDelivery(MessageEndpointProxy proxy, Method method) throws NoSuchMethodException, ResourceException {
084                throw new IllegalStateException();
085            }
086    
087            public void onMessage(MessageEndpointProxy proxy, Message message) {
088                throw new IllegalStateException();
089            }
090    
091            public void afterDelivery(MessageEndpointProxy proxy) throws ResourceException {
092                throw new IllegalStateException();
093            }
094    
095            public void release(MessageEndpointProxy proxy) {
096                throw new IllegalStateException();
097            }
098    
099            protected final void transition(MessageEndpointProxy proxy, MessageEndpointState nextState) {
100                proxy.state = nextState;
101                nextState.enter(proxy);
102            }
103    
104            protected void enter(MessageEndpointProxy proxy) {
105            }
106        }
107    
108        private static class MessageEndpointAlive extends MessageEndpointState {
109    
110            public void beforeDelivery(MessageEndpointProxy proxy, Method method) throws NoSuchMethodException, ResourceException {
111                try {
112                    proxy.endpoint.beforeDelivery(method);
113                } catch (NoSuchMethodException e) {
114                    transition(proxy, DEAD);
115                    throw e;
116                } catch (ResourceException e) {
117                    transition(proxy, DEAD);
118                    throw e;
119                }
120            }
121    
122            public void onMessage(MessageEndpointProxy proxy, Message message) {
123                proxy.messageListener.onMessage(message);
124            }
125    
126            public void afterDelivery(MessageEndpointProxy proxy) throws ResourceException {
127                try {
128                    proxy.endpoint.afterDelivery();
129                } catch (ResourceException e) {
130                    transition(proxy, DEAD);
131                    throw e;
132                }
133            }
134    
135            public void release(MessageEndpointProxy proxy) {
136                transition(proxy, DEAD);
137            }
138        }
139    
140        private static class MessageEndpointDead extends MessageEndpointState {
141    
142            protected void enter(MessageEndpointProxy proxy) {
143                proxy.endpoint.release();
144            }
145    
146            public void beforeDelivery(MessageEndpointProxy proxy, Method method) throws NoSuchMethodException, ResourceException {
147                throw new InvalidMessageEndpointException();
148            }
149    
150            public void onMessage(MessageEndpointProxy proxy, Message message) {
151                throw new InvalidMessageEndpointException();
152            }
153    
154            public void afterDelivery(MessageEndpointProxy proxy) throws ResourceException {
155                throw new InvalidMessageEndpointException();
156            }
157    
158            public void release(MessageEndpointProxy proxy) {
159                throw new InvalidMessageEndpointException();
160            }
161        }
162    }