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 */
017package org.apache.activemq.ra;
018
019import java.lang.reflect.Method;
020
021import javax.jms.Message;
022import javax.jms.MessageListener;
023import javax.resource.ResourceException;
024import javax.resource.spi.endpoint.MessageEndpoint;
025import org.slf4j.Logger;
026import org.slf4j.LoggerFactory;
027
028/**
029 * @author <a href="mailto:michael.gaffney@panacya.com">Michael Gaffney </a>
030 */
031public 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}