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.AbstractManager;
020    
021    import javax.jms.JMSException;
022    import javax.jms.Message;
023    import javax.jms.MessageProducer;
024    import javax.jms.ObjectMessage;
025    import javax.jms.Session;
026    import javax.jms.TextMessage;
027    import javax.naming.Context;
028    import javax.naming.InitialContext;
029    import javax.naming.NameNotFoundException;
030    import javax.naming.NamingException;
031    import java.io.Serializable;
032    import java.util.Properties;
033    
034    /**
035     * Base Class for Managers of JMS connections.
036     */
037    public abstract class AbstractJMSManager extends AbstractManager {
038    
039        /**
040         * The Constructor.
041         * @param name The name of the Appender.
042         */
043        public AbstractJMSManager(String name) {
044            super(name);
045        }
046    
047        /**
048         * Create the InitialContext.
049         * @param factoryName The fully qualified class name of the InitialContextFactory.
050         * @param providerURL The URL of the provider to use.
051         * @param urlPkgPrefixes A colon-separated list of package prefixes for the class name of the factory class that
052         * will create a URL context factory
053         * @param securityPrincipalName The name of the identity of the Principal.
054         * @param securityCredentials The security credentials of the Principal.
055         * @return the InitialContext.
056         * @throws NamingException if a naming error occurs.
057         */
058        protected static Context createContext(String factoryName, String providerURL, String urlPkgPrefixes,
059                                               String securityPrincipalName, String securityCredentials)
060            throws NamingException {
061    
062            Properties props = getEnvironment(factoryName, providerURL, urlPkgPrefixes, securityPrincipalName,
063                                              securityCredentials);
064            return new InitialContext(props);
065        }
066    
067        /**
068         * Looks up the name in the context.
069         * @param ctx The Context.
070         * @param name The name to locate.
071         * @return The object to be located.
072         * @throws NamingException If an error occurs locating the name.
073         */
074        protected static Object lookup(Context ctx, String name) throws NamingException {
075            try {
076                return ctx.lookup(name);
077            } catch (NameNotFoundException e) {
078                LOGGER.error("Could not find name [" + name + "].");
079                throw e;
080            }
081        }
082    
083        /**
084         * Sets up the properties to pass to the InitialContext.
085         * @param factoryName The fully qualified class name of the InitialContextFactory.
086         * @param providerURL The URL of the provider to use.
087         * @param urlPkgPrefixes A colon-separated list of package prefixes for the class name of the factory class that
088         * will create a URL context factory
089         * @param securityPrincipalName The name of the identity of the Principal.
090         * @param securityCredentials The security credentials of the Principal.
091         * @return The Properties.
092         */
093        protected static Properties getEnvironment(String factoryName, String providerURL, String urlPkgPrefixes,
094                                                   String securityPrincipalName, String securityCredentials) {
095            Properties props = new Properties();
096            if (factoryName != null) {
097                props.put(Context.INITIAL_CONTEXT_FACTORY, factoryName);
098                if (providerURL != null) {
099                    props.put(Context.PROVIDER_URL, providerURL);
100                } else {
101                    LOGGER.warn("The InitalContext factory name has been provided without a ProviderURL. " +
102                        "This is likely to cause problems");
103                }
104                if (urlPkgPrefixes != null) {
105                    props.put(Context.URL_PKG_PREFIXES, urlPkgPrefixes);
106                }
107                if (securityPrincipalName != null) {
108                    props.put(Context.SECURITY_PRINCIPAL, securityPrincipalName);
109                    if (securityCredentials != null) {
110                        props.put(Context.SECURITY_CREDENTIALS, securityCredentials);
111                    } else {
112                        LOGGER.warn("SecurityPrincipalName has been set without SecurityCredentials. " +
113                            "This is likely to cause problems.");
114                    }
115                }
116                return props;
117            }
118            return null;
119        }
120    
121        /**
122         * Send the message.
123         * @param object The Object to sent.
124         * @throws Exception if an error occurs.
125         */
126        public abstract void send(Serializable object) throws Exception;
127    
128        /**
129         * Send the Object.
130         * @param object The Object to send.
131         * @param session The Session.
132         * @param producer The MessageProducer.
133         * @throws Exception if an error occurs.
134         */
135        public synchronized void send(Serializable object, Session session, MessageProducer producer) throws Exception {
136            try {
137                Message msg;
138                if (object instanceof String) {
139                    msg = session.createTextMessage();
140                    ((TextMessage) msg).setText((String) object);
141                } else {
142                    msg = session.createObjectMessage();
143                    ((ObjectMessage) msg).setObject(object);
144                }
145                producer.send(msg);
146            } catch (JMSException ex) {
147                LOGGER.error("Could not publish message via JMS " + getName());
148                throw ex;
149            }
150        }
151    }