001    /** 
002     * 
003     * Copyright 2004 Michael Gaffney
004     * 
005     * Licensed under the Apache License, Version 2.0 (the "License"); 
006     * you may not use this file except in compliance with the License. 
007     * 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     **/
018    package org.activemq.ra;
019    
020    import java.lang.reflect.Method;
021    
022    import javax.jms.Message;
023    import javax.jms.MessageListener;
024    import javax.resource.ResourceException;
025    import javax.resource.spi.endpoint.MessageEndpoint;
026    
027    /**
028     * @author <a href="mailto:michael.gaffney@panacya.com">Michael Gaffney </a>
029     */
030    public class MessageEndpointProxy implements MessageListener, MessageEndpoint {
031        
032        private static final MessageEndpointState ALIVE = new MessageEndpointAlive();
033        private static final MessageEndpointState DEAD = new MessageEndpointDead();
034        
035        private static int proxyCount = 0;    
036        private final int proxyID;    
037        private MessageEndpoint endpoint;
038        private MessageEndpointState state = ALIVE;
039    
040        private static int getID() {
041            return ++proxyCount;
042        }
043            
044        public MessageEndpointProxy(MessageEndpoint endpoint) {        
045            if (!(endpoint instanceof MessageListener)) {
046                throw new IllegalArgumentException("MessageEndpoint is not a MessageListener");            
047            }        
048            proxyID = getID();
049            this.endpoint = endpoint;
050        }
051    
052        public void beforeDelivery(Method method) throws NoSuchMethodException, ResourceException {
053            state.beforeDelivery(this, method);
054        }
055    
056        public void onMessage(Message message) {
057            state.onMessage(this, message);
058        }
059    
060        public void afterDelivery() throws ResourceException {
061            state.afterDelivery(this);
062        }
063    
064        public void release() {
065            state.release(this);
066        }
067    
068        public String toString() {
069            return "MessageEndpointProxy{ " +
070                    "proxyID: " + proxyID +
071                    ", endpoint: " + endpoint +
072                    " }";
073        }
074        
075        private abstract static class MessageEndpointState {
076    
077            public void beforeDelivery(MessageEndpointProxy proxy, Method method) throws NoSuchMethodException, ResourceException {
078                throw new IllegalStateException();
079            }
080    
081            public void onMessage(MessageEndpointProxy proxy, Message message) {
082                throw new IllegalStateException();
083            }
084    
085            public void afterDelivery(MessageEndpointProxy proxy) throws ResourceException {
086                throw new IllegalStateException();
087            }
088    
089            public void release(MessageEndpointProxy proxy) {
090                throw new IllegalStateException();
091            }
092            
093            protected final void transition(MessageEndpointProxy proxy, MessageEndpointState nextState) {
094                proxy.state = nextState;
095                nextState.enter(proxy);
096            }
097            
098            protected void enter(MessageEndpointProxy proxy) {            
099            }        
100        }
101        
102        private static class MessageEndpointAlive extends MessageEndpointState {
103    
104            public void beforeDelivery(MessageEndpointProxy proxy, Method method) throws NoSuchMethodException, ResourceException {            
105                try {
106                    proxy.endpoint.beforeDelivery(method);
107                } catch (NoSuchMethodException e) {
108                    transition(proxy, DEAD);
109                    throw e;
110                } catch (ResourceException e) {
111                    transition(proxy, DEAD);                
112                    throw e;
113                }            
114            }
115    
116            public void onMessage(MessageEndpointProxy proxy, Message message) {
117                ((MessageListener) proxy.endpoint).onMessage(message);
118            }
119    
120            public void afterDelivery(MessageEndpointProxy proxy) throws ResourceException {
121                try {
122                    proxy.endpoint.afterDelivery();
123                } catch (ResourceException e) {
124                    transition(proxy, DEAD);                
125                    throw e;
126                }                        
127            }
128    
129            public void release(MessageEndpointProxy proxy) {
130                transition(proxy, DEAD);                
131            }
132        }
133    
134        private static class MessageEndpointDead extends MessageEndpointState {
135    
136            protected void enter(MessageEndpointProxy proxy) {
137                proxy.endpoint.release();
138                proxy.endpoint = null;
139            }
140    
141            public void beforeDelivery(MessageEndpointProxy proxy, Method method) throws NoSuchMethodException, ResourceException {
142                throw new InvalidMessageEndpointException();
143            }
144    
145            public void onMessage(MessageEndpointProxy proxy, Message message) {
146                throw new InvalidMessageEndpointException();
147            }
148    
149            public void afterDelivery(MessageEndpointProxy proxy) throws ResourceException {
150                throw new InvalidMessageEndpointException();
151            }
152    
153            public void release(MessageEndpointProxy proxy) {
154                throw new InvalidMessageEndpointException();
155            }
156        }
157    }