/*
 * Copyright 2004 The Apache Software Foundation.
 *
 * Licensed 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.joran.action;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.InitialContext;

import org.apache.joran.ExecutionContext;
import org.apache.joran.action.Action;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.ErrorItem;

import org.xml.sax.Attributes;

/**
 * This action looks up JNDI properties specified in the configuration
 * file and adds them to the Joran <code>ExecutionContext</code>.  The
 * element in the configuration file should have an attribute called
 * "jndiName".  This attribute will be the key to the naming context lookup,
 * as well as the key to the <code>ExecutionContext</code> properties.  If a value
 * is found whose name matches the given jndiName, it will be placed
 * in the ExecutionContext's properties.
 *
 * @author Yoav Shapira
 */
public class JndiSubstitutionPropertyAction extends Action {
    /**
     * Logger.
     */
    private static final Logger LOGGER = Logger.getLogger(JndiSubstitutionPropertyAction.class);

    /**
     * The attribute name specifying the JNDI variable to lookup.
     */
    private static final String JNDI_ATTR = "jndiName";

    /**
     * The naming context.
     */
    private Context namingContext;

    /**
     * Returns the naming context for lookups.
     *
     * @return The context (may be null)
     */
    protected Context getNamingContext() {
        return namingContext;
    }

    /**
     * Creates the naming context.  This is an expensive
     * operation.
     *
     * @throws NamingException If an error occurs
     */
    protected void findNamingContext() throws NamingException {
        if(getNamingContext() != null) {
            LOGGER.warn("Overwriting existing naming context.");
        }

        // POSSIBLE TO-DO: add support for properties
        // passed to the initial context, e.g. a factory,
        // to enable things like a remote context.
        InitialContext ic = new InitialContext();
        namingContext = (Context) ic.lookup("java:comp/env");
    }

    /**
     * @see org.apache.joran.Action#begin.
     */
    public void begin(final ExecutionContext ec, final String name, final Attributes attributes) {
        if(LOGGER.isDebugEnabled()) {
            LOGGER.debug(getClass().getName() +
                         ": begin(" + ec +
                         ", " + name +
                         ", " + attributes +
                         "): here.");
        }

        // If first time, create and locate context: expensive operation.
        if(getNamingContext() == null) {
            try {
                findNamingContext();
            } catch (Exception e) {
                LOGGER.error("Couldn't find JNDI naming context: ", e);
                ec.addError(new ErrorItem("Couldn't find JNDI naming context.", e));
            }
        }

        String jndiName = attributes.getValue(JNDI_ATTR);
        
        if((jndiName == null) || (jndiName.trim().length() < 1)) {
            LOGGER.warn("Missing " + JNDI_ATTR + " attribute, ignoring.");
        } else if(getNamingContext() != null){ 
            Object value = null;

            try {
                value = getNamingContext().lookup(jndiName);
            } catch (Exception e) {
                LOGGER.error("Error looking up " + jndiName + ": ", e);
                ec.addError(new ErrorItem("Error looking up " + jndiName, e));
            }

            if(value == null) {
                LOGGER.warn("No JNDI value found for " + jndiName);
            } else if(! (value instanceof String)) {
                LOGGER.warn("Value for " + jndiName + " is not a String.");
            } else {
                ec.addProperty(jndiName, (String) value);
            }
        } else {
            LOGGER.warn("Naming context is null, cannot lookup " + jndiName);
        }
    }

    /**
     * @see org.apache.joran.Action#end.
     */
    public void end(final ExecutionContext ec, final String name) {
    }


}

// End of class: JndiSubstitutionPropertyAction.java

@@ -838,40 +838,8 @@
 on;%0A
-import org.apache.log4j.Logger;%0A
 impo
@@ -1487,137 +1487,8 @@
 n %7B%0A
-    /**%0A     * Logger.%0A     */%0A    private static final Logger LOGGER = Logger.getLogger(JndiSubstitutionPropertyAction.class);%0A%0A
     
@@ -2153,30 +2153,35 @@
             
-LOGGER
+getLogger()
 .warn(%22Overw
@@ -2677,22 +2677,27 @@
      if(
-LOGGER
+getLogger()
 .isDebug
@@ -2721,22 +2721,27 @@
         
-LOGGER
+getLogger()
 .debug(g
@@ -2787,16 +2787,21 @@
         
+     
 %22: begin
@@ -2805,136 +2805,53 @@
 gin(
-%22 + ec +%0A                         %22, %22 + name +%0A                         %22, %22 + attributes +%0A                         %22): here.%22
+%7B%7D, %22 + name + %22, %7B%7D): here.%22, ec, attributes
 );%0A 
@@ -3074,38 +3074,43 @@
                 
-LOGGER
+getLogger()
 .error(%22Couldn't
@@ -3395,30 +3395,35 @@
             
-LOGGER
+getLogger()
 .warn(%22Missi
@@ -3429,25 +3429,10 @@
 ing 
-%22 + JNDI_ATTR + %22
+%7B%7D
  att
@@ -3445,24 +3445,35 @@
 , ignoring.%22
+, JNDI_ATTR
 );%0A        %7D
@@ -3676,22 +3676,27 @@
         
-LOGGER
+getLogger()
 .error(%22
@@ -3871,38 +3871,43 @@
                 
-LOGGER
+getLogger()
 .warn(%22No JNDI v
@@ -3917,27 +3917,29 @@
 e found for 
-%22 +
+%7B%7D.%22,
  jndiName);%0A
@@ -4003,30 +4003,35 @@
             
-LOGGER
+getLogger()
 .warn(%22Value
@@ -4035,32 +4035,18 @@
 lue for 
-%22 + jndiName + %22
+%7B%7D
  is not 
@@ -4055,16 +4055,26 @@
 String.%22
+, jndiName
 );%0A     
@@ -4194,14 +4194,19 @@
     
-LOGGER
+getLogger()
 .war
@@ -4246,19 +4246,20 @@
  lookup 
-%22 +
+%7B%7D%22,
  jndiNam

Change JndiSubstitutionPropertyAction to use the instance Logger and parameterized Logger calls when possible for performance.