All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.log4j.net.JMSAppender Maven / Gradle / Ivy

There is a newer version: 6.1.2
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.log4j.net;

import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.spi.ErrorCode;
import org.apache.log4j.spi.LoggingEvent;

import javax.jms.JMSException;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Properties;

/**
 * A simple appender that publishes events to a JMS Topic. The events are serialized and transmitted as JMS message type
 * {@link ObjectMessage}.
 *
 * 

* JMS {@link Topic topics} and {@link TopicConnectionFactory topic connection factories} are administered objects that * are retrieved using JNDI messaging which in turn requires the retrieval of a JNDI {@link Context}. * *

* There are two common methods for retrieving a JNDI {@link Context}. If a file resource named jndi.properties * is available to the JNDI API, it will use the information found therein to retrieve an initial JNDI context. To * obtain an initial context, your code will simply call: * *

 * InitialContext jndiContext = new InitialContext();
 * 
* *

* Calling the no-argument InitialContext() method will also work from within Enterprise Java Beans (EJBs) * because it is part of the EJB contract for application servers to provide each bean an environment naming context * (ENC). * *

* In the second approach, several predetermined properties are set and these properties are passed to the * InitialContext constructor to connect to the naming service provider. For example, to connect to JBoss * naming service one would write: * *

 * Properties env = new Properties();
 * env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
 * env.put(Context.PROVIDER_URL, "jnp://hostname:1099");
 * env.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
 * InitialContext jndiContext = new InitialContext(env);
 * 
*

* where hostname is the host where the JBoss application server is running. * *

* To connect to the the naming service of Weblogic application server one would write: * *

 * Properties env = new Properties();
 * env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
 * env.put(Context.PROVIDER_URL, "t3://localhost:7001");
 * InitialContext jndiContext = new InitialContext(env);
 * 
* *

* Other JMS providers will obviously require different values. *

* The initial JNDI context can be obtained by calling the no-argument * InitialContext() method in EJBs. Only clients running in a * separate JVM need to be concerned about the jndi.properties file and calling * {@link InitialContext#InitialContext()} or alternatively correctly setting the different properties before calling * {@link InitialContext#InitialContext(java.util.Hashtable)} method. * * @author Ceki Gülcü */ public class JMSAppender extends AppenderSkeleton { String securityPrincipalName; String securityCredentials; String initialContextFactoryName; String urlPkgPrefixes; String providerURL; String topicBindingName; String tcfBindingName; String userName; String password; boolean locationInfo; TopicConnection topicConnection; TopicSession topicSession; TopicPublisher topicPublisher; public JMSAppender() { } /** * The TopicConnectionFactoryBindingName option takes a string value. Its value will be used to lookup the * appropriate * TopicConnectionFactory from the JNDI context. */ public void setTopicConnectionFactoryBindingName(String tcfBindingName) { this.tcfBindingName = tcfBindingName; } /** * Returns the value of the TopicConnectionFactoryBindingName option. */ public String getTopicConnectionFactoryBindingName() { return tcfBindingName; } /** * The TopicBindingName option takes a string value. Its value will be used to lookup the appropriate * Topic from the JNDI context. */ public void setTopicBindingName(String topicBindingName) { this.topicBindingName = topicBindingName; } /** * Returns the value of the TopicBindingName option. */ public String getTopicBindingName() { return topicBindingName; } /** * Returns value of the LocationInfo property which determines whether location (stack) info is sent to the * remote subscriber. */ public boolean getLocationInfo() { return locationInfo; } /** * Options are activated and become effective only after calling this method. */ public void activateOptions() { TopicConnectionFactory topicConnectionFactory; try { Context jndi; LogLog.debug("Getting initial context."); if (initialContextFactoryName != null) { Properties env = new Properties(); env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactoryName); if (providerURL != null) { env.put(Context.PROVIDER_URL, providerURL); } else { LogLog.warn("You have set InitialContextFactoryName option but not the " + "ProviderURL. This is likely to cause problems."); } if (urlPkgPrefixes != null) { env.put(Context.URL_PKG_PREFIXES, urlPkgPrefixes); } if (securityPrincipalName != null) { env.put(Context.SECURITY_PRINCIPAL, securityPrincipalName); if (securityCredentials != null) { env.put(Context.SECURITY_CREDENTIALS, securityCredentials); } else { LogLog.warn("You have set SecurityPrincipalName option but not the " + "SecurityCredentials. This is likely to cause problems."); } } jndi = new InitialContext(env); } else { jndi = new InitialContext(); } LogLog.debug("Looking up [" + tcfBindingName + "]"); topicConnectionFactory = (TopicConnectionFactory) lookup(jndi, tcfBindingName); LogLog.debug("About to create TopicConnection."); if (userName != null) { topicConnection = topicConnectionFactory.createTopicConnection(userName, password); } else { topicConnection = topicConnectionFactory.createTopicConnection(); } LogLog.debug("Creating TopicSession, non-transactional, " + "in AUTO_ACKNOWLEDGE mode."); topicSession = topicConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); LogLog.debug("Looking up topic name [" + topicBindingName + "]."); Topic topic = (Topic) lookup(jndi, topicBindingName); LogLog.debug("Creating TopicPublisher."); topicPublisher = topicSession.createPublisher(topic); LogLog.debug("Starting TopicConnection."); topicConnection.start(); jndi.close(); } catch (JMSException e) { errorHandler.error("Error while activating options for appender named [" + name + "].", e, ErrorCode.GENERIC_FAILURE); } catch (NamingException e) { errorHandler.error("Error while activating options for appender named [" + name + "].", e, ErrorCode.GENERIC_FAILURE); } catch (RuntimeException e) { errorHandler.error("Error while activating options for appender named [" + name + "].", e, ErrorCode.GENERIC_FAILURE); } } protected Object lookup(Context ctx, String name) throws NamingException { Object result = JNDIUtil.lookupObject(ctx, name); if (result == null) { String msg = "Could not find name [" + name + "]."; throw new NamingException(msg); } return result; } protected boolean checkEntryConditions() { String fail = null; if (this.topicConnection == null) { fail = "No TopicConnection"; } else if (this.topicSession == null) { fail = "No TopicSession"; } else if (this.topicPublisher == null) { fail = "No TopicPublisher"; } if (fail != null) { errorHandler.error(fail + " for JMSAppender named [" + name + "]."); return false; } else { return true; } } /** * Close this JMSAppender. Closing releases all resources used by the appender. A closed appender cannot be * re-opened. */ public synchronized void close() { // The synchronized modifier avoids concurrent append and close operations if (this.closed) return; LogLog.debug("Closing appender [" + name + "]."); this.closed = true; try { if (topicSession != null) topicSession.close(); if (topicConnection != null) topicConnection.close(); } catch (JMSException e) { LogLog.error("Error while closing JMSAppender [" + name + "].", e); } catch (RuntimeException e) { LogLog.error("Error while closing JMSAppender [" + name + "].", e); } // Help garbage collection topicPublisher = null; topicSession = null; topicConnection = null; } /** * This method called by {@link AppenderSkeleton#doAppend} method to do most of the real appending work. */ public void append(LoggingEvent event) { if (!checkEntryConditions()) { return; } try { ObjectMessage msg = topicSession.createObjectMessage(); if (locationInfo) { event.getLocationInformation(); } msg.setObject(event); topicPublisher.publish(msg); } catch (JMSException e) { errorHandler.error("Could not publish message in JMSAppender [" + name + "].", e, ErrorCode.GENERIC_FAILURE); } catch (RuntimeException e) { errorHandler.error("Could not publish message in JMSAppender [" + name + "].", e, ErrorCode.GENERIC_FAILURE); } } /** * Returns the value of the InitialContextFactoryName option. See {@link #setInitialContextFactoryName} for * more details on the meaning of this option. */ public String getInitialContextFactoryName() { return initialContextFactoryName; } /** * Setting the InitialContextFactoryName method will cause this * JMSAppender instance to use the * {@link InitialContext#InitialContext(Hashtable)} method instead of the no-argument constructor. If you set this * option, you should also at least set the ProviderURL option. * *

* See also {@link #setProviderURL(String)}. */ public void setInitialContextFactoryName(String initialContextFactoryName) { this.initialContextFactoryName = initialContextFactoryName; } public String getProviderURL() { return providerURL; } public void setProviderURL(String providerURL) { this.providerURL = providerURL; } String getURLPkgPrefixes() { return urlPkgPrefixes; } public void setURLPkgPrefixes(String urlPkgPrefixes) { this.urlPkgPrefixes = urlPkgPrefixes; } public String getSecurityCredentials() { return securityCredentials; } public void setSecurityCredentials(String securityCredentials) { this.securityCredentials = securityCredentials; } public String getSecurityPrincipalName() { return securityPrincipalName; } public void setSecurityPrincipalName(String securityPrincipalName) { this.securityPrincipalName = securityPrincipalName; } public String getUserName() { return userName; } /** * The user name to use when * {@link TopicConnectionFactory#createTopicConnection(String, String) creating a topic session}. If you set this * option, you should also set the * Password option. See {@link #setPassword(String)}. */ public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } /** * The paswword to use when creating a topic session. */ public void setPassword(String password) { this.password = password; } /** * If true, the information sent to the remote subscriber will include caller's location information. By default no * location information is sent to the subscriber. */ public void setLocationInfo(boolean locationInfo) { this.locationInfo = locationInfo; } /** * Returns the TopicConnection used for this appender. Only valid after activateOptions() method has been invoked. */ protected TopicConnection getTopicConnection() { return topicConnection; } /** * Returns the TopicSession used for this appender. Only valid after activateOptions() method has been invoked. */ protected TopicSession getTopicSession() { return topicSession; } /** * Returns the TopicPublisher used for this appender. Only valid after activateOptions() method has been invoked. */ protected TopicPublisher getTopicPublisher() { return topicPublisher; } /** * The JMSAppender sends serialized events and consequently does not require a layout. */ public boolean requiresLayout() { return false; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy