001    /*
002     * Copyright (C) The Apache Software Foundation. All rights reserved.
003     *
004     * This software is published under the terms of the Apache Software License
005     * version 1.1, a copy of which has been included with this distribution in
006     * the LICENSE file.
007     * 
008     * $Id: ManagerServlet.java 155459 2005-02-26 13:24:44Z dirkv $
009     */
010    package org.apache.commons.messagelet;
011    
012    import java.net.URL;
013    import java.util.Iterator;
014    
015    import javax.jms.JMSException;
016    import javax.servlet.GenericServlet;
017    import javax.servlet.ServletException;
018    import javax.servlet.ServletRequest;
019    import javax.servlet.ServletResponse;
020    
021    import org.apache.commons.messagelet.model.SubscriptionDigester;
022    import org.apache.commons.messagelet.model.SubscriptionList;
023    import org.apache.commons.messenger.Messenger;
024    import org.apache.commons.messenger.MessengerManager;
025    
026    /** <p><code>ManagerServlet</code> manages the 
027      * initialisation and destruction of the Messenger connections
028      * and use of MessageListener beans for a given ServletContext.</p>
029      *
030      * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
031      * @version $Revision: 155459 $
032      */
033    public class ManagerServlet extends GenericServlet {
034    
035        /** Should HTTP servlets be used or generic servlets. If true then JSP can be dispatched to easily */
036        private static final boolean USE_HTTP_SERVLETS = true;
037    
038        private static final String KEY_CONNECTIONS = "connections";
039        private static final String KEY_SUBSCRIPTIONS = "subscriptions";
040    
041        /** 
042         * Whether exceptions occurring during subscriptions on startup should 
043         * terminate the initialization
044         */
045        private boolean continueOnSubscribeException;
046        
047        public ManagerServlet() {
048        }
049        
050        public SubscriptionManager getSubscriptionManager() {
051            SubscriptionManager answer = (SubscriptionManager) getServletContext().getAttribute( "subscriptionManager" );
052            if (answer == null) {
053                answer = new SubscriptionManager();
054                getServletContext().setAttribute( "subscriptionManager", answer );
055            }
056            return answer;
057        }
058    
059        // Servlet methods
060        //-------------------------------------------------------------------------    
061        
062        public synchronized void init() throws ServletException {        
063            String text = getServletContext().getInitParameter( "continueOnSubscribeException" );
064            if ( text != null && text.equals( "true" ) ) {
065                continueOnSubscribeException = true;
066            }
067            
068            // ensure Messenger is initialised
069            try {
070                SubscriptionManager subscriber = getSubscriptionManager();
071                MessengerManager manager = subscriber.getMessengerManager();
072                if ( manager == null ) {
073                    manager = createMessengerManager();
074        
075                    subscriber.setMessengerManager( manager );
076                    subscriber.setSubscriptionList( createSubscriptionList() );
077                    subscriber.setServletContext( getServletContext() );
078                    
079                    // load the subscriptions....
080                    subscriber.subscribe();
081                    
082                    // now lets start all the connections...
083                    for (Iterator iter = manager.getMessengerNames(); iter.hasNext(); ) {
084                        String name = (String) iter.next();
085                        Messenger messenger = manager.getMessenger( name );
086                        try {
087                            messenger.getConnection().start();
088                        }
089                        catch (JMSException e) {
090                            log( "Caught exception trying to start messenger: " + name + ". Exception: " + e, e );
091                        }
092                    }
093                }
094            }
095            catch (JMSException e) {
096                throw new ServletException("Failed to initialize: " + e, e );
097            }
098        }
099        
100        public void destroy() {
101            try {
102                getSubscriptionManager().unsubscribe();
103            }
104            catch (Exception e) {
105                log( "Failed to destrory the MBOs: " + e, e );
106            }
107    
108            try {        
109                MessengerManager manager = getSubscriptionManager().getMessengerManager();
110                if ( manager != null ) {
111                    log( "Closing the Messenger connections" );
112                    manager.close();
113                }
114            }
115            catch (Exception e) {
116                log( "Failed to close the Messenger Manager: " + e, e );
117            }
118            getSubscriptionManager().setMessengerManager( null );
119        }
120        
121        public void service(ServletRequest request, ServletResponse response) throws ServletException {
122        }
123    
124    
125        // Properties
126        //-------------------------------------------------------------------------    
127        public boolean isContinueOnSubscriptionException() {
128            return continueOnSubscribeException;
129        }
130        
131        /** 
132         * Sets whether exceptions occurring during subscriptions on startup should 
133         * terminate the initialization
134         */
135        public void setContinueOnSubscribeException(boolean continueOnSubscribeException) {
136            this.continueOnSubscribeException = continueOnSubscribeException;
137        }
138    
139        
140        // Implementation methods
141        //-------------------------------------------------------------------------    
142        protected MessengerManager createMessengerManager() throws ServletException {
143            String config = getURLResource( KEY_CONNECTIONS, "The Messenger connections XML deployment document" );
144    
145            log( "Creating the Messenger connections from the file: " + config );
146            
147            try {
148                return MessengerManager.load( config );
149            }
150            catch (JMSException e) {
151                log( "Could not parse Messenger connection XML deployment document for URL: " + config, e );
152                
153                throw new ServletException(
154                    "Could not parse Messenger connection XML deployment document for URL: " + config
155                    + " reason: " + e, e
156                );
157            }
158        }
159        
160        protected SubscriptionList createSubscriptionList() throws ServletException {
161            String config = getURLResource( KEY_SUBSCRIPTIONS, "The Messenger subscriptions XML deployment document" );
162            
163            log( "Loading the Messenger subscriptions from: " + config );
164            
165            try {
166                SubscriptionDigester digester = new SubscriptionDigester();
167                return (SubscriptionList) digester.parse( config );
168            }
169            catch (Exception e) {
170                log( "Could not parse Messenger subscription XML deployment document for URL: " + config, e );
171                
172                throw new ServletException(
173                    "Could not parse Messenger subscription XML deployment document for URL: " + config
174                    + " reason: " + e, e
175                );
176            }
177        }
178    
179        protected String getURLResource(String key, String description) throws ServletException {
180            String config = getInitParameter( key );
181            if ( config == null || config.length() == 0 ) {
182                throw new ServletException( 
183                    "No initialization parameter for parameter: " + key 
184                    + " description: " + description 
185                );
186            }
187            try {
188                URL url = getServletContext().getResource( config );
189                config = url.toString();
190            }
191            catch (Exception e) {
192                // ignore, must be an absolute URL
193            }
194            return config;
195        }
196    
197        /**
198         * Allows derived servlets to handle JMS exceptions differently, such as ignoring certain kinds of
199         * exceptions or performing custom logging etc.
200         */
201        protected void handleJMSException(String message, JMSException exception) throws ServletException {    
202            log( message, exception );
203            
204            if ( ! isContinueOnSubscriptionException() ) {
205                throw new ServletException( message, exception );
206            }
207        }
208    }