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(final 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(final String factoryName, final String providerURL,
059                                               final String urlPkgPrefixes, final String securityPrincipalName,
060                                               final String securityCredentials)
061            throws NamingException {
062    
063            final Properties props = getEnvironment(factoryName, providerURL, urlPkgPrefixes, securityPrincipalName,
064                                              securityCredentials);
065            return new InitialContext(props);
066        }
067    
068        /**
069         * Looks up the name in the context.
070         * @param ctx The Context.
071         * @param name The name to locate.
072         * @return The object to be located.
073         * @throws NamingException If an error occurs locating the name.
074         */
075        protected static Object lookup(final Context ctx, final String name) throws NamingException {
076            try {
077                return ctx.lookup(name);
078            } catch (final NameNotFoundException e) {
079                LOGGER.warn("Could not find name [" + name + "].");
080                throw e;
081            }
082        }
083    
084        /**
085         * Sets up the properties to pass to the InitialContext.
086         * @param factoryName The fully qualified class name of the InitialContextFactory.
087         * @param providerURL The URL of the provider to use.
088         * @param urlPkgPrefixes A colon-separated list of package prefixes for the class name of the factory class that
089         * will create a URL context factory
090         * @param securityPrincipalName The name of the identity of the Principal.
091         * @param securityCredentials The security credentials of the Principal.
092         * @return The Properties.
093         */
094        protected static Properties getEnvironment(final String factoryName, final String providerURL,
095                                                   final String urlPkgPrefixes, final String securityPrincipalName,
096                                                   final String securityCredentials) {
097            final Properties props = new Properties();
098            if (factoryName != null) {
099                props.put(Context.INITIAL_CONTEXT_FACTORY, factoryName);
100                if (providerURL != null) {
101                    props.put(Context.PROVIDER_URL, providerURL);
102                } else {
103                    LOGGER.warn("The InitalContext factory name has been provided without a ProviderURL. " +
104                        "This is likely to cause problems");
105                }
106                if (urlPkgPrefixes != null) {
107                    props.put(Context.URL_PKG_PREFIXES, urlPkgPrefixes);
108                }
109                if (securityPrincipalName != null) {
110                    props.put(Context.SECURITY_PRINCIPAL, securityPrincipalName);
111                    if (securityCredentials != null) {
112                        props.put(Context.SECURITY_CREDENTIALS, securityCredentials);
113                    } else {
114                        LOGGER.warn("SecurityPrincipalName has been set without SecurityCredentials. " +
115                            "This is likely to cause problems.");
116                    }
117                }
118                return props;
119            }
120            return null;
121        }
122    
123        /**
124         * Send the message.
125         * @param object The Object to sent.
126         * @throws Exception if an error occurs.
127         */
128        public abstract void send(Serializable object) throws Exception;
129    
130        /**
131         * Send the Object.
132         * @param object The Object to send.
133         * @param session The Session.
134         * @param producer The MessageProducer.
135         * @throws Exception if an error occurs.
136         */
137        public synchronized void send(final Serializable object, final Session session, final MessageProducer producer)
138            throws Exception {
139            try {
140                Message msg;
141                if (object instanceof String) {
142                    msg = session.createTextMessage();
143                    ((TextMessage) msg).setText((String) object);
144                } else {
145                    msg = session.createObjectMessage();
146                    ((ObjectMessage) msg).setObject(object);
147                }
148                producer.send(msg);
149            } catch (final JMSException ex) {
150                LOGGER.error("Could not publish message via JMS " + getName());
151                throw ex;
152            }
153        }
154    }