Configure logging with <Logging> element in origin.xml.
authornlevitt <nlevitt@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Mon, 16 Feb 2004 20:55:34 +0000 (20:55 +0000)
committernlevitt <nlevitt@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Mon, 16 Feb 2004 20:55:34 +0000 (20:55 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@896 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

src/conf/log4j.properties [deleted file]
src/conf/origin.xml
src/edu/internet2/middleware/shibboleth/aa/AAServlet.java
src/edu/internet2/middleware/shibboleth/common/OriginConfig.java [moved from src/edu/internet2/middleware/shibboleth/common/OriginComponent.java with 81% similarity]
src/edu/internet2/middleware/shibboleth/hs/HandleServlet.java
src/edu/internet2/middleware/shibboleth/log/LogServ.java [deleted file]
src/edu/internet2/middleware/shibboleth/log/LoggingContextListener.java [new file with mode: 0644]
src/schemas/origin.xsd
webAppConfig/all.xml
webAppConfig/origin.xml
webAppConfig/wayf.xml

diff --git a/src/conf/log4j.properties b/src/conf/log4j.properties
deleted file mode 100755 (executable)
index 6cb02d6..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-##
-#
-# Shibboleth Log4J configuration
-#
-##
-
-
-# Default configuration.  Sends logging output to STDOUT.
-
-log4j.rootCategory=WARN, stdout
-log4j.logger.org.apache.xml.security=OFF
-log4j.logger.org.opensaml=OFF
-log4j.appender.stdout=org.apache.log4j.ConsoleAppender
-log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
-log4j.appender.stdout.layout.ConversionPattern=%-5p %-41X{serviceId} %d{ISO8601} - %m%n
-
-
-# Security transactions can be logged to a separate log as well
-
-# log4j.logger.edu.internet2.middleware.shibboleth.TRANSACTION=INFO, transaction
-log4j.logger.edu.internet2.middleware.shibboleth.TRANSACTION=OFF
-log4j.appender.transaction=org.apache.log4j.RollingFileAppender
-log4j.appender.transaction.File=/tmp/shibboleth-origin.log
-log4j.appender.transaction.layout=org.apache.log4j.PatternLayout
-log4j.appender.transaction.layout.ConversionPattern=%d{ISO8601} %m%n
-
-# The following block represents an example of how to enable very verbose logging.
-
-#log4j.rootCategory=DEBUG, stdout
-#log4j.logger.org.apache.xml.security=OFF
-#log4j.appender.stdout=org.apache.log4j.ConsoleAppender
-#log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
-#log4j.appender.stdout.layout.ConversionPattern=%-5p %-41X{serviceId} %d{ISO8601} (%c:%L) - %m%n
-
-
-# The following block represents an example of how to direct logging output to a file.
-
-#log4j.rootCategory=INFO, file
-#log4j.logger.org.apache.xml.security=OFF
-#log4j.logger.org.opensaml=OFF
-#log4j.appender.file=org.apache.log4j.RollingFileAppender
-#log4j.appender.file.File=/var/log/shib.log
-#log4j.appender.file.MaxFileSize=100KB
-#log4j.appender.file.MaxBackupIndex=1
-#log4j.appender.file.layout=org.apache.log4j.PatternLayout
-#log4j.appender.file.layout.ConversionPattern=%-5p %-41X{serviceId} %d{ISO8601} - %m%n
-
-
-# Uncomment the following line to enable verbose debugging output concerning log4j initialization.
-
-#log4j.debug=TRUE
index c5ae7c8..bfb94dd 100644 (file)
@@ -1,29 +1,52 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<ShibbolethOriginConfig xmlns="urn:mace:shibboleth:origin:1.0" xmlns:cred="urn:mace:shibboleth:credentials:1.0" xmlns:name="urn:mace:shibboleth:namemapper:1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mace:shibboleth:origin:1.0 origin.xsd" 
-       AAUrl="http://therock.cc.columbia.edu:6666/shibboleth/AA" defaultRelyingParty="urn:mace:inqueue" 
+
+<ShibbolethOriginConfig 
+       xmlns="urn:mace:shibboleth:origin:1.0" 
+       xmlns:cred="urn:mace:shibboleth:credentials:1.0" 
+       xmlns:name="urn:mace:shibboleth:namemapper:1.0" 
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+       xsi:schemaLocation="urn:mace:shibboleth:origin:1.0 origin.xsd" 
+       AAUrl="http://therock.cc.columbia.edu:6666/shibboleth/AA" 
+       defaultRelyingParty="urn:mace:inqueue" 
        providerId="urn:mace:inqueue:shibdev.edu">
 
        <RelyingParty name="urn:mace:inqueue" signingCredential="foo">
                <HSNameFormat nameMapping="crypto"/>
        </RelyingParty>
-       
+
        <ReleasePolicyEngine>
                <ArpRepository implementation="edu.internet2.middleware.shibboleth.aa.arp.provider.FileSystemArpRepository">
                        <Path>/conf/arps/</Path>
                </ArpRepository>
        </ReleasePolicyEngine>
-       
-       <name:NameMapping xmlns="urn:mace:shibboleth:namemapper:1.0" id="crypto" format="urn:mace:shibboleth:1.0:nameIdentifier" type="SharedMemoryShibHandle" handleTTL="1800"/>
-       
+
+       <!--
+       <Logging>
+               <Log4JConfig location="file:///tmp/log4j.properties" />
+       </Logging>
+       <Logging>
+               <ErrorLog level="DEBUG" location="file:///tmp/shib-error.log" />
+               <TransactionLog location="file:///tmp/shib-access.log" />
+       </Logging>
+       -->
+
+       <name:NameMapping 
+               xmlns="urn:mace:shibboleth:namemapper:1.0" 
+               id="crypto" 
+               format="urn:mace:shibboleth:1.0:nameIdentifier" 
+               type="SharedMemoryShibHandle" 
+               handleTTL="1800"/>
+
        <cred:Credentials xmlns="urn:mace:shibboleth:credentials:1.0">
                <FileResolver Id="foo">
-               <Key format="DER">
-                       <Path>/conf/shib2.key</Path>
-               </Key>
-               <Certificate format="PEM">
-                       <Path>/conf/shib2.crt</Path>
-               </Certificate>
-       </FileResolver>
+                       <Key format="DER">
+                               <Path>/conf/shib2.key</Path>
+                       </Key>
+                       <Certificate format="PEM">
+                               <Path>/conf/shib2.crt</Path>
+                       </Certificate>
+               </FileResolver>
        </cred:Credentials>
 
 </ShibbolethOriginConfig>
+
index e6ddeba..7b77efc 100755 (executable)
@@ -49,6 +49,7 @@ import java.util.Iterator;
 
 import javax.servlet.ServletException;
 import javax.servlet.UnavailableException;
+import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
@@ -81,7 +82,7 @@ import edu.internet2.middleware.shibboleth.common.AuthNPrincipal;
 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.OriginComponent;
+import edu.internet2.middleware.shibboleth.common.OriginConfig;
 import edu.internet2.middleware.shibboleth.common.RelyingParty;
 import edu.internet2.middleware.shibboleth.common.SAMLBindingFactory;
 import edu.internet2.middleware.shibboleth.common.ServiceProviderMapperException;
@@ -92,7 +93,7 @@ import edu.internet2.middleware.shibboleth.common.ShibbolethOriginConfig;
  * @author Walter Hoehn
  */
 
-public class AAServlet extends OriginComponent {
+public class AAServlet extends HttpServlet {
 
        private AAConfig configuration;
        protected AAResponder responder;
@@ -128,7 +129,7 @@ public class AAServlet extends OriginComponent {
 
        protected void loadConfiguration() throws ShibbolethConfigurationException {
 
-               Document originConfig = getOriginConfig();
+               Document originConfig = OriginConfig.getOriginConfig(this.getServletContext());
 
                //Load global configuration properties
                configuration = new AAConfig(originConfig.getDocumentElement());
@@ -52,6 +52,7 @@ import java.io.InputStream;
 import java.util.StringTokenizer;
 
 import javax.servlet.http.HttpServlet;
+import javax.servlet.ServletContext;
 
 import org.apache.log4j.Logger;
 import org.apache.xerces.parsers.DOMParser;
@@ -63,14 +64,29 @@ import org.xml.sax.SAXParseException;
 import org.w3c.dom.Document;
 
 /**
- * Shared functionality for origin components.
+ * Constructs a DOM tree for the origin configuration XML file.
  * 
  * @author Walter Hoehn
+ * @author Noah Levitt
  */
-public abstract class OriginComponent extends HttpServlet {
+public class OriginConfig {
 
-       private static Logger log = Logger.getLogger(OriginComponent.class.getName());
+       private static Logger log = Logger.getLogger(OriginConfig.class);
        private static Document originConfig = null;
+        private static String originConfigFile = null;
+
+       // never returns null
+       private static String getOriginConfigFile(ServletContext context)
+       {
+               if (context.getInitParameter("OriginConfigFile") != null)
+               {
+                       return context.getInitParameter("OriginConfigFile");
+               }
+               else
+               {
+                       return "/conf/origin.xml";
+               }
+       }
 
        /**
         * Loads the Origin Configuration file into a DOM tree.
@@ -79,14 +95,23 @@ public abstract class OriginComponent extends HttpServlet {
         * @throws ShibbolethConfigurationException
         *             if there was an error loading the file
         */
-       protected synchronized Document getOriginConfig() throws ShibbolethConfigurationException {
-               /*
-                * synchronized to make sure only one thread attempts to parse the
-                * config file
-                */
-               if (originConfig != null) {
+       public static synchronized Document getOriginConfig(ServletContext context) throws ShibbolethConfigurationException 
+       {
+               if (getOriginConfigFile(context).equals(originConfigFile))
+               {
                        return originConfig;
                }
+               else if (originConfigFile == null)
+               {
+                       originConfigFile = getOriginConfigFile(context);
+               }
+               else 
+               {
+                       log.error("Previously read origin configuration from (" + originConfigFile + "), re-reading from (" + getOriginConfigFile(context) + "). This probably indicates a bug in shibboleth.");
+                       originConfigFile = getOriginConfigFile(context);
+               }
+
+               originConfigFile = context.getInitParameter("OriginConfigFile");
 
                DOMParser parser = new DOMParser();
 
@@ -106,7 +131,7 @@ public abstract class OriginComponent extends HttpServlet {
                                                if (xsdFile.endsWith(".xsd")) {
                                                        InputStream stream;
                                                        try {
-                                                               stream = new ShibResource("/schemas/" + xsdFile, this.getClass()).getInputStream();
+                                                               stream = new ShibResource("/schemas/" + xsdFile, OriginConfig.class).getInputStream();
                                                        } catch (IOException ioe) {
                                                                log.error("Error loading schema: " + xsdFile + ": " + ioe);
                                                                return null;
@@ -137,18 +162,13 @@ public abstract class OriginComponent extends HttpServlet {
                        throw new ShibbolethConfigurationException("Unable to setup a workable XML parser.");
                }
 
-               String originConfigFile = getInitParameter("OriginConfigFile");
-               if (originConfigFile == null) {
-                       originConfigFile = "/conf/origin.xml";
-               }
-
                log.debug("Loading Configuration from (" + originConfigFile + ").");
 
                try {
-                       parser.parse(new InputSource(new ShibResource(originConfigFile, this.getClass()).getInputStream()));
+                       parser.parse(new InputSource(new ShibResource(originConfigFile, OriginConfig.class).getInputStream()));
                } catch (SAXException e) {
                        log.error("Error while parsing origin configuration: " + e);
-                       throw new ShibbolethConfigurationException("Error while parsing origin configuration.");
+                       throw new ShibbolethConfigurationException("Error while parsing origin configuration:" + e);
                } catch (IOException e) {
                        log.error("Could not load origin configuration: " + e);
                        throw new ShibbolethConfigurationException("Could not load origin configuration.");
@@ -157,5 +177,5 @@ public abstract class OriginComponent extends HttpServlet {
                originConfig = parser.getDocument();
 
                return originConfig;
-       }
+        }
 }
index a117776..5010fe2 100644 (file)
@@ -44,6 +44,7 @@ import java.util.Date;
 import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletException;
 import javax.servlet.UnavailableException;
+import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
@@ -66,15 +67,15 @@ import edu.internet2.middleware.shibboleth.common.AuthNPrincipal;
 import edu.internet2.middleware.shibboleth.common.Credentials;
 import edu.internet2.middleware.shibboleth.common.NameIdentifierMapping;
 import edu.internet2.middleware.shibboleth.common.NameIdentifierMappingException;
-import edu.internet2.middleware.shibboleth.common.OriginComponent;
+import edu.internet2.middleware.shibboleth.common.OriginConfig;
 import edu.internet2.middleware.shibboleth.common.ServiceProviderMapperException;
 import edu.internet2.middleware.shibboleth.common.ShibPOSTProfile;
 import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
 
-public class HandleServlet extends OriginComponent {
+public class HandleServlet extends HttpServlet {
 
        private static Logger log = Logger.getLogger(HandleServlet.class.getName());
-       private static Logger transactionLog = Logger.getLogger("edu.internet2.middleware.shibboleth.TRANSACTION");
+       private static Logger transactionLog = Logger.getLogger("Shibboleth-TRANSACTION");
 
        private Semaphore throttle;
        private HSConfig configuration;
@@ -85,7 +86,7 @@ public class HandleServlet extends OriginComponent {
 
        protected void loadConfiguration() throws ShibbolethConfigurationException {
 
-               Document originConfig = getOriginConfig();
+               Document originConfig = OriginConfig.getOriginConfig(this.getServletContext());
 
                //Load global configuration properties
                configuration = new HSConfig(originConfig.getDocumentElement());
diff --git a/src/edu/internet2/middleware/shibboleth/log/LogServ.java b/src/edu/internet2/middleware/shibboleth/log/LogServ.java
deleted file mode 100755 (executable)
index 27adbdc..0000000
+++ /dev/null
@@ -1,100 +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.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.UnavailableException;
-import javax.servlet.http.HttpServlet;
-
-import org.apache.log4j.Logger;
-import org.apache.log4j.MDC;
-import org.apache.log4j.PropertyConfigurator;
-import org.apache.xml.security.Init;
-
-import edu.internet2.middleware.shibboleth.common.ShibResource;
-
-/**
- * 
- * Servlet used to configure logging for other components.
- * 
- * @author Walter Hoehn
- *
- */
-public class LogServ extends HttpServlet {
-
-       private static Logger log = Logger.getLogger(LogServ.class.getName());
-
-       /**
-        * @see javax.servlet.GenericServlet#init()
-        */
-       public void init() throws ServletException {
-
-               super.init();
-               //Silliness to get around xmlsec doing its own configuration, ie: we might need to override it
-               Init.init();
-               String log4jConfigFileLocation = getServletConfig().getInitParameter("log4jConfigFileLocation");
-               if (log4jConfigFileLocation == null) {
-                       log4jConfigFileLocation = "/conf/log4j.properties";
-               }
-               try {
-                       PropertyConfigurator.configure(new ShibResource(log4jConfigFileLocation, this.getClass()).getURL());
-               } catch (IOException e) {
-                       getServletContext().log("Could not load Logger configuration from supplied location.", e);
-                       System.err.println("Could not load Logger configuration from supplied location: " + e);
-                       throw new UnavailableException("Could not load Logger configuration from supplied location: " + e);
-               }
-               MDC.put("serviceId", "[Logger] Core");
-               log.info("Logger initialized.");
-       }
-
-}
-
diff --git a/src/edu/internet2/middleware/shibboleth/log/LoggingContextListener.java b/src/edu/internet2/middleware/shibboleth/log/LoggingContextListener.java
new file mode 100644 (file)
index 0000000..1b29773
--- /dev/null
@@ -0,0 +1,269 @@
+/* 
+ * 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.IOException;
+import java.io.PrintWriter;
+import java.io.File;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.Level;
+import org.apache.log4j.ConsoleAppender;
+import org.apache.log4j.PropertyConfigurator;
+import org.apache.log4j.PatternLayout;
+import org.apache.log4j.RollingFileAppender;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.xml.DOMConfigurator;
+
+import org.apache.xml.security.Init;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.NamedNodeMap;
+
+import edu.internet2.middleware.shibboleth.common.OriginConfig;
+import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
+import edu.internet2.middleware.shibboleth.common.ShibbolethOriginConfig;
+import edu.internet2.middleware.shibboleth.common.ShibResource;
+
+/**
+ * {@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)
+       {
+               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"));
+
+               Logger.getLogger("org.apache.xml.security").setLevel((Level) Level.OFF);
+               Logger.getLogger("org.opensaml").setLevel((Level) Level.OFF);
+
+               //Silliness to get around xmlsec doing its own configuration, ie: we might need to override it
+               Init.init();
+
+               try {
+                       Document originConfig = OriginConfig.getOriginConfig(sce.getServletContext());
+                       loadConfiguration(originConfig);
+               } 
+                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);  // XXX
+               }
+
+               log.info("Logger initialized.");
+       }
+
+       public void contextDestroyed(ServletContextEvent sce)
+       {
+            log.info("Shutting down logging infrastructure.");
+            LogManager.shutdown();
+       }
+
+       protected void loadConfiguration(Document originConfig) throws ShibbolethConfigurationException
+       {
+               NodeList itemElements = originConfig.getDocumentElement().getElementsByTagNameNS(ShibbolethOriginConfig.originConfigNamespace, "Logging");
+               if (itemElements.getLength() > 1) 
+               {
+                       log.warn("Encountered multiple <Logging> configuration elements. Using first one.");
+               }
+
+               if (itemElements.getLength() >= 1) 
+               {
+                       Node loggingNode = itemElements.item(0);
+                       Node errorLogNode = null;
+
+                       for (int i = 0; i < loggingNode.getChildNodes().getLength(); i++)
+                       {
+                               Node node = loggingNode.getChildNodes().item(i);
+
+                               if ("Log4JConfig".equals(node.getNodeName()))
+                               {
+                                       doLog4JConfig(node);
+                               }
+                               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);
+                       }
+               }
+       }
+
+       // location should be a "file:/" uri
+       private RollingFileAppender makeRollingFileAppender(String location, String pattern) throws ShibbolethConfigurationException
+       {
+               try {
+                       String logPath = new ShibResource(location, LoggingContextListener.class).getFile().getCanonicalPath();
+                       RollingFileAppender appender = new RollingFileAppender(new PatternLayout(pattern), logPath);
+
+                       appender.setMaximumFileSize(1024*1024);        // 1 megabyte
+                       appender.setMaxBackupIndex(Integer.MAX_VALUE); // imho we should not delete any log files
+
+                       return appender;
+               }
+               catch (IOException e) {
+                       log.fatal("<TransactionLog location=\"" + location + "\">: error creating RollingFileAppender: " + e);
+                       throw new ShibbolethConfigurationException("<TransactionLog location=\"" + location + "\">: error creating RollingFileAppender: " + e);
+               }
+       }
+
+       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();
+               RollingFileAppender appender = makeRollingFileAppender(location, "%d{ISO8601} %-5p %-41X{serviceId} - %m%n");
+
+               appender.setName("error");
+               appender.setMaxBackupIndex(Integer.MAX_VALUE); // imho we should not delete any log files
+
+               Level level = (Level) Level.WARN;
+               if (attributes.getNamedItem("level") != null)
+               {
+                       log.info("Setting 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();
+               RollingFileAppender appender = makeRollingFileAppender(location, "%d{ISO8601} %m%n");
+               appender.setName("transaction");
+
+               Logger log = Logger.getLogger("Shibboleth-TRANSACTION");
+               log.setAdditivity(false);         // do not want parent's messages
+               log.setLevel((Level) Level.INFO); // all messages to this log are INFO
+
+               // 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);
+               }
+       }
+}
+
index 3fdc28c..42b79d1 100644 (file)
@@ -1,7 +1,43 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<xs:schema targetNamespace="urn:mace:shibboleth:origin:1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:credentials="urn:mace:shibboleth:credentials:1.0" xmlns:namemapper="urn:mace:shibboleth:namemapper:1.0" xmlns:origin="urn:mace:shibboleth:origin:1.0" elementFormDefault="qualified" attributeFormDefault="unqualified">
+<xs:schema 
+       targetNamespace="urn:mace:shibboleth:origin:1.0" 
+       xmlns:xs="http://www.w3.org/2001/XMLSchema" 
+       xmlns:credentials="urn:mace:shibboleth:credentials:1.0" 
+       xmlns:namemapper="urn:mace:shibboleth:namemapper:1.0" 
+       xmlns:origin="urn:mace:shibboleth:origin:1.0" 
+       elementFormDefault="qualified" 
+       attributeFormDefault="unqualified">
+
        <xs:import namespace="urn:mace:shibboleth:credentials:1.0" schemaLocation="credentials.xsd"/>
        <xs:import namespace="urn:mace:shibboleth:namemapper:1.0" schemaLocation="namemapper.xsd"/>
+
+       <xs:simpleType name="LevelType">
+               <xs:restriction base="xs:string">
+                       <xs:enumeration value="OFF"/>
+                       <xs:enumeration value="FATAL"/>
+                       <xs:enumeration value="ERROR"/>
+                       <xs:enumeration value="WARN"/>
+                       <xs:enumeration value="INFO"/>
+                       <xs:enumeration value="DEBUG"/>
+               </xs:restriction>
+       </xs:simpleType>
+
+       <xs:complexType name="LogWithLevels">
+               <xs:attribute name="location" type="xs:anyURI" use="required" />
+               <xs:attribute name="level" type="origin:LevelType" use="optional" default="WARN" />
+       </xs:complexType>
+
+       <xs:complexType name="Log">
+               <xs:attribute name="location" type="xs:anyURI" use="required"/>
+       </xs:complexType>
+
+       <xs:simpleType name="Log4JConfigType">
+               <xs:restriction base="xs:string">
+                       <xs:enumeration value="properties"/>
+                       <xs:enumeration value="xml"/>
+               </xs:restriction>
+       </xs:simpleType>
+
        <xs:element name="ShibbolethOriginConfig">
                <xs:annotation>
                        <xs:documentation>Configures the Shibboleth Origin software.</xs:documentation>
                                                </xs:sequence>
                                        </xs:complexType>
                                </xs:element>
+
+                               <xs:element name="Logging" minOccurs="0" maxOccurs="1">
+                                       <xs:complexType>
+                                               <xs:choice>
+                                                       <xs:sequence>
+                                                               <xs:element name="ErrorLog" type="origin:LogWithLevels" minOccurs="0" maxOccurs="1" />
+                                                               <xs:element name="TransactionLog" type="origin:Log" minOccurs="0" maxOccurs="1" />
+                                                       </xs:sequence>
+                                                       <xs:element name="Log4JConfig">
+                                                               <xs:complexType>
+                                                                       <xs:attribute name="type" type="origin:Log4JConfigType" use="optional" default="properties" />
+                                                                       <xs:attribute name="location" type="xs:anyURI" use="required" />
+                                                               </xs:complexType>
+                                                       </xs:element>
+                                               </xs:choice>
+                                       </xs:complexType>
+                               </xs:element>
+
                                <xs:sequence>
                                        <xs:element ref="namemapper:NameMapping" maxOccurs="unbounded"/>
                                </xs:sequence>
+
                                <xs:element ref="credentials:Credentials"/>
+
                        </xs:sequence>
+
                        <xs:attribute name="resolverConfig" type="xs:string" use="optional" default="/conf/resolver.xml"/>
                        <xs:attribute name="AAUrl" type="xs:anyURI" use="optional"/>
                        <xs:attribute name="providerId" type="xs:anyURI" use="required"/>
                        <xs:attribute name="maxHSThreads" type="xs:integer" use="optional"/>
                </xs:complexType>
        </xs:element>
+
 </xs:schema>
index 3775417..d88cbed 100755 (executable)
@@ -5,15 +5,11 @@
     "http://java.sun.com/dtd/web-app_2_3.dtd">
 
 <web-app>
-       <servlet>
-               <servlet-name>Logging Service</servlet-name>
-               <servlet-class>edu.internet2.middleware.shibboleth.log.LogServ</servlet-class>
-               <init-param>
-                       <param-name>log4jConfigFileLocation</param-name>
-                       <param-value>/conf/log4j.properties</param-value>
-               </init-param>
-               <load-on-startup>1</load-on-startup>
-       </servlet>
+
+       <listener> 
+               <listener-class>edu.internet2.middleware.shibboleth.log.LoggingContextListener</listener-class> 
+       </listener>
+
        <servlet>
                <servlet-name>HS</servlet-name>
                <display-name>Shibboleth Handle Service</display-name>
                <display-name>Shibboleth Attribute Authority</display-name>
                <servlet-class>edu.internet2.middleware.shibboleth.aa.AAServlet</servlet-class>
        </servlet>
-       
+
        <servlet>
                <servlet-name>WAYF</servlet-name>
                <display-name>Shibboleth WAYF Service</display-name>
                <servlet-class>edu.internet2.middleware.shibboleth.wayf.WayfService</servlet-class>
-                <init-param>
-                    <param-name>SiteConfigFileLocation</param-name>
-                    <param-value>/conf/sites.xml</param-value>
-                </init-param>
+               <init-param>
+                       <param-name>SiteConfigFileLocation</param-name>
+                       <param-value>/conf/sites.xml</param-value>
+               </init-param>
        </servlet>
-       
-     <servlet-mapping>
+
+       <servlet-mapping>
                <servlet-name>WAYF</servlet-name>
                <url-pattern>/WAYF</url-pattern>
        </servlet-mapping>
-     <servlet-mapping>
+       <servlet-mapping>
                <servlet-name>HS</servlet-name>
                <url-pattern>/HS</url-pattern>
        </servlet-mapping>
@@ -47,7 +43,7 @@
                <servlet-name>AA</servlet-name>
                <url-pattern>/AA</url-pattern>
        </servlet-mapping>
-       
+
        <mime-mapping>
                <extension>css</extension>
                <mime-type>text/css</mime-type>
index 1ead141..42f27f3 100755 (executable)
@@ -5,15 +5,15 @@
     "http://java.sun.com/dtd/web-app_2_3.dtd">
 
 <web-app>
-       <servlet>
-               <servlet-name>Logging Service</servlet-name>
-               <servlet-class>edu.internet2.middleware.shibboleth.log.LogServ</servlet-class>
-               <init-param>
-                       <param-name>log4jConfigFileLocation</param-name>
-                       <param-value>/conf/log4j.properties</param-value>
-               </init-param>
-               <load-on-startup>1</load-on-startup>
-       </servlet>
+       <context-param>
+               <param-name>OriginConfigFile</param-name>
+               <param-value>/conf/origin.xml</param-value>
+       </context-param>
+
+       <listener> 
+               <listener-class>edu.internet2.middleware.shibboleth.log.LoggingContextListener</listener-class> 
+       </listener>
+
        <servlet>
                <servlet-name>HS</servlet-name>
                <display-name>Shibboleth Handle Service</display-name>
@@ -24,8 +24,8 @@
                <display-name>Shibboleth Attribute Authority</display-name>
                <servlet-class>edu.internet2.middleware.shibboleth.aa.AAServlet</servlet-class>
        </servlet>
-       
-     <servlet-mapping>
+
+       <servlet-mapping>
                <servlet-name>HS</servlet-name>
                <url-pattern>/HS</url-pattern>
        </servlet-mapping>
@@ -33,7 +33,7 @@
                <servlet-name>AA</servlet-name>
                <url-pattern>/AA</url-pattern>
        </servlet-mapping>
-       
+
        <mime-mapping>
                <extension>css</extension>
                <mime-type>text/css</mime-type>
index e945daf..03234fb 100755 (executable)
@@ -5,31 +5,25 @@
     "http://java.sun.com/dtd/web-app_2_3.dtd">
 
 <web-app>
-       <servlet>
-               <servlet-name>Logging Service</servlet-name>
-               <servlet-class>edu.internet2.middleware.shibboleth.log.LogServ</servlet-class>
-               <init-param>
-                       <param-name>log4jConfigFileLocation</param-name>
-                       <param-value>/conf/log4j.properties</param-value>
-               </init-param>
-               <load-on-startup>1</load-on-startup>
-       </servlet>
-       
+       <listener> 
+               <listener-class>edu.internet2.middleware.shibboleth.log.LoggingContextListener</listener-class> 
+       </listener>
+
        <servlet>
                <servlet-name>WAYF</servlet-name>
                <display-name>Shibboleth WAYF Service</display-name>
                <servlet-class>edu.internet2.middleware.shibboleth.wayf.WayfService</servlet-class>
-                <init-param>
-                    <param-name>SiteConfigFileLocation</param-name>
-                    <param-value>/conf/sites.xml</param-value>
-                </init-param>
+               <init-param>
+                       <param-name>SiteConfigFileLocation</param-name>
+                       <param-value>/conf/sites.xml</param-value>
+               </init-param>
        </servlet>
-       
-     <servlet-mapping>
+
+       <servlet-mapping>
                <servlet-name>WAYF</servlet-name>
                <url-pattern>/WAYF</url-pattern>
        </servlet-mapping>
-       
+
        <mime-mapping>
                <extension>css</extension>
                <mime-type>text/css</mime-type>