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.Session;
023    import javax.jms.Topic;
024    import javax.jms.TopicConnection;
025    import javax.jms.TopicConnectionFactory;
026    import javax.jms.TopicPublisher;
027    import javax.jms.TopicSession;
028    import javax.naming.Context;
029    import javax.naming.NamingException;
030    import java.io.Serializable;
031    
032    /**
033     * Manager for JMS Topic connections.
034     */
035    public class JMSTopicManager extends AbstractJMSManager {
036    
037        private static final JMSTopicManagerFactory factory = new JMSTopicManagerFactory();
038    
039        private final TopicConnection topicConnection;
040        private final TopicSession topicSession;
041        private final TopicPublisher topicPublisher;
042    
043        /**
044         * Constructor.
045         * @param name The unique name of the connection.
046         * @param conn The TopicConnection.
047         * @param sess The TopicSession.
048         * @param pub The TopicPublisher.
049         */
050        public JMSTopicManager(String name, TopicConnection conn, TopicSession sess, TopicPublisher pub) {
051            super(name);
052            this.topicConnection = conn;
053            this.topicSession = sess;
054            this.topicPublisher = pub;
055        }
056    
057        /**
058         * Obtain a JSMTopicManager.
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 TopicConnectionFactory.
066         * @param topicBindingName The name to use to locate the Topic.
067         * @param userName The userid to use to create the Topic Connection.
068         * @param password The password to use to create the Topic Connection.
069         * @return A JMSTopicManager.
070         */
071        public static JMSTopicManager getJMSTopicManager(String factoryName, String providerURL, String urlPkgPrefixes,
072                                                         String securityPrincipalName, String securityCredentials,
073                                                         String factoryBindingName, String topicBindingName,
074                                                         String userName, String password) {
075    
076            if (factoryBindingName == null) {
077                LOGGER.error("No factory name provided for JMSTopicManager");
078                return null;
079            }
080            if (topicBindingName == null) {
081                LOGGER.error("No topic name provided for JMSTopicManager");
082                return null;
083            }
084    
085            String name = "JMSTopic:" + factoryBindingName + '.' + topicBindingName;
086            return getManager(name, factory, new FactoryData(factoryName, providerURL, urlPkgPrefixes,
087                securityPrincipalName, securityCredentials, factoryBindingName, topicBindingName, userName, password));
088        }
089    
090    
091        @Override
092        public void send(Serializable object) throws Exception {
093            super.send(object, topicSession, topicPublisher);
094        }
095    
096        @Override
097        public void releaseSub() {
098            try {
099                if (topicSession != null) {
100                    topicSession.close();
101                }
102                if (topicConnection != null) {
103                    topicConnection.close();
104                }
105            } catch (JMSException ex) {
106                LOGGER.error("Error closing " + getName(), ex);
107            }
108        }
109    
110        /**
111         * Data for the factory.
112         */
113        private static class FactoryData {
114            private String factoryName;
115            private String providerURL;
116            private String urlPkgPrefixes;
117            private String securityPrincipalName;
118            private String securityCredentials;
119            private String factoryBindingName;
120            private String topicBindingName;
121            private String userName;
122            private String password;
123    
124            public FactoryData(String factoryName, String providerURL, String urlPkgPrefixes, String securityPrincipalName,
125                               String securityCredentials, String factoryBindingName, String topicBindingName,
126                               String userName, String password) {
127                this.factoryName = factoryName;
128                this.providerURL = providerURL;
129                this.urlPkgPrefixes = urlPkgPrefixes;
130                this.securityPrincipalName = securityPrincipalName;
131                this.securityCredentials = securityCredentials;
132                this.factoryBindingName = factoryBindingName;
133                this.topicBindingName = topicBindingName;
134                this.userName = userName;
135                this.password = password;
136            }
137        }
138    
139        /**
140         * Factory to create a JMSTopicManager.
141         */
142        private static class JMSTopicManagerFactory implements ManagerFactory<JMSTopicManager, FactoryData> {
143    
144            public JMSTopicManager createManager(String name, FactoryData data) {
145                try {
146                    Context ctx = createContext(data.factoryName, data.providerURL, data.urlPkgPrefixes,
147                                                data.securityPrincipalName, data.securityCredentials);
148                    TopicConnectionFactory factory = (TopicConnectionFactory) lookup(ctx, data.factoryBindingName);
149                    TopicConnection conn;
150                    if (data.userName != null) {
151                        conn = factory.createTopicConnection(data.userName, data.password);
152                    } else {
153                        conn = factory.createTopicConnection();
154                    }
155                    TopicSession sess = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
156                    Topic topic = (Topic) lookup(ctx, data.topicBindingName);
157                    TopicPublisher pub = sess.createPublisher(topic);
158                    conn.start();
159                    return new JMSTopicManager(name, conn, sess, pub);
160                } catch (NamingException ex) {
161                    LOGGER.error("Bad Name " + data.topicBindingName, ex);
162                } catch (JMSException jmsex) {
163                    LOGGER.error("Unable to create publisher ", jmsex);
164                }
165    
166                return null;
167            }
168        }
169    }