Integrated Chad's logging changes:
authorwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Tue, 17 May 2005 18:41:29 +0000 (18:41 +0000)
committerwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Tue, 17 May 2005 18:41:29 +0000 (18:41 +0000)
1) Don't assume shib is the only application using log4j
2) Don't count on the context listerner to load before init() {This isn't the case in all containers}

git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@1495 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

src/edu/internet2/middleware/shibboleth/idp/IdPConfigLoader.java [moved from src/edu/internet2/middleware/shibboleth/common/IdPConfigLoader.java with 97% similarity]
src/edu/internet2/middleware/shibboleth/idp/IdPResponder.java
src/edu/internet2/middleware/shibboleth/log/LoggingContextListener.java [deleted file]
src/edu/internet2/middleware/shibboleth/log/LoggingInitializer.java [new file with mode: 0644]
src/edu/internet2/middleware/shibboleth/utils/ResolverTest.java

  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package edu.internet2.middleware.shibboleth.common;
+package edu.internet2.middleware.shibboleth.idp;
 
 import javax.servlet.ServletContext;
 
 import org.apache.log4j.Logger;
 import org.w3c.dom.Document;
 
+import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
 import edu.internet2.middleware.shibboleth.xml.Parser;
 
 /**
index 150db3a..da31a31 100644 (file)
@@ -58,13 +58,13 @@ import edu.internet2.middleware.shibboleth.artifact.ArtifactMapper;
 import edu.internet2.middleware.shibboleth.artifact.ArtifactMapperFactory;
 import edu.internet2.middleware.shibboleth.artifact.provider.MemoryArtifactMapper;
 import edu.internet2.middleware.shibboleth.common.Credentials;
-import edu.internet2.middleware.shibboleth.common.IdPConfigLoader;
 import edu.internet2.middleware.shibboleth.common.NameIdentifierMapping;
 import edu.internet2.middleware.shibboleth.common.NameIdentifierMappingException;
 import edu.internet2.middleware.shibboleth.common.NameMapper;
 import edu.internet2.middleware.shibboleth.common.ServiceProviderMapper;
 import edu.internet2.middleware.shibboleth.common.ServiceProviderMapperException;
 import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
+import edu.internet2.middleware.shibboleth.log.LoggingInitializer;
 import edu.internet2.middleware.shibboleth.metadata.Metadata;
 import edu.internet2.middleware.shibboleth.metadata.MetadataException;
 
@@ -77,8 +77,8 @@ import edu.internet2.middleware.shibboleth.metadata.MetadataException;
 
 public class IdPResponder extends HttpServlet {
 
-       private static Logger transactionLog = Logger.getLogger("Shibboleth-TRANSACTION");
-       private static Logger log = Logger.getLogger(IdPResponder.class.getName());
+       private static Logger transactionLog;
+       private static Logger log;
        private static Random idgen = new Random();
        private SAMLBinding binding;
 
@@ -92,20 +92,35 @@ public class IdPResponder extends HttpServlet {
        public void init() throws ServletException {
 
                super.init();
-               MDC.put("serviceId", "[IdP] Core");
-               log.info("Initializing Identity Provider.");
 
                try {
                        binding = SAMLBindingFactory.getInstance(SAMLBinding.SOAP);
 
                        Document idPConfig = IdPConfigLoader.getIdPConfig(this.getServletContext());
 
+                       // Initialize logging
+                       NodeList itemElements = idPConfig.getDocumentElement().getElementsByTagNameNS(IdPConfig.configNameSpace,
+                                       "Logging");
+                       if (itemElements.getLength() > 0) {
+                               if (itemElements.getLength() > 1) {
+                                       System.err
+                                                       .println("WARNING: More than one Logging element in IdP configuration, using the first one.");
+                               } else {
+                                       Element loggingConfig = (Element) itemElements.item(0);
+                                       LoggingInitializer.initializeLogging(loggingConfig);
+                                       transactionLog = Logger.getLogger("Shibboleth-TRANSACTION");
+                                       log = Logger.getLogger(IdPResponder.class);
+                                       MDC.put("serviceId", "[IdP] Core");
+                                       log.info("Initializing Identity Provider.");
+                               }
+                       }
+
                        // Load global configuration properties
                        configuration = new IdPConfig(idPConfig.getDocumentElement());
 
                        // Load name mappings
                        NameMapper nameMapper = new NameMapper();
-                       NodeList itemElements = idPConfig.getDocumentElement().getElementsByTagNameNS(
+                       itemElements = idPConfig.getDocumentElement().getElementsByTagNameNS(
                                        NameIdentifierMapping.mappingNamespace, "NameMapping");
 
                        for (int i = 0; i < itemElements.getLength(); i++) {
diff --git a/src/edu/internet2/middleware/shibboleth/log/LoggingContextListener.java b/src/edu/internet2/middleware/shibboleth/log/LoggingContextListener.java
deleted file mode 100644 (file)
index 149493d..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * The Shibboleth License, Version 1. Copyright (c) 2002 University Corporation for Advanced Internet Development, Inc.
- * All rights reserved Redistribution and use in source and binary forms, with or without modification, are permitted
- * provided that the following conditions are met: Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution, if any, must include the following acknowledgment: "This product includes software
- * developed by the University Corporation for Advanced Internet Development <http://www.ucaid.edu>Internet2 Project.
- * Alternately, this acknowledegement may appear in the software itself, if and wherever such third-party
- * acknowledgments normally appear. Neither the name of Shibboleth nor the names of its contributors, nor Internet2, nor
- * the University Corporation for Advanced Internet Development, Inc., nor UCAID may be used to endorse or promote
- * products derived from this software without specific prior written permission. For written permission, please contact
- * shibboleth@shibboleth.org Products derived from this software may not be called Shibboleth, Internet2, UCAID, or the
- * University Corporation for Advanced Internet Development, nor may Shibboleth appear in their name, without prior
- * written permission of the University Corporation for Advanced Internet Development. THIS SOFTWARE IS PROVIDED BY THE
- * COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE
- * DISCLAIMED AND THE ENTIRE RISK OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE. IN NO
- * EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC.
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package edu.internet2.middleware.shibboleth.log;
-
-import java.io.PrintWriter;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-
-import org.apache.log4j.ConsoleAppender;
-import org.apache.log4j.DailyRollingFileAppender;
-import org.apache.log4j.Level;
-import org.apache.log4j.LogManager;
-import org.apache.log4j.Logger;
-import org.apache.log4j.PatternLayout;
-import org.apache.log4j.PropertyConfigurator;
-import org.apache.log4j.xml.DOMConfigurator;
-import org.apache.xml.security.Init;
-import org.w3c.dom.Document;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import edu.internet2.middleware.shibboleth.common.IdPConfigLoader;
-import edu.internet2.middleware.shibboleth.common.ShibResource;
-import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
-import edu.internet2.middleware.shibboleth.idp.IdPConfig;
-
-/**
- * {@link ServletContextListener}used to configure logging for other components.
- * 
- * @author Walter Hoehn
- * @author Noah Levitt
- */
-public class LoggingContextListener implements ServletContextListener {
-
-       private static Logger log = Logger.getLogger(LoggingContextListener.class.getName());
-
-       // tomcat calls this before the servlet init()s, but is that guaranteed?
-       public void contextInitialized(ServletContextEvent sce) {
-
-               // Silliness to get around xmlsec doing its own configuration, ie: we might need to override it
-               Init.init();
-
-               ConsoleAppender rootAppender = new ConsoleAppender();
-               rootAppender.setWriter(new PrintWriter(System.out));
-               rootAppender.setName("stdout");
-               Logger.getRootLogger().addAppender(rootAppender);
-
-               // rootAppender.setLayout(new PatternLayout("%-5p %-41X{serviceId} %d{ISO8601} (%c:%L) - %m%n"));
-               // Logger.getRootLogger().setLevel((Level) Level.DEBUG);
-               Logger.getRootLogger().setLevel((Level) Level.INFO);
-               rootAppender.setLayout(new PatternLayout("%d{ISO8601} %-5p %-41X{serviceId} - %m%n"));
-
-               try {
-                       Document idpConfig = IdPConfigLoader.getIdPConfig(sce.getServletContext());
-                       loadConfiguration(idpConfig);
-               } catch (ShibbolethConfigurationException e) {
-                       sce.getServletContext().log("Problem setting up logging.", e);
-                       log.fatal("Problem setting up logging: " + e);
-                       throw new Error("Problem setting up logging: " + e);
-               }
-
-               log.info("Logger initialized.");
-       }
-
-       public void contextDestroyed(ServletContextEvent sce) {
-
-               log.info("Shutting down logging infrastructure.");
-               LogManager.shutdown();
-       }
-
-       protected void loadConfiguration(Document idpConfig) throws ShibbolethConfigurationException {
-
-               NodeList itemElements = idpConfig.getDocumentElement().getElementsByTagNameNS(IdPConfig.configNameSpace,
-                               "Logging");
-               Node errorLogNode = null;
-               boolean encounteredLog4JConfig = false;
-
-               if (itemElements.getLength() > 1) {
-                       log.warn("Encountered multiple <Logging> configuration elements. Using first one.");
-               }
-
-               if (itemElements.getLength() >= 1) {
-                       Node loggingNode = itemElements.item(0);
-
-                       for (int i = 0; i < loggingNode.getChildNodes().getLength(); i++) {
-                               Node node = loggingNode.getChildNodes().item(i);
-
-                               if ("Log4JConfig".equals(node.getNodeName())) {
-                                       doLog4JConfig(node);
-                                       encounteredLog4JConfig = true;
-                               } else if ("TransactionLog".equals(node.getNodeName())) {
-                                       configureTransactionLog(node);
-                               } else if ("ErrorLog".equals(node.getNodeName())) {
-                                       // make sure we do ErrorLog after TransactionLog so that the transaction log
-                                       // initialization info always gets logged in the same place
-                                       errorLogNode = node;
-                               }
-                       }
-               }
-
-               if (errorLogNode != null) {
-                       configureErrorLog(errorLogNode);
-               } else {
-                       // started out at INFO for logging config messages
-                       Logger.getRootLogger().setLevel((Level) Level.WARN);
-               }
-
-               // turn these off by default
-               if (!encounteredLog4JConfig) {
-                       Logger.getLogger("org.apache.xml.security").setLevel((Level) Level.OFF);
-                       Logger.getLogger("org.opensaml").setLevel((Level) Level.OFF);
-               }
-       }
-
-       private void configureErrorLog(Node node) throws ShibbolethConfigurationException {
-
-               NamedNodeMap attributes = node.getAttributes();
-
-               // schema check should catch if "location" is missing, NullPointerException here if not
-               String location = attributes.getNamedItem("location").getNodeValue();
-               DailyRollingFileAppender appender = null;
-               try {
-                       String logPath = new ShibResource(location, LoggingContextListener.class).getFile().getCanonicalPath();
-                       log.debug("logPath = " + logPath);
-                       appender = new DailyRollingFileAppender(new PatternLayout("%d{ISO8601} %-5p %-41X{serviceId} - %m%n"),
-                                       logPath, "'.'yyyy-MM-dd");
-               } catch (Exception e) { // catch any exception
-                       log.fatal("<ErrorLog location=\"" + location + "\">: error creating DailyRollingFileAppender: " + e);
-                       throw new ShibbolethConfigurationException("<ErrorLog location=\"" + location
-                                       + "\">: error creating DailyRollingFileAppender: " + e);
-               }
-               appender.setName("error");
-
-               Level level = (Level) Level.WARN;
-               if (attributes.getNamedItem("level") != null) {
-                       log.info("Setting error log level to " + attributes.getNamedItem("level").getNodeValue());
-                       level = Level.toLevel(attributes.getNamedItem("level").getNodeValue());
-                       Logger.getRootLogger().setLevel(level);
-               }
-
-               // log this before switching levels
-               log.info("Switching logging to " + appender.getFile());
-               Logger.getRootLogger().removeAllAppenders();
-               Logger.getRootLogger().addAppender(appender);
-
-               Logger.getRootLogger().setLevel(level);
-       }
-
-       private void configureTransactionLog(Node node) throws ShibbolethConfigurationException {
-
-               NamedNodeMap attributes = node.getAttributes();
-
-               // schema check should catch if "location" is missing, NullPointerException here if not
-               String location = attributes.getNamedItem("location").getNodeValue();
-               DailyRollingFileAppender appender = null;
-               try {
-                       String logPath = new ShibResource(attributes.getNamedItem("location").getNodeValue(),
-                                       LoggingContextListener.class).getFile().getCanonicalPath();
-                       log.debug("logPath = " + logPath);
-                       appender = new DailyRollingFileAppender(new PatternLayout("%d{ISO8601} %m%n"), logPath, "'.'yyyy-MM-dd");
-               } catch (Exception e) { // catch any exception
-                       log.fatal("<TransactionLog location=\"" + location + "\">: error creating DailyRollingFileAppender: " + e);
-                       throw new ShibbolethConfigurationException("<TransactionLog location=\"" + location
-                                       + "\">: error creating DailyRollingFileAppender: " + e);
-               }
-               appender.setName("transaction");
-
-               Logger log = Logger.getLogger("Shibboleth-TRANSACTION");
-               log.setAdditivity(false); // do not want parent's messages
-
-               // Standard transaction stuff is INFO, but some more detailed info is available via DEBUG
-               Level level = Level.INFO;
-               if (attributes.getNamedItem("level") != null) {
-                       log.info("Setting transaction log level to " + attributes.getNamedItem("level").getNodeValue());
-                       level = Level.toLevel(attributes.getNamedItem("level").getNodeValue());
-                       Logger.getRootLogger().setLevel(level);
-               }
-               log.setLevel(level);
-
-               // log.removeAllAppenders(); // imho we want these messages to appear in the "error" log if level >= INFO
-               log.addAppender(appender);
-       }
-
-       private void doLog4JConfig(Node node) throws ShibbolethConfigurationException {
-
-               NamedNodeMap attributes = node.getAttributes();
-
-               // schema check should catch if location is missing, NullPointerException here if not
-               String location = attributes.getNamedItem("location").getNodeValue();
-
-               String type = null;
-               if (attributes.getNamedItem("type") != null) {
-                       type = attributes.getNamedItem("type").getNodeValue();
-               }
-
-               URL url;
-               try {
-                       url = new URL(location);
-               } catch (MalformedURLException e) {
-                       log.fatal("<Log4JConfig location=\"" + location + "\">: not a valid URL: " + e);
-                       throw new ShibbolethConfigurationException("<Log4JConfig location=\"" + location + "\">: not a valid URL: "
-                                       + e);
-               }
-
-               if (type == null || "properties".equals(type)) {
-                       log.info("Using Properties log4j configuration from " + url);
-                       PropertyConfigurator.configure(url);
-               } else if ("xml".equals(type)) {
-                       log.info("Using XML log4j configuration from " + url);
-                       DOMConfigurator.configure(url);
-               }
-       }
-}
diff --git a/src/edu/internet2/middleware/shibboleth/log/LoggingInitializer.java b/src/edu/internet2/middleware/shibboleth/log/LoggingInitializer.java
new file mode 100644 (file)
index 0000000..3b421c8
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * The Shibboleth License, Version 1. Copyright (c) 2002 University Corporation for Advanced Internet Development, Inc.
+ * All rights reserved Redistribution and use in source and binary forms, with or without modification, are permitted
+ * provided that the following conditions are met: Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution, if any, must include the following acknowledgment: "This product includes software
+ * developed by the University Corporation for Advanced Internet Development <http://www.ucaid.edu>Internet2 Project.
+ * Alternately, this acknowledegement may appear in the software itself, if and wherever such third-party
+ * acknowledgments normally appear. Neither the name of Shibboleth nor the names of its contributors, nor Internet2, nor
+ * the University Corporation for Advanced Internet Development, Inc., nor UCAID may be used to endorse or promote
+ * products derived from this software without specific prior written permission. For written permission, please contact
+ * shibboleth@shibboleth.org Products derived from this software may not be called Shibboleth, Internet2, UCAID, or the
+ * University Corporation for Advanced Internet Development, nor may Shibboleth appear in their name, without prior
+ * written permission of the University Corporation for Advanced Internet Development. THIS SOFTWARE IS PROVIDED BY THE
+ * COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE
+ * DISCLAIMED AND THE ENTIRE RISK OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE. IN NO
+ * EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC.
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package edu.internet2.middleware.shibboleth.log;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.log4j.DailyRollingFileAppender;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.log4j.PatternLayout;
+import org.apache.log4j.PropertyConfigurator;
+import org.apache.log4j.xml.DOMConfigurator;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import edu.internet2.middleware.shibboleth.common.ShibResource;
+import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
+import edu.internet2.middleware.shibboleth.idp.IdPConfig;
+
+/**
+ * A helper class for configuring the the IdP transaction log, general system log, and any logs specified in a Log4J
+ * configuration file.
+ * <p>
+ * The IdP transaction log with the name <code>Shibboleth-TRANSACTION</code> and should be used to track an
+ * individuals path through the IdP. It's default logging level is <code>INFO</code>.
+ * <p>
+ * The general system log logs messages from any class in either the <code>edu.internet2.middleware.shibboleth</code>
+ * package or the <code>org.opensaml</code> package. It's default logging level is <code>WARN</code>
+ * <p>
+ * All logs are configured through information found in the IdP XML configuration file.
+ * 
+ * @author Chad La Joie
+ */
+public class LoggingInitializer {
+
+       /**
+        * Log message layout pattern for the transaction log
+        */
+       private static String txLogLayoutPattern = "%d{ISO8601} %m%n";
+
+       /**
+        * Date pattern used at the end of the transaction log filename
+        */
+       private static String txLogAppenderDatePattern = "'.'yyyy-MM-dd";
+
+       /**
+        * Log message layout pattern for the general system log
+        */
+       private static String sysLogLayoutPattern = "%d{ISO8601} %-5p %-41X{serviceId} - %m%n";
+
+       /**
+        * Date pattern used at the end of the general system log filename
+        */
+       private static String sysLogAppenderDatePattern = "'.'yyyy-MM-dd";
+
+       /**
+        * Initializes the Log4J logging framework.
+        * 
+        * @param configuration
+        *            logging configuration element from the IdP XML configuration file
+        * @throws ShibbolethConfigurationException
+        *             thrown if there is a problem configuring the logs
+        */
+       public static void initializeLogging(Element configuration) throws ShibbolethConfigurationException {
+
+               NodeList txLogElems = configuration.getElementsByTagNameNS(IdPConfig.configNameSpace, "TransactonLog");
+               if (txLogElems.getLength() > 0) {
+                       if (txLogElems.getLength() > 1) {
+                               System.err.println("WARNING: More than one TransactionLog element detected in IdP logging "
+                                               + "configuration, only the first one will be used.");
+                       }
+                       Element txLogConfig = (Element) txLogElems.item(0);
+                       configureTransactionLog(txLogConfig);
+               }
+
+               NodeList sysLogElems = configuration.getElementsByTagNameNS(IdPConfig.configNameSpace, "ErrorLog");
+               if (sysLogElems.getLength() > 0) {
+                       if (sysLogElems.getLength() > 1) {
+                               System.err.println("WARNING: More than one ErrorLog element detected in IdP logging configuration, "
+                                               + "only the first one will be used.");
+                       }
+                       Element sysLogConfig = (Element) sysLogElems.item(0);
+                       configureSystemLog(sysLogConfig);
+               }
+
+               NodeList log4jElems = configuration.getElementsByTagNameNS(IdPConfig.configNameSpace, "Log4JConfig");
+               if (log4jElems.getLength() > 0) {
+                       if (log4jElems.getLength() > 1) {
+                               System.err.println("WARNING: More than one Log4JConfig element detected in IdP logging configuration, "
+                                               + "only the first one will be used.");
+                       }
+                       Element log4jConfig = (Element) log4jElems.item(0);
+                       configureLog4J(log4jConfig);
+               }
+       }
+
+       /**
+        * Configures the transaction log.
+        * 
+        * @param configuration
+        *            the TransactionLog element from the IdP XML logging configuration
+        * @throws ShibbolethConfigurationException
+        *             thrown if there is a problem configuring the logs
+        */
+       private static void configureTransactionLog(Element configuration) throws ShibbolethConfigurationException {
+
+               NamedNodeMap attributes = configuration.getAttributes();
+
+               String location = attributes.getNamedItem("location").getNodeValue();
+               if (location == null) { throw new ShibbolethConfigurationException(
+                               "No log file location attribute specified in TransactionLog element"); }
+
+               DailyRollingFileAppender appender = null;
+               try {
+                       String logPath = new ShibResource(location, LoggingInitializer.class).getFile().getCanonicalPath();
+                       PatternLayout messageLayout = new PatternLayout(txLogLayoutPattern);
+
+                       appender = new DailyRollingFileAppender(messageLayout, logPath, txLogAppenderDatePattern);
+                       appender.setName("shibboleth-transaction");
+               } catch (Exception e) {
+                       throw new ShibbolethConfigurationException("<TransactionLog location=\"" + location
+                                       + "\">: error creating DailyRollingFileAppender: " + e);
+               }
+
+               Level level = Level.INFO;
+               if (attributes.getNamedItem("level") != null) {
+                       level = Level.toLevel(attributes.getNamedItem("level").getNodeValue());
+               }
+
+               Logger log = Logger.getLogger("Shibboleth-TRANSACTION");
+               log.setAdditivity(false); // do not want parent's messages
+               log.setLevel(level);
+               log.addAppender(appender);
+       }
+
+       /**
+        * Configures the system-wide IdP log.
+        * 
+        * @param configuration
+        *            the ErrorLog element from the IdP XML logging configuration
+        * @throws ShibbolethConfigurationException
+        *             thrown if there is a problem configuring the logs
+        */
+       private static void configureSystemLog(Element configuration) throws ShibbolethConfigurationException {
+
+               NamedNodeMap attributes = configuration.getAttributes();
+
+               String location = attributes.getNamedItem("location").getNodeValue();
+               if (location == null) { throw new ShibbolethConfigurationException(
+                               "No log file location attribute specified in ErrorLog element"); }
+
+               DailyRollingFileAppender appender = null;
+               try {
+                       String logPath = new ShibResource(location, LoggingInitializer.class).getFile().getCanonicalPath();
+                       PatternLayout messageLayout = new PatternLayout(sysLogLayoutPattern);
+
+                       appender = new DailyRollingFileAppender(messageLayout, logPath, sysLogAppenderDatePattern);
+                       appender.setName("shibboleth-error");
+               } catch (Exception e) { // catch any exception
+                       throw new ShibbolethConfigurationException("<ErrorLog location=\"" + location
+                                       + "\">: error creating DailyRollingFileAppender: " + e);
+               }
+
+               Level level = Level.WARN;
+               if (attributes.getNamedItem("level") != null) {
+                       level = Level.toLevel(attributes.getNamedItem("level").getNodeValue());
+               }
+
+               Logger shibLog = Logger.getLogger("edu.internet2.middleware.shibboleth");
+               shibLog.setLevel(level);
+               shibLog.addAppender(appender);
+
+               Logger openSAMLLog = Logger.getLogger("org.opensaml");
+               openSAMLLog.setLevel(level);
+               openSAMLLog.addAppender(appender);
+       }
+
+       /**
+        * Configures Log4J by way of a Log4J specific configuration file.
+        * 
+        * @param configuration
+        *            the Log4JConfig element from the IdP XML logging configuration
+        * @throws ShibbolethConfigurationException
+        *             thrown if there is a problem configuring the logs
+        */
+       private static void configureLog4J(Element configuration) throws ShibbolethConfigurationException {
+
+               NamedNodeMap attributes = configuration.getAttributes();
+
+               String location = attributes.getNamedItem("location").getNodeValue();
+               if (location == null) { throw new ShibbolethConfigurationException(
+                               "No configuration file location attribute specified in Log4JConfig element"); }
+
+               String type = null;
+               Node typeNode = attributes.getNamedItem("type");
+               if (typeNode != null) {
+                       type = typeNode.getNodeValue();
+               }
+
+               URL url;
+               try {
+                       url = new URL(location);
+               } catch (MalformedURLException e) {
+                       throw new ShibbolethConfigurationException("<Log4JConfig location=\"" + location + "\">: not a valid URL: "
+                                       + e);
+               }
+
+               if (type == null || "properties".equals(type)) {
+                       PropertyConfigurator.configure(url);
+               } else if ("xml".equals(type)) {
+                       DOMConfigurator.configure(url);
+               }
+       }
+}
index 1201f4f..eddc82b 100644 (file)
@@ -1,50 +1,26 @@
-/* 
- * The Shibboleth License, Version 1. 
- * Copyright (c) 2002 
- * University Corporation for Advanced Internet Development, Inc. 
- * All rights reserved
- * 
- * 
- * Redistribution and use in source and binary forms, with or without 
- * modification, are permitted provided that the following conditions are met:
- * 
- * Redistributions of source code must retain the above copyright notice, this 
- * list of conditions and the following disclaimer.
- * 
- * Redistributions in binary form must reproduce the above copyright notice, 
- * this list of conditions and the following disclaimer in the documentation 
- * and/or other materials provided with the distribution, if any, must include 
- * the following acknowledgment: "This product includes software developed by 
- * the University Corporation for Advanced Internet Development 
- * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement 
- * may appear in the software itself, if and wherever such third-party 
- * acknowledgments normally appear.
- * 
- * Neither the name of Shibboleth nor the names of its contributors, nor 
- * Internet2, nor the University Corporation for Advanced Internet Development, 
- * Inc., nor UCAID may be used to endorse or promote products derived from this 
- * software without specific prior written permission. For written permission, 
- * please contact shibboleth@shibboleth.org
- * 
- * Products derived from this software may not be called Shibboleth, Internet2, 
- * UCAID, or the University Corporation for Advanced Internet Development, nor 
- * may Shibboleth appear in their name, without prior written permission of the 
- * University Corporation for Advanced Internet Development.
- * 
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
- * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
- * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK 
- * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE. 
- * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY 
- * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT, 
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/*
+ * The Shibboleth License, Version 1. Copyright (c) 2002 University Corporation for Advanced Internet Development, Inc.
+ * All rights reserved Redistribution and use in source and binary forms, with or without modification, are permitted
+ * provided that the following conditions are met: Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution, if any, must include the following acknowledgment: "This product includes software
+ * developed by the University Corporation for Advanced Internet Development <http://www.ucaid.edu>Internet2 Project.
+ * Alternately, this acknowledegement may appear in the software itself, if and wherever such third-party
+ * acknowledgments normally appear. Neither the name of Shibboleth nor the names of its contributors, nor Internet2, nor
+ * the University Corporation for Advanced Internet Development, Inc., nor UCAID may be used to endorse or promote
+ * products derived from this software without specific prior written permission. For written permission, please contact
+ * shibboleth@shibboleth.org Products derived from this software may not be called Shibboleth, Internet2, UCAID, or the
+ * University Corporation for Advanced Internet Development, nor may Shibboleth appear in their name, without prior
+ * written permission of the University Corporation for Advanced Internet Development. THIS SOFTWARE IS PROVIDED BY THE
+ * COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE
+ * DISCLAIMED AND THE ENTIRE RISK OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE. IN NO
+ * EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC.
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 package edu.internet2.middleware.shibboleth.utils;
@@ -54,8 +30,8 @@ import jargs.gnu.CmdLineParser;
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
 import java.io.PrintWriter;
-import java.net.URL;
 import java.net.MalformedURLException;
+import java.net.URL;
 import java.security.Principal;
 
 import org.apache.log4j.ConsoleAppender;
@@ -77,9 +53,9 @@ import edu.internet2.middleware.shibboleth.aa.arp.ArpProcessingException;
 import edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeResolver;
 import edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeResolverException;
 import edu.internet2.middleware.shibboleth.common.LocalPrincipal;
-import edu.internet2.middleware.shibboleth.common.IdPConfigLoader;
 import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
 import edu.internet2.middleware.shibboleth.idp.IdPConfig;
+import edu.internet2.middleware.shibboleth.idp.IdPConfigLoader;
 import edu.internet2.middleware.shibboleth.xml.Parser;
 
 /**
@@ -88,8 +64,8 @@ import edu.internet2.middleware.shibboleth.xml.Parser;
  * @author Walter Hoehn
  * @author Noah Levitt
  */
-public class ResolverTest 
-{
+public class ResolverTest {
+
        private static boolean debug = false;
        private static String resolverxml = null;
        private static String idpXml = null;
@@ -100,8 +76,8 @@ public class ResolverTest
        private static AttributeResolver resolver = null;
        private static ArpEngine arpEngine = null;
 
-       public static void main(String[] args) 
-       {
+       public static void main(String[] args) {
+
                parseCommandLine(args);
                initializeResolver();
                AAAttributeSet attributeSet = createAttributeSet();
@@ -112,8 +88,8 @@ public class ResolverTest
                printAttributes(System.out, attributeSet);
        }
 
-       private static void resolveAttributes(AAAttributeSet attributeSet)
-       {
+       private static void resolveAttributes(AAAttributeSet attributeSet) {
+
                Principal principal = new LocalPrincipal(user);
 
                resolver.resolveAttributes(principal, requester, attributeSet);
@@ -122,15 +98,14 @@ public class ResolverTest
                        if (arpEngine != null) {
                                arpEngine.filterAttributes(attributeSet, principal, requester, resourceUrl);
                        }
-               }
-               catch (ArpProcessingException e) {
+               } catch (ArpProcessingException e) {
                        System.err.println("Error applying Attribute Release Policy: " + e.getMessage());
                        System.exit(1);
                }
        }
 
-       private static void parseCommandLine(String[] args)
-       {
+       private static void parseCommandLine(String[] args) {
+
                CmdLineParser parser = new CmdLineParser();
 
                CmdLineParser.Option helpOption = parser.addBooleanOption('h', "help");
@@ -144,8 +119,7 @@ public class ResolverTest
 
                try {
                        parser.parse(args);
-               } 
-               catch (CmdLineParser.OptionException e) {
+               } catch (CmdLineParser.OptionException e) {
                        System.out.println(e.getMessage());
                        printUsage(System.out);
                        System.exit(1);
@@ -163,12 +137,12 @@ public class ResolverTest
                }
 
                // if --resolverxml and --file both specified, silently use --resolverxml
-               resolverxml = (String) parser.getOptionValue(resolverxmlOption); 
+               resolverxml = (String) parser.getOptionValue(resolverxmlOption);
                if (resolverxml == null) {
                        resolverxml = (String) parser.getOptionValue(fileOption);
                }
 
-               idpXml = (String) parser.getOptionValue(idpXmlOption); 
+               idpXml = (String) parser.getOptionValue(idpXmlOption);
 
                user = (String) parser.getOptionValue(userOption);
                requester = (String) parser.getOptionValue(requesterOption);
@@ -181,8 +155,8 @@ public class ResolverTest
        /**
         * Ensures that all required parameters were specified and successfully parsed.
         */
-       private static void checkRequired() 
-       {
+       private static void checkRequired() {
+
                if (user == null) {
                        System.out.println("Missing required parameter --user.");
                        System.out.println();
@@ -197,16 +171,15 @@ public class ResolverTest
                }
        }
 
-       private static AAAttributeSet createAttributeSet()
-       {
+       private static AAAttributeSet createAttributeSet() {
+
                String[] attributes = resolver.listRegisteredAttributeDefinitionPlugIns();
                AAAttributeSet attributeSet = new AAAttributeSet();
 
                for (int i = 0; i < attributes.length; i++) {
-                       try { 
+                       try {
                                attributeSet.add(new AAAttribute(attributes[i]));
-                       }
-                       catch (SAMLException e) {
+                       } catch (SAMLException e) {
                                System.err.println("Error creating AAAttribute (" + attributes[i] + "): " + e.getMessage());
                                System.exit(1);
                        }
@@ -215,8 +188,8 @@ public class ResolverTest
                return attributeSet;
        }
 
-       private static void initializeResolver()
-       {
+       private static void initializeResolver() {
+
                if (idpXml != null) {
                        try {
                                Document idpConfig = IdPConfigLoader.getIdPConfig(idpXml);
@@ -224,13 +197,13 @@ public class ResolverTest
 
                                resolver = new AttributeResolver(configuration);
 
-                               NodeList itemElements =
-                                       idpConfig.getDocumentElement().getElementsByTagNameNS(
-                                                       IdPConfig.configNameSpace,
-                                                       "ReleasePolicyEngine");
+                               NodeList itemElements = idpConfig.getDocumentElement().getElementsByTagNameNS(
+                                               IdPConfig.configNameSpace, "ReleasePolicyEngine");
 
                                if (itemElements.getLength() > 1) {
-                                       System.err.println("Warning: encountered multiple <ReleasePolicyEngine> configuration elements in (" + idpXml + "). Using first...");
+                                       System.err
+                                                       .println("Warning: encountered multiple <ReleasePolicyEngine> configuration elements in ("
+                                                                       + idpXml + "). Using first...");
                                }
 
                                if (itemElements.getLength() < 1) {
@@ -242,41 +215,33 @@ public class ResolverTest
                                if (resource != null) {
                                        resourceUrl = new URL(resource);
                                }
-                       } 
-                       catch (ShibbolethConfigurationException e) {
+                       } catch (ShibbolethConfigurationException e) {
                                System.err.println("Error loading IdP configuration file (" + idpXml + "): " + e.getMessage());
                                System.exit(1);
-                       }
-                       catch (AttributeResolverException e) {
+                       } catch (AttributeResolverException e) {
                                System.err.println("Error initializing the Attribute Resolver: " + e.getMessage());
                                System.exit(1);
-                       }
-                       catch (ArpException e) {
+                       } catch (ArpException e) {
                                System.err.println("Error initializing the ARP Engine: " + e.getMessage());
                                System.exit(1);
-                       }
-                       catch (MalformedURLException e) {
+                       } catch (MalformedURLException e) {
                                System.err.println("Specified resource URL is invalid: " + e.getMessage());
                                System.exit(1);
                        }
-               }
-               else {
+               } else {
                        try {
                                resolver = new AttributeResolver(resolverxml);
-                       } 
-                       catch (AttributeResolverException e) {
+                       } catch (AttributeResolverException e) {
                                System.err.println("Error initializing the Attribute Resolver: " + e.getMessage());
                                System.exit(1);
                        }
                }
        }
 
-       private static void printAttributes(PrintStream out, AAAttributeSet attributeSet)
-       {
-               try
-               {
-                       for (ShibAttributeIterator iterator = attributeSet.shibAttributeIterator(); iterator.hasNext();) 
-                       {
+       private static void printAttributes(PrintStream out, AAAttributeSet attributeSet) {
+
+               try {
+                       for (ShibAttributeIterator iterator = attributeSet.shibAttributeIterator(); iterator.hasNext();) {
                                AAAttribute attribute = iterator.nextShibAttribute();
                                Node node = attribute.toDOM();
 
@@ -288,15 +253,14 @@ public class ResolverTest
                                out.println(Parser.serialize(node));
                                out.println();
                        }
-               }
-               catch (SAMLException e) {
+               } catch (SAMLException e) {
                        System.err.println("Error creating SAML attribute: " + e.getMessage());
                        System.exit(1);
                }
        }
 
-       private static void configureLogging(boolean debugEnabled) 
-       {
+       private static void configureLogging(boolean debugEnabled) {
+
                ConsoleAppender rootAppender = new ConsoleAppender();
                rootAppender.setWriter(new PrintWriter(System.out));
                rootAppender.setName("stdout");
@@ -304,17 +268,17 @@ public class ResolverTest
 
                if (debugEnabled) {
                        Logger.getRootLogger().setLevel(Level.DEBUG);
-                       rootAppender.setLayout(new PatternLayout("%-5p %-41X{serviceId} %d{ISO8601} (%c:%L) - %m%n")); 
+                       rootAppender.setLayout(new PatternLayout("%-5p %-41X{serviceId} %d{ISO8601} (%c:%L) - %m%n"));
                } else {
                        Logger.getRootLogger().setLevel(Level.INFO);
                        Logger.getLogger("edu.internet2.middleware.shibboleth.aa.attrresolv").setLevel(Level.WARN);
-                       rootAppender.setLayout(new PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN)); 
+                       rootAppender.setLayout(new PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN));
                }
                Logger.getLogger("org.apache.xml.security").setLevel(Level.OFF);
        }
 
-       private static void printUsage(PrintStream out) 
-       {
+       private static void printUsage(PrintStream out) {
+
                // out.println("Tests an AA Attribute Resolver configuration.");
                out.println("Usage: resolvertest --user=USER {--idpXml=URL|--resolverxml=URL} [OPTION...]");
                out.println();
@@ -333,4 +297,3 @@ public class ResolverTest
                out.println("                            to any resource will be returned if not specified");
        }
 }
-