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