Merged V3.1 to HEAD

12898: Cleaned up svn:mergeinfo
   12905: Added 'js' to svn:ignore
   12916: Divorced repositories [sic] Log4J extension point from Log4J imports
   12939: Build/test fix (follow on from r12899)
   12945: Merged V2.1-A to V3.1
      7720: (record-only) Customer-specific request to allow domains to be case-sensitive
   12946: fix for ETHREEOH-1227 (bunch of FTL and JS files by Lawrence)
   12949: Merged V2.1-A to V3.1
      8123: (record-only) Allow authorities that are identical ignoring case (as we do in 2.2)
   ___________________________________________________________________
   Modified: svn:mergeinfo
      Merged /alfresco/BRANCHES/V2.1-A:r7720,8123
      Merged /alfresco/BRANCHES/V3.1:r12898,12905,12916,12939,12945-12946,12949


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13536 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2009-03-10 16:26:40 +00:00
parent 800c11f884
commit 42fa774d76
7 changed files with 180 additions and 236 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
* Copyright (C) 2005-2008 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -15,205 +15,138 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.admin;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import org.apache.log4j.jmx.HierarchyDynamicMBean;
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.spi.LoggerRepository;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
/**
* Initialises Log4j's HierarchyDynamicMBean (refer to core-services-context.xml)
* and any overriding log4.properties files.
* Initialises Log4j's HierarchyDynamicMBean (refer to core-services-context.xml) and any overriding log4.properties files.
* The actual implementation uses introspection to avoid any hard-coded references to Log4J classes. If Log4J is
* not present, this class will do nothing.
* <p>
* Alfresco modules can provide their own log4j.properties file,
* which augments/overrides the global log4j.properties within
* the Alfresco webapp. Within the module's source tree, suppose
* you create:<pre>
* config/alfresco/module/{module.id}/log4j.properties</pre>
* At deployment time, this log4j.properties file will be placed in:<pre>
* WEB-INF/classes/alfresco/module/{module.id}/log4j.properties</pre>
* Where {module.id} is whatever value is set within the AMP's
* module.properties file. For details, see:
* <a href='http://wiki.alfresco.com/wiki/Developing_an_Alfresco_Module'>Developing an Alfresco Module</a>
* <p>
* For example, if {module.id} is "org.alfresco.module.avmCompare", then
* within your source code you'll have:<pre>
* config/alfresco/module/org.alfresco.module.avmCompare/log4j.properties</pre>
* This would be deployed to:<pre>
* WEB-INF/classes/alfresco/module/org.alfresco.module.avmCompare/log4j.properties</pre>
* By default the 'overriding_log4j_properties' property of the
* 'log4JHierarchyInit' bean within core-services-context.xml is:<pre>
* classpath&#042;:alfresco/module/&#042;/log4j.properties</pre>
* Therefore, Log4JHierarchyInit will discover this supplimentary log4j.properties
* file, and merge it with the main log4j.file (WEB-INF/classes/log4j.properties).
* For example, the org.alfresco.module.avmCompare log4j.properties file might look like this:
* Alfresco modules can provide their own log4j.properties file, which augments/overrides the global log4j.properties
* within the Alfresco webapp. Within the module's source tree, suppose you create:
* <pre>
* #-----------------------------------------------------------------------
* # webscript module log4j.properties
* #
* # NOTE
* # ----
* #
* # Log4j uses the following logging levels:
* # debug,info,warn,error,fatal
* #
* # To set the logging level of {fullClassName} to {loglevel},
* # add a line to this file of the following form:
* #
* # log4j.logger.{fullClassName}={loglevel}
* #
* # For example, to make 'com.example.MyExample' produce 'debug'
* # logs, add a line like this:
* #
* # log4j.logger.com.example.MyExample=debug
* #
* #
* # WARNING
* # -------
* # Log properties in this log4j.properties file override/augment
* # those in the webapp's main log4j.properties.
* #
* #-----------------------------------------------------------------------
*
* log4j.logger.org.alfresco.module.avmCompare.AvmCompare=info
* </pre>
*
* This system allows the author of any module to provide rich logging control
* without concern for corrupting the central log4j.properties file during
* AMP installation/deinstallation. For details, see:
* <a href='http://wiki.alfresco.com/wiki/Module_Management_Tool'>Module Management Tool</a>
* config/alfresco/module/{module.id}/log4j.properties
* </pre>
* At deployment time, this log4j.properties file will be placed in:
* <pre>
* WEB-INF/classes/alfresco/module/{module.id}/log4j.properties
* </pre>
* Where {module.id} is whatever value is set within the AMP's module.properties file. For details, see: <a
* href='http://wiki.alfresco.com/wiki/Developing_an_Alfresco_Module'>Developing an Alfresco Module</a>
* <p>
* For example, if {module.id} is "org.alfresco.module.avmCompare", then within your source code you'll have:
*
* <pre>
* config / alfresco / module / org.alfresco.module.avmCompare / log4j.properties
* </pre>
*
* This would be deployed to:
* <pre>
* WEB - INF / classes / alfresco / module / org.alfresco.module.avmCompare / log4j.properties
* </pre>
*/
public class Log4JHierarchyInit
{
private HierarchyDynamicMBean log4jHierarchy;
private List<String> extra_log4j_urls;
public Log4JHierarchyInit()
{
extra_log4j_urls = new ArrayList<String>();
}
private static Log logger = LogFactory.getLog(Log4JHierarchyInit.class);
private List<String> extraLog4jUrls;
public Log4JHierarchyInit()
{
extraLog4jUrls = new ArrayList<String>();
}
/**
* Loads a set of augmenting/overriding log4j.properties files
* from locations specified via an array of 'spring_urls'
* (typically provided by a core-services-context.xml).
*
* This function supports Spring's syntax for retrieving
* multiple class path resources with the same name,
* via the "classpath&#042;:" prefix. For details, see:
* <a href='http://www.jdocs.com/spring/1.2.8/org/springframework/core/io/support/PathMatchingResourcePatternResolver.html'>PathMatchingResourcePatternResolver</a>.
*/
public void setOverriding_log4j_properties(List<String> spring_urls)
* Loads a set of augmenting/overriding log4j.properties files from locations specified via an array of Srping URLS.
* <p>
* This function supports Spring's syntax for retrieving multiple class path resources with the same name,
* via the "classpath&#042;:" prefix. For details, see: {@link PathMatchingResourcePatternResolver}.
*/
public void setExtraLog4jUrls(List<String> urls)
{
for ( String url : spring_urls ) { extra_log4j_urls.add( url ); }
for (String url : urls)
{
extraLog4jUrls.add(url);
}
}
public void setLog4jHierarchy(HierarchyDynamicMBean log4jHierarchy)
{
this.log4jHierarchy = log4jHierarchy;
}
@SuppressWarnings("unchecked")
public void init()
{
// Add each logger (that has a level set) from
// the Log4J Repository to the Hierarchy MBean
importLogSettings();
}
LoggerRepository r = LogManager.getLoggerRepository();
// Include overriding loggers
//
// Typically, extra loggers come from AMP modules, but you
// could add others by augmenting core-services-context.xml
// This mechanism allows modules to have their own local
// log4j.properties file within:
//
// WEB-INF/classes/alfresco/module/{module.id}/log4j.properties
//
// Where: module.id is whatever value is set within the AMP's
// 'module.properties' file.
//
// See also:
// http://wiki.alfresco.com/wiki/Developing_an_Alfresco_Module
// (the module.properties section)
//
// And:
// core-services-context.xml
set_overriding_loggers( r );
Enumeration loggers = r.getCurrentLoggers();
Logger logger = null;
while (loggers.hasMoreElements())
@SuppressWarnings("unchecked")
private void importLogSettings()
{
try
{
logger = (Logger)loggers.nextElement();
if (logger.getLevel() != null)
// Get the PropertyConfigurator
Class clazz = Class.forName("org.apache.log4j.PropertyConfigurator");
Method method = clazz.getMethod("configure", URL.class);
// Import using this method
for (String url : extraLog4jUrls)
{
log4jHierarchy.addLoggerMBean(logger.getName());
importLogSettings(method, url);
}
}
}
void set_overriding_loggers( LoggerRepository hierarchy )
{
for ( String spring_url : extra_log4j_urls )
catch (ClassNotFoundException e)
{
set_overriding_logger( spring_url, hierarchy );
// Log4J not present
return;
}
catch (NoSuchMethodException e)
{
throw new RuntimeException("Unable to find method 'configure' on class 'org.apache.log4j.PropertyConfigurator'");
}
}
void set_overriding_logger( String spring_url,
LoggerRepository hierarchy )
private void importLogSettings(Method method, String springUrl)
{
PathMatchingResourcePatternResolver resolver;
PropertyConfigurator prop_config;
prop_config = new PropertyConfigurator();
resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = null;
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = null;
try
{
resources = resolver.getResources( spring_url );
resources = resolver.getResources(springUrl);
}
catch (Exception e)
{
logger.warn("Failed to find additional Logger configuration: " + springUrl);
}
catch (Exception e) { return ; }
// Read each resource
for (Resource resource : resources )
for (Resource resource : resources)
{
try
{
InputStream istream = new BufferedInputStream(resource.getInputStream());
Properties properties = new Properties();
properties.load(istream);
prop_config.doConfigure(properties, hierarchy);
URL url = resource.getURL();
method.invoke(null, url);
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.debug("Failed to add extra Logger configuration: \n" + " URL: " + springUrl + "\n" + " Error: " + e.getMessage(), e);
}
}
catch (Throwable e) { /* do nothing */ }
}
}
}