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 */
017package org.apache.logging.log4j.core.net;
018
019import java.io.Serializable;
020import java.util.Properties;
021import javax.jms.JMSException;
022import javax.jms.Message;
023import javax.jms.MessageProducer;
024import javax.jms.ObjectMessage;
025import javax.jms.Session;
026import javax.jms.TextMessage;
027import javax.naming.Context;
028import javax.naming.InitialContext;
029import javax.naming.NameNotFoundException;
030import javax.naming.NamingException;
031
032import org.apache.logging.log4j.core.appender.AbstractManager;
033
034/**
035 * Base Class for Managers of JMS connections.
036 */
037public 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 InitialContext 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}