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.logging.log4j.core.net;
018    
019    import org.apache.logging.log4j.core.appender.ManagerFactory;
020    
021    import javax.jms.JMSException;
022    import javax.jms.Queue;
023    import javax.jms.QueueConnection;
024    import javax.jms.QueueConnectionFactory;
025    import javax.jms.QueueSender;
026    import javax.jms.QueueSession;
027    import javax.jms.Session;
028    import javax.naming.Context;
029    import javax.naming.NamingException;
030    import java.io.Serializable;
031    
032    /**
033     * Manager for a JMS Queue.
034     */
035    public class JMSQueueManager extends AbstractJMSManager {
036    
037        private static final JMSQueueManagerFactory factory = new JMSQueueManagerFactory();
038    
039        private final QueueConnection queueConnection;
040        private final QueueSession queueSession;
041        private final QueueSender queueSender;
042    
043        /**
044         * The Constructor.
045         * @param name The unique name of the connection.
046         * @param conn The QueueConnection.
047         * @param sess The QueueSession.
048         * @param sender The QueueSender.
049         */
050        protected JMSQueueManager(String name, QueueConnection conn, QueueSession sess, QueueSender sender) {
051            super(name);
052            this.queueConnection = conn;
053            this.queueSession = sess;
054            this.queueSender = sender;
055        }
056    
057        /**
058         * Obtain a JMSQueueManager.
059         * @param factoryName The fully qualified class name of the InitialContextFactory.
060         * @param providerURL The URL of the provider to use.
061         * @param urlPkgPrefixes A colon-separated list of package prefixes for the class name of the factory class that
062         * will create a URL context factory
063         * @param securityPrincipalName The name of the identity of the Principal.
064         * @param securityCredentials The security credentials of the Principal.
065         * @param factoryBindingName The name to locate in the Context that provides the QueueConnectionFactory.
066         * @param queueBindingName The name to use to locate the Queue.
067         * @param userName The userid to use to create the Queue Connection.
068         * @param password The password to use to create the Queue Connection.
069         * @return The JMSQueueManager.
070         */
071        public static JMSQueueManager getJMSQueueManager(String factoryName, String providerURL, String urlPkgPrefixes,
072                                                         String securityPrincipalName, String securityCredentials,
073                                                         String factoryBindingName, String queueBindingName,
074                                                         String userName, String password) {
075    
076            if (factoryBindingName == null) {
077                LOGGER.error("No factory name provided for JMSQueueManager");
078                return null;
079            }
080            if (queueBindingName == null) {
081                LOGGER.error("No topic name provided for JMSQueueManager");
082                return null;
083            }
084    
085            String name = "JMSQueue:" + factoryBindingName + '.' + queueBindingName;
086            return getManager(name, factory, new FactoryData(factoryName, providerURL, urlPkgPrefixes,
087                securityPrincipalName, securityCredentials, factoryBindingName, queueBindingName, userName, password));
088        }
089    
090        @Override
091        public void send(Serializable object) throws Exception {
092            super.send(object, queueSession, queueSender);
093        }
094    
095        @Override
096        public void releaseSub() {
097            try {
098                if (queueSession != null) {
099                    queueSession.close();
100                }
101                if (queueConnection != null) {
102                    queueConnection.close();
103                }
104            } catch (JMSException ex) {
105                LOGGER.error("Error closing " + getName(), ex);
106            }
107        }
108    
109        /**
110         * Data for the factory.
111         */
112        private static class FactoryData {
113            private String factoryName;
114            private String providerURL;
115            private String urlPkgPrefixes;
116            private String securityPrincipalName;
117            private String securityCredentials;
118            private String factoryBindingName;
119            private String queueBindingName;
120            private String userName;
121            private String password;
122    
123            public FactoryData(String factoryName, String providerURL, String urlPkgPrefixes, String securityPrincipalName,
124                               String securityCredentials, String factoryBindingName, String queueBindingName,
125                               String userName, String password) {
126                this.factoryName = factoryName;
127                this.providerURL = providerURL;
128                this.urlPkgPrefixes = urlPkgPrefixes;
129                this.securityPrincipalName = securityPrincipalName;
130                this.securityCredentials = securityCredentials;
131                this.factoryBindingName = factoryBindingName;
132                this.queueBindingName = queueBindingName;
133                this.userName = userName;
134                this.password = password;
135            }
136        }
137    
138        /**
139         * Factory to create the JMSQueueManager.
140         */
141        private static class JMSQueueManagerFactory implements ManagerFactory<JMSQueueManager, FactoryData> {
142    
143            public JMSQueueManager createManager(String name, FactoryData data) {
144                try {
145                    Context ctx = createContext(data.factoryName, data.providerURL, data.urlPkgPrefixes,
146                                                data.securityPrincipalName, data.securityCredentials);
147                    QueueConnectionFactory factory = (QueueConnectionFactory) lookup(ctx, data.factoryBindingName);
148                    QueueConnection conn;
149                    if (data.userName != null) {
150                        conn = factory.createQueueConnection(data.userName, data.password);
151                    } else {
152                        conn = factory.createQueueConnection();
153                    }
154                    QueueSession sess = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
155                    Queue queue = (Queue) lookup(ctx, data.queueBindingName);
156                    QueueSender sender = sess.createSender(queue);
157                    conn.start();
158                    return new JMSQueueManager(name, conn, sess, sender);
159    
160                } catch (NamingException ex) {
161                    LOGGER.error("Unable to locate resource", ex);
162                } catch (JMSException jmsex) {
163                    LOGGER.error("Unable to establish connection", jmsex);
164                }
165    
166                return null;
167            }
168        }
169    }