mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged DAVEW_V3.2 to HEAD
13659: Fix NTLMAuthenticationFilter to call super.afterPropertiesSet() 13658: MOB-424: Utility to Dump JMX Data - new enterprise distributable jmx-dumper.jar - command line invocation via "java -jar jmx-dumper.jar" - admin web access via http://localhost:8080/alfresco/faces/jsp/admin/jmx-dumper.jsp 13575: Preconfigured authentication stacks for alfresco, LDAP, Kerberos and NTLM. TODO: file server config. 13493: Initial work to enable selection, configuration, testing and hot-swapping of different authentication subsystems via JMX or admin UI. 13309: Changes to allow datasource and property configuration via JNDI - Move AVM catalina .jars into 3rd-party/lib/virtual-tomcat so that they don't get automatically included in the .war file and hence stop JNDI lookups from working - Allow JNDI lookup of datasource – use standard app server mechanisms for managing it but still fall back to 'normal' one - Allow properties to be overridden by JNDI env-entries as well as system properties. Including hibernate dialect ones. Web.xml can then declare required env-entries and these can be defined on deployment. - Rewire iBatis so that no config file edits are necessary when dialect is changed - Use proxy around datasource so that auto-commit is always activated for iBatis git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13668 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -1742,6 +1742,10 @@ workflow_last_command=Last command:
|
|||||||
workflow_duration=Duration:
|
workflow_duration=Duration:
|
||||||
workflow_duration_ms=ms
|
workflow_duration_ms=ms
|
||||||
|
|
||||||
|
# JMX Dumper messages
|
||||||
|
title_jmx_dumper=JMX Dumper
|
||||||
|
title_jmx_output=Output
|
||||||
|
|
||||||
# WebClient Config Admin Console messages
|
# WebClient Config Admin Console messages
|
||||||
title_configadmin_console=Web Client Config Admin Console
|
title_configadmin_console=Web Client Config Admin Console
|
||||||
configadmin_context=Context
|
configadmin_context=Context
|
||||||
|
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||||
|
<beans>
|
||||||
|
<bean id="authenticationFilter" class="org.alfresco.web.app.servlet.AuthenticationFilter">
|
||||||
|
<property name="configService">
|
||||||
|
<ref bean="webClientConfigService" />
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- NullFilter used for these beans, as they are currenly only required by NTLM -->
|
||||||
|
<bean id="globalAuthenticationFilter" class="org.alfresco.repo.web.filter.beans.NullFilter"/>
|
||||||
|
<bean id="webscriptAuthenticationFilter" class="org.alfresco.repo.web.filter.beans.NullFilter"/>
|
||||||
|
|
||||||
|
<bean id="webDavAuthenticationFilter" class="org.alfresco.repo.webdav.auth.AuthenticationFilter">
|
||||||
|
<property name="authenticationService">
|
||||||
|
<ref bean="AuthenticationService" />
|
||||||
|
</property>
|
||||||
|
<property name="personService">
|
||||||
|
<ref bean="PersonService" />
|
||||||
|
</property>
|
||||||
|
<property name="nodeService">
|
||||||
|
<ref bean="NodeService" />
|
||||||
|
</property>
|
||||||
|
<property name="transactionService">
|
||||||
|
<ref bean="TransactionService" />
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
</beans>
|
@@ -0,0 +1,70 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||||
|
<beans>
|
||||||
|
<bean id="authenticationFilter" class="org.alfresco.web.app.servlet.KerberosAuthenticationFilter">
|
||||||
|
<property name="serverConfigurationBean">
|
||||||
|
<ref bean="fileServerConfiguration" />
|
||||||
|
</property>
|
||||||
|
<property name="authenticationService">
|
||||||
|
<ref bean="AuthenticationService" />
|
||||||
|
</property>
|
||||||
|
<property name="authenticationComponent">
|
||||||
|
<ref bean="AuthenticationComponent" />
|
||||||
|
</property>
|
||||||
|
<property name="personService">
|
||||||
|
<ref bean="personService" />
|
||||||
|
</property>
|
||||||
|
<property name="nodeService">
|
||||||
|
<ref bean="NodeService" />
|
||||||
|
</property>
|
||||||
|
<property name="transactionService">
|
||||||
|
<ref bean="TransactionService" />
|
||||||
|
</property>
|
||||||
|
<property name="realm">
|
||||||
|
<value>${kerberos.authentication.realm}</value>
|
||||||
|
</property>
|
||||||
|
<property name="password">
|
||||||
|
<value>${kerberos.authentication.http.password}</value>
|
||||||
|
</property>
|
||||||
|
<property name="jaasConfigEntryName">
|
||||||
|
<value>${kerberos.authentication.http.configEntryName}</value>
|
||||||
|
</property>
|
||||||
|
<property name="configService">
|
||||||
|
<ref bean="webClientConfigService" />
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- NullFilter used for these beans, as they are currenly only required by NTLM -->
|
||||||
|
<bean id="globalAuthenticationFilter" class="org.alfresco.repo.web.filter.beans.NullFilter"/>
|
||||||
|
<bean id="webscriptAuthenticationFilter" class="org.alfresco.repo.web.filter.beans.NullFilter"/>
|
||||||
|
|
||||||
|
<bean id="webDavAuthenticationFilter" class="org.alfresco.repo.webdav.auth.KerberosAuthenticationFilter">
|
||||||
|
<property name="serverConfigurationBean">
|
||||||
|
<ref bean="fileServerConfiguration" />
|
||||||
|
</property>
|
||||||
|
<property name="authenticationService">
|
||||||
|
<ref bean="AuthenticationService" />
|
||||||
|
</property>
|
||||||
|
<property name="authenticationComponent">
|
||||||
|
<ref bean="AuthenticationComponent" />
|
||||||
|
</property>
|
||||||
|
<property name="personService">
|
||||||
|
<ref bean="personService" />
|
||||||
|
</property>
|
||||||
|
<property name="nodeService">
|
||||||
|
<ref bean="NodeService" />
|
||||||
|
</property>
|
||||||
|
<property name="transactionService">
|
||||||
|
<ref bean="TransactionService" />
|
||||||
|
</property>
|
||||||
|
<property name="realm">
|
||||||
|
<value>${kerberos.authentication.realm}</value>
|
||||||
|
</property>
|
||||||
|
<property name="password">
|
||||||
|
<value>${kerberos.authentication.http.password}</value>
|
||||||
|
</property>
|
||||||
|
<property name="jaasConfigEntryName">
|
||||||
|
<value>${kerberos.authentication.http.configEntryName}</value>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
</beans>
|
@@ -0,0 +1,2 @@
|
|||||||
|
kerberos.authentication.http.configEntryName=AlfrescoHTTP
|
||||||
|
kerberos.authentication.http.password=secret
|
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||||
|
<beans>
|
||||||
|
<bean id="authenticationFilter" class="org.alfresco.web.app.servlet.AuthenticationFilter">
|
||||||
|
<property name="configService">
|
||||||
|
<ref bean="webClientConfigService" />
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- NullFilter used for these beans, as they are currenly only required by NTLM -->
|
||||||
|
<bean id="globalAuthenticationFilter" class="org.alfresco.repo.web.filter.beans.NullFilter"/>
|
||||||
|
<bean id="webscriptAuthenticationFilter" class="org.alfresco.repo.web.filter.beans.NullFilter"/>
|
||||||
|
|
||||||
|
<bean id="webDavAuthenticationFilter" class="org.alfresco.repo.webdav.auth.AuthenticationFilter">
|
||||||
|
<property name="authenticationService">
|
||||||
|
<ref bean="AuthenticationService" />
|
||||||
|
</property>
|
||||||
|
<property name="personService">
|
||||||
|
<ref bean="PersonService" />
|
||||||
|
</property>
|
||||||
|
<property name="nodeService">
|
||||||
|
<ref bean="NodeService" />
|
||||||
|
</property>
|
||||||
|
<property name="transactionService">
|
||||||
|
<ref bean="TransactionService" />
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
</beans>
|
@@ -0,0 +1,87 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||||
|
<beans>
|
||||||
|
<!-- NullFilter used for this bean, as we are using the more widely-scoped globalAuthenticationFilter -->
|
||||||
|
<bean id="authenticationFilter" class="org.alfresco.repo.web.filter.beans.NullFilter"/>
|
||||||
|
|
||||||
|
<bean id="globalAuthenticationFilter" class="org.alfresco.web.app.servlet.NTLMAuthenticationFilter">
|
||||||
|
<property name="serverConfigurationBean">
|
||||||
|
<ref bean="fileServerConfiguration" />
|
||||||
|
</property>
|
||||||
|
<property name="authenticationService">
|
||||||
|
<ref bean="AuthenticationService" />
|
||||||
|
</property>
|
||||||
|
<property name="authenticationComponent">
|
||||||
|
<ref bean="AuthenticationComponent" />
|
||||||
|
</property>
|
||||||
|
<property name="personService">
|
||||||
|
<ref bean="personService" />
|
||||||
|
</property>
|
||||||
|
<property name="nodeService">
|
||||||
|
<ref bean="NodeService" />
|
||||||
|
</property>
|
||||||
|
<property name="transactionService">
|
||||||
|
<ref bean="TransactionService" />
|
||||||
|
</property>
|
||||||
|
<property name="mapUnknownUserToGuest">
|
||||||
|
<value>${ntlm.authentication.mapUnknownUserToGuest}</value>
|
||||||
|
</property>
|
||||||
|
<property name="configService">
|
||||||
|
<ref bean="webClientConfigService" />
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="webscriptAuthenticationFilter" class="org.alfresco.web.app.servlet.WebScriptNTLMAuthenticationFilter">
|
||||||
|
<property name="serverConfigurationBean">
|
||||||
|
<ref bean="fileServerConfiguration" />
|
||||||
|
</property>
|
||||||
|
<property name="authenticationService">
|
||||||
|
<ref bean="AuthenticationService" />
|
||||||
|
</property>
|
||||||
|
<property name="authenticationComponent">
|
||||||
|
<ref bean="AuthenticationComponent" />
|
||||||
|
</property>
|
||||||
|
<property name="personService">
|
||||||
|
<ref bean="personService" />
|
||||||
|
</property>
|
||||||
|
<property name="nodeService">
|
||||||
|
<ref bean="NodeService" />
|
||||||
|
</property>
|
||||||
|
<property name="transactionService">
|
||||||
|
<ref bean="TransactionService" />
|
||||||
|
</property>
|
||||||
|
<property name="mapUnknownUserToGuest">
|
||||||
|
<value>${ntlm.authentication.mapUnknownUserToGuest}</value>
|
||||||
|
</property>
|
||||||
|
<property name="configService">
|
||||||
|
<ref bean="webClientConfigService" />
|
||||||
|
</property>
|
||||||
|
<property name="container">
|
||||||
|
<ref bean="webscripts.container" />
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="webDavAuthenticationFilter" class="org.alfresco.repo.webdav.auth.NTLMAuthenticationFilter">
|
||||||
|
<property name="serverConfigurationBean">
|
||||||
|
<ref bean="fileServerConfiguration" />
|
||||||
|
</property>
|
||||||
|
<property name="authenticationService">
|
||||||
|
<ref bean="AuthenticationService" />
|
||||||
|
</property>
|
||||||
|
<property name="authenticationComponent">
|
||||||
|
<ref bean="AuthenticationComponent" />
|
||||||
|
</property>
|
||||||
|
<property name="personService">
|
||||||
|
<ref bean="personService" />
|
||||||
|
</property>
|
||||||
|
<property name="nodeService">
|
||||||
|
<ref bean="NodeService" />
|
||||||
|
</property>
|
||||||
|
<property name="transactionService">
|
||||||
|
<ref bean="TransactionService" />
|
||||||
|
</property>
|
||||||
|
<property name="mapUnknownUserToGuest">
|
||||||
|
<value>${ntlm.authentication.mapUnknownUserToGuest}</value>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
</beans>
|
@@ -0,0 +1 @@
|
|||||||
|
ntlm.authentication.mapUnknownUserToGuest=false
|
@@ -302,4 +302,61 @@
|
|||||||
<property name="authenticationService" ref="AuthenticationService" />
|
<property name="authenticationService" ref="AuthenticationService" />
|
||||||
<property name="transactionService" ref="TransactionService" />
|
<property name="transactionService" ref="TransactionService" />
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="authenticationFilter" class="org.alfresco.repo.management.ManagedSubsystemProxyFactory">
|
||||||
|
<property name="sourceApplicationContextFactory">
|
||||||
|
<ref bean="authenticationSelector" />
|
||||||
|
</property>
|
||||||
|
<property name="interfaces">
|
||||||
|
<list>
|
||||||
|
<value>org.alfresco.repo.web.filter.beans.DependencyInjectedFilter</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
<property name="sourceBeanName">
|
||||||
|
<value>authenticationFilter</value>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="globalAuthenticationFilter" class="org.alfresco.repo.management.ManagedSubsystemProxyFactory">
|
||||||
|
<property name="sourceApplicationContextFactory">
|
||||||
|
<ref bean="authenticationSelector" />
|
||||||
|
</property>
|
||||||
|
<property name="interfaces">
|
||||||
|
<list>
|
||||||
|
<value>org.alfresco.repo.web.filter.beans.DependencyInjectedFilter</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
<property name="sourceBeanName">
|
||||||
|
<value>globalAuthenticationFilter</value>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="webscriptAuthenticationFilter" class="org.alfresco.repo.management.ManagedSubsystemProxyFactory">
|
||||||
|
<property name="sourceApplicationContextFactory">
|
||||||
|
<ref bean="authenticationSelector" />
|
||||||
|
</property>
|
||||||
|
<property name="interfaces">
|
||||||
|
<list>
|
||||||
|
<value>org.alfresco.repo.web.filter.beans.DependencyInjectedFilter</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
<property name="sourceBeanName">
|
||||||
|
<value>webscriptAuthenticationFilter</value>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="webDavAuthenticationFilter" class="org.alfresco.repo.management.ManagedSubsystemProxyFactory">
|
||||||
|
<property name="sourceApplicationContextFactory">
|
||||||
|
<ref bean="authenticationSelector" />
|
||||||
|
</property>
|
||||||
|
<property name="interfaces">
|
||||||
|
<list>
|
||||||
|
<value>org.alfresco.repo.web.filter.beans.DependencyInjectedFilter</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
<property name="sourceBeanName">
|
||||||
|
<value>webDavAuthenticationFilter</value>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
@@ -71,9 +71,16 @@ public class ContextListener implements ServletContextListener, HttpSessionListe
|
|||||||
*/
|
*/
|
||||||
public void contextInitialized(ServletContextEvent event)
|
public void contextInitialized(ServletContextEvent event)
|
||||||
{
|
{
|
||||||
// make sure that the spaces store in the repository exists
|
// make sure that the spaces store in the repository exists
|
||||||
this.servletContext = event.getServletContext();
|
this.servletContext = event.getServletContext();
|
||||||
WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
|
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);
|
||||||
|
|
||||||
|
// If no context has been initialised, exit silently so config changes can be made
|
||||||
|
if (ctx == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ServiceRegistry registry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
ServiceRegistry registry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||||
TransactionService transactionService = registry.getTransactionService();
|
TransactionService transactionService = registry.getTransactionService();
|
||||||
NodeService nodeService = registry.getNodeService();
|
NodeService nodeService = registry.getNodeService();
|
||||||
|
79
source/java/org/alfresco/web/app/ContextLoaderListener.java
Normal file
79
source/java/org/alfresco/web/app/ContextLoaderListener.java
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2009 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
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* 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 received a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.web.app;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContextEvent;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.jndi.JndiTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A specialised {@link org.springframework.web.context.ContextLoaderListener} that can be disabled by a boolean
|
||||||
|
* <code>java:comp/env/properties/startup.enable</code> JNDI entry. If <code>startup.enable</code> is configured as
|
||||||
|
* false then the Spring Application Context is not created, allowing further configuration changes to be made after
|
||||||
|
* initial deployment.
|
||||||
|
*
|
||||||
|
* @author dward
|
||||||
|
*/
|
||||||
|
public class ContextLoaderListener extends org.springframework.web.context.ContextLoaderListener
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The JNDI environment entry that controls global startup
|
||||||
|
*/
|
||||||
|
private static final String PROPERTY_ENABLE_STARTUP = "java:comp/env/properties/startup.enable";
|
||||||
|
|
||||||
|
protected final static Log log = LogFactory.getLog(ContextLoaderListener.class);
|
||||||
|
private boolean enableStartup;
|
||||||
|
|
||||||
|
public ContextLoaderListener()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.enableStartup = (Boolean) new JndiTemplate().lookup(ContextLoaderListener.PROPERTY_ENABLE_STARTUP,
|
||||||
|
Boolean.class);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
this.enableStartup = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contextInitialized(ServletContextEvent event)
|
||||||
|
{
|
||||||
|
if (this.enableStartup)
|
||||||
|
{
|
||||||
|
super.contextInitialized(event);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ContextLoaderListener.log
|
||||||
|
.warn("The "
|
||||||
|
+ ContextLoaderListener.PROPERTY_ENABLE_STARTUP
|
||||||
|
+ " environment entry is false. Please configure the environment entries for this application and then restart the server.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -26,9 +26,7 @@ package org.alfresco.web.app.servlet;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import javax.servlet.Filter;
|
|
||||||
import javax.servlet.FilterChain;
|
import javax.servlet.FilterChain;
|
||||||
import javax.servlet.FilterConfig;
|
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
@@ -36,7 +34,9 @@ import javax.servlet.ServletResponse;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.alfresco.web.app.Application;
|
import org.alfresco.config.ConfigService;
|
||||||
|
import org.alfresco.repo.web.filter.beans.DependencyInjectedFilter;
|
||||||
|
import org.alfresco.web.config.ClientConfigElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Kevin Roast
|
* @author Kevin Roast
|
||||||
@@ -50,75 +50,55 @@ import org.alfresco.web.app.Application;
|
|||||||
* Note that this filter is only active when the system is running in a servlet container -
|
* Note that this filter is only active when the system is running in a servlet container -
|
||||||
* the AlfrescoFacesPortlet will be used for a JSR-168 Portal environment.
|
* the AlfrescoFacesPortlet will be used for a JSR-168 Portal environment.
|
||||||
*/
|
*/
|
||||||
public class AuthenticationFilter implements Filter
|
public class AuthenticationFilter implements DependencyInjectedFilter
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
|
|
||||||
*/
|
|
||||||
public void init(FilterConfig config) throws ServletException
|
|
||||||
{
|
|
||||||
this.context = config.getServletContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
private String loginPage;
|
||||||
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
|
|
||||||
*/
|
/**
|
||||||
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
|
* @param configService
|
||||||
throws IOException, ServletException
|
* the configService to set
|
||||||
{
|
*/
|
||||||
HttpServletRequest httpReq = (HttpServletRequest)req;
|
public void setConfigService(ConfigService configService)
|
||||||
HttpServletResponse httpRes = (HttpServletResponse)res;
|
{
|
||||||
|
ClientConfigElement clientConfig = (ClientConfigElement) configService.getGlobalConfig().getConfigElement(
|
||||||
// allow the login page to proceed
|
ClientConfigElement.CONFIG_ELEMENT_ID);
|
||||||
if (httpReq.getRequestURI().endsWith(getLoginPage()) == false)
|
|
||||||
{
|
if (clientConfig != null)
|
||||||
AuthenticationStatus status =
|
{
|
||||||
AuthenticationHelper.authenticate(this.context, httpReq, httpRes, false);
|
loginPage = clientConfig.getLoginPage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doFilter(ServletContext context, ServletRequest req, ServletResponse res, FilterChain chain)
|
||||||
|
throws IOException, ServletException
|
||||||
|
{
|
||||||
|
HttpServletRequest httpReq = (HttpServletRequest) req;
|
||||||
|
HttpServletResponse httpRes = (HttpServletResponse) res;
|
||||||
|
|
||||||
|
// allow the login page to proceed
|
||||||
|
if (!httpReq.getRequestURI().endsWith(this.loginPage))
|
||||||
|
{
|
||||||
|
AuthenticationStatus status = AuthenticationHelper.authenticate(context, httpReq, httpRes, false);
|
||||||
|
|
||||||
|
if (status == AuthenticationStatus.Success || status == AuthenticationStatus.Guest)
|
||||||
|
{
|
||||||
|
// continue filter chaining
|
||||||
|
chain.doFilter(req, res);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// authentication failed - so end servlet execution and redirect to login page
|
||||||
|
// also save the requested URL so the login page knows where to redirect too later
|
||||||
|
BaseServlet.redirectToLoginPage(httpReq, httpRes, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BaseServlet.setLanguageFromRequestHeader(httpReq, context);
|
||||||
|
|
||||||
if (status == AuthenticationStatus.Success || status == AuthenticationStatus.Guest)
|
|
||||||
{
|
|
||||||
// continue filter chaining
|
// continue filter chaining
|
||||||
chain.doFilter(req, res);
|
chain.doFilter(req, res);
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
// authentication failed - so end servlet execution and redirect to login page
|
|
||||||
// also save the requested URL so the login page knows where to redirect too later
|
|
||||||
BaseServlet.redirectToLoginPage(httpReq, httpRes, context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BaseServlet.setLanguageFromRequestHeader(httpReq, context);
|
|
||||||
|
|
||||||
// continue filter chaining
|
|
||||||
chain.doFilter(req, res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see javax.servlet.Filter#destroy()
|
|
||||||
*/
|
|
||||||
public void destroy()
|
|
||||||
{
|
|
||||||
// nothing to do
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The login page url
|
|
||||||
*/
|
|
||||||
private String getLoginPage()
|
|
||||||
{
|
|
||||||
if (this.loginPage == null)
|
|
||||||
{
|
|
||||||
this.loginPage = Application.getLoginPage(this.context);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.loginPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private String loginPage = null;
|
|
||||||
|
|
||||||
private ServletContext context;
|
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -25,67 +25,24 @@
|
|||||||
package org.alfresco.web.app.servlet;
|
package org.alfresco.web.app.servlet;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.security.Principal;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Random;
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import javax.security.auth.Subject;
|
|
||||||
import javax.security.auth.callback.Callback;
|
|
||||||
import javax.security.auth.callback.CallbackHandler;
|
|
||||||
import javax.security.auth.callback.NameCallback;
|
|
||||||
import javax.security.auth.callback.PasswordCallback;
|
|
||||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
|
||||||
import javax.security.auth.login.LoginContext;
|
|
||||||
import javax.security.auth.login.LoginException;
|
|
||||||
import javax.security.sasl.RealmCallback;
|
|
||||||
import javax.servlet.Filter;
|
|
||||||
import javax.servlet.FilterChain;
|
|
||||||
import javax.servlet.FilterConfig;
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
import javax.servlet.ServletResponse;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
import javax.transaction.UserTransaction;
|
|
||||||
|
|
||||||
import org.alfresco.config.ConfigService;
|
import org.alfresco.config.ConfigService;
|
||||||
import org.alfresco.filesys.ServerConfigurationBean;
|
|
||||||
import org.alfresco.i18n.I18NUtil;
|
import org.alfresco.i18n.I18NUtil;
|
||||||
import org.alfresco.jlan.server.auth.kerberos.KerberosDetails;
|
|
||||||
import org.alfresco.jlan.server.auth.kerberos.SessionSetupPrivilegedAction;
|
|
||||||
import org.alfresco.jlan.server.auth.spnego.NegTokenInit;
|
|
||||||
import org.alfresco.jlan.server.auth.spnego.NegTokenTarg;
|
|
||||||
import org.alfresco.jlan.server.auth.spnego.OID;
|
|
||||||
import org.alfresco.jlan.server.auth.spnego.SPNEGO;
|
|
||||||
import org.alfresco.model.ContentModel;
|
|
||||||
import org.alfresco.repo.SessionUser;
|
import org.alfresco.repo.SessionUser;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
|
||||||
import org.alfresco.repo.security.authentication.NTLMMode;
|
|
||||||
import org.alfresco.repo.webdav.auth.BaseKerberosAuthenticationFilter;
|
import org.alfresco.repo.webdav.auth.BaseKerberosAuthenticationFilter;
|
||||||
import org.alfresco.service.ServiceRegistry;
|
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeService;
|
|
||||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
|
||||||
import org.alfresco.service.cmr.security.PersonService;
|
|
||||||
import org.alfresco.service.transaction.TransactionService;
|
|
||||||
import org.alfresco.web.app.Application;
|
import org.alfresco.web.app.Application;
|
||||||
import org.alfresco.web.bean.LoginBean;
|
|
||||||
import org.alfresco.web.bean.repository.User;
|
import org.alfresco.web.bean.repository.User;
|
||||||
|
import org.alfresco.web.config.ClientConfigElement;
|
||||||
import org.alfresco.web.config.LanguagesConfigElement;
|
import org.alfresco.web.config.LanguagesConfigElement;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.ietf.jgss.Oid;
|
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
|
||||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kerberos Authentication Filter Class
|
* Kerberos Authentication Filter Class
|
||||||
@@ -110,36 +67,39 @@ public class KerberosAuthenticationFilter extends BaseKerberosAuthenticationFilt
|
|||||||
|
|
||||||
// List of available locales (from the web-client configuration)
|
// List of available locales (from the web-client configuration)
|
||||||
|
|
||||||
private List<String> m_languages;
|
private List<String> m_languages;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the filter
|
* @param configService the configService to set
|
||||||
*
|
|
||||||
* @param args FilterConfig
|
|
||||||
* @exception ServletException
|
|
||||||
*/
|
*/
|
||||||
public void init(FilterConfig args) throws ServletException
|
public void setConfigService(ConfigService configService)
|
||||||
{
|
{
|
||||||
// Call the base Kerberos filter initialization
|
m_configService = configService;
|
||||||
|
}
|
||||||
super.init( args);
|
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
// Setup the authentication context
|
* @see org.alfresco.repo.webdav.auth.BaseKerberosAuthenticationFilter#afterPropertiesSet()
|
||||||
|
*/
|
||||||
WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(m_context);
|
@Override
|
||||||
m_configService = (ConfigService)ctx.getBean("webClientConfigService");
|
public void afterPropertiesSet() throws Exception
|
||||||
|
{
|
||||||
|
// Call the base Kerberos filter initialization
|
||||||
|
super.afterPropertiesSet();
|
||||||
|
|
||||||
// Get a list of the available locales
|
// Get a list of the available locales
|
||||||
|
LanguagesConfigElement config = (LanguagesConfigElement) m_configService.getConfig("Languages")
|
||||||
LanguagesConfigElement config = (LanguagesConfigElement) m_configService.
|
.getConfigElement(LanguagesConfigElement.CONFIG_ELEMENT_ID);
|
||||||
getConfig("Languages").getConfigElement(LanguagesConfigElement.CONFIG_ELEMENT_ID);
|
|
||||||
|
|
||||||
m_languages = config.getLanguages();
|
m_languages = config.getLanguages();
|
||||||
|
|
||||||
// Set hte login page address
|
ClientConfigElement clientConfig = (ClientConfigElement) m_configService.getGlobalConfig().getConfigElement(
|
||||||
|
ClientConfigElement.CONFIG_ELEMENT_ID);
|
||||||
setLoginPage( Application.getLoginPage(m_context));
|
|
||||||
|
if (clientConfig != null)
|
||||||
|
{
|
||||||
|
setLoginPage(clientConfig.getLoginPage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
|
@@ -28,8 +28,6 @@ import java.io.IOException;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import javax.servlet.FilterConfig;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
@@ -41,11 +39,10 @@ import org.alfresco.repo.webdav.auth.BaseNTLMAuthenticationFilter;
|
|||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.web.app.Application;
|
import org.alfresco.web.app.Application;
|
||||||
import org.alfresco.web.bean.repository.User;
|
import org.alfresco.web.bean.repository.User;
|
||||||
|
import org.alfresco.web.config.ClientConfigElement;
|
||||||
import org.alfresco.web.config.LanguagesConfigElement;
|
import org.alfresco.web.config.LanguagesConfigElement;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
|
||||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Web-client NTLM Authentication Filter Class
|
* Web-client NTLM Authentication Filter Class
|
||||||
@@ -61,38 +58,42 @@ public class NTLMAuthenticationFilter extends BaseNTLMAuthenticationFilter
|
|||||||
// Debug logging
|
// Debug logging
|
||||||
private static Log logger = LogFactory.getLog(NTLMAuthenticationFilter.class);
|
private static Log logger = LogFactory.getLog(NTLMAuthenticationFilter.class);
|
||||||
|
|
||||||
// Various services required by NTLM authenticator
|
protected ConfigService m_configService;
|
||||||
private ConfigService m_configService;
|
|
||||||
|
|
||||||
// List of available locales (from the web-client configuration)
|
// List of available locales (from the web-client configuration)
|
||||||
private List<String> m_languages;
|
private List<String> m_languages;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the filter
|
* @param configService the configService to set
|
||||||
*
|
|
||||||
* @param args FilterConfig
|
|
||||||
* @exception ServletException
|
|
||||||
*/
|
*/
|
||||||
public void init(FilterConfig args) throws ServletException
|
public void setConfigService(ConfigService configService)
|
||||||
{
|
{
|
||||||
super.init(args);
|
m_configService = configService;
|
||||||
|
|
||||||
// Setup the authentication context
|
|
||||||
|
|
||||||
WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(m_context);
|
|
||||||
m_configService = (ConfigService)ctx.getBean("webClientConfigService");
|
|
||||||
|
|
||||||
// Get a list of the available locales
|
|
||||||
|
|
||||||
LanguagesConfigElement config = (LanguagesConfigElement) m_configService.
|
|
||||||
getConfig("Languages").getConfigElement(LanguagesConfigElement.CONFIG_ELEMENT_ID);
|
|
||||||
|
|
||||||
m_languages = config.getLanguages();
|
|
||||||
setLoginPage( Application.getLoginPage(m_context));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.webdav.auth.BaseNTLMAuthenticationFilter#afterPropertiesSet()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception
|
||||||
|
{
|
||||||
|
// Call the base NTLM filter initialization
|
||||||
|
super.afterPropertiesSet();
|
||||||
|
|
||||||
|
// Get a list of the available locales
|
||||||
|
LanguagesConfigElement config = (LanguagesConfigElement) m_configService.getConfig("Languages")
|
||||||
|
.getConfigElement(LanguagesConfigElement.CONFIG_ELEMENT_ID);
|
||||||
|
|
||||||
|
m_languages = config.getLanguages();
|
||||||
|
ClientConfigElement clientConfig = (ClientConfigElement) m_configService.getGlobalConfig().getConfigElement(
|
||||||
|
ClientConfigElement.CONFIG_ELEMENT_ID);
|
||||||
|
if (clientConfig != null)
|
||||||
|
{
|
||||||
|
setLoginPage(clientConfig.getLoginPage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
* @see org.alfresco.repo.webdav.auth.BaseSSOAuthenticationFilter#createUserObject(java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
|
* @see org.alfresco.repo.webdav.auth.BaseSSOAuthenticationFilter#createUserObject(java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@@ -27,20 +27,16 @@ package org.alfresco.web.app.servlet;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
import javax.servlet.FilterChain;
|
||||||
import javax.servlet.FilterConfig;
|
import javax.servlet.ServletContext;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
import javax.servlet.ServletResponse;
|
import javax.servlet.ServletResponse;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.alfresco.config.ConfigService;
|
|
||||||
import org.alfresco.util.URLDecoder;
|
import org.alfresco.util.URLDecoder;
|
||||||
import org.alfresco.web.scripts.Match;
|
import org.alfresco.web.scripts.Match;
|
||||||
import org.alfresco.web.scripts.RuntimeContainer;
|
import org.alfresco.web.scripts.RuntimeContainer;
|
||||||
import org.alfresco.web.scripts.Description.RequiredAuthentication;
|
import org.alfresco.web.scripts.Description.RequiredAuthentication;
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WebScript aware NTLM Authentication Filter Class.
|
* WebScript aware NTLM Authentication Filter Class.
|
||||||
@@ -53,45 +49,26 @@ import org.springframework.web.context.support.WebApplicationContextUtils;
|
|||||||
*/
|
*/
|
||||||
public class WebScriptNTLMAuthenticationFilter extends NTLMAuthenticationFilter
|
public class WebScriptNTLMAuthenticationFilter extends NTLMAuthenticationFilter
|
||||||
{
|
{
|
||||||
private RuntimeContainer container;
|
private RuntimeContainer container;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the filter
|
* @param container the container to set
|
||||||
*
|
|
||||||
* @param args FilterConfig
|
|
||||||
* @exception ServletException
|
|
||||||
*/
|
*/
|
||||||
public void init(FilterConfig args) throws ServletException
|
public void setContainer(RuntimeContainer container)
|
||||||
{
|
{
|
||||||
super.init(args);
|
this.container = container;
|
||||||
|
|
||||||
ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(args.getServletContext());
|
|
||||||
ConfigService configService = (ConfigService)context.getBean("web.config");
|
|
||||||
String containerName = args.getInitParameter("container");
|
|
||||||
if (containerName == null)
|
|
||||||
{
|
|
||||||
containerName = "webscripts.container";
|
|
||||||
}
|
|
||||||
container = (RuntimeContainer)context.getBean(containerName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Run the filter
|
/* (non-Javadoc)
|
||||||
*
|
* @see org.alfresco.repo.webdav.auth.BaseNTLMAuthenticationFilter#doFilter(javax.servlet.ServletContext, javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
|
||||||
* @param sreq ServletRequest
|
|
||||||
* @param sresp ServletResponse
|
|
||||||
* @param chain FilterChain
|
|
||||||
*
|
|
||||||
* @exception IOException
|
|
||||||
* @exception ServletException
|
|
||||||
*/
|
*/
|
||||||
public void doFilter(ServletRequest sreq, ServletResponse sres, FilterChain chain)
|
@Override
|
||||||
throws IOException, ServletException
|
public void doFilter(ServletContext context, ServletRequest sreq, ServletResponse sresp, FilterChain chain)
|
||||||
|
throws IOException, ServletException
|
||||||
{
|
{
|
||||||
// Get the HTTP request/response
|
// Get the HTTP request/response
|
||||||
HttpServletRequest req = (HttpServletRequest)sreq;
|
HttpServletRequest req = (HttpServletRequest)sreq;
|
||||||
HttpServletResponse res = (HttpServletResponse)sres;
|
|
||||||
|
|
||||||
// find a webscript match for the requested URI
|
// find a webscript match for the requested URI
|
||||||
String requestURI = req.getRequestURI();
|
String requestURI = req.getRequestURI();
|
||||||
@@ -114,6 +91,6 @@ public class WebScriptNTLMAuthenticationFilter extends NTLMAuthenticationFilter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
super.doFilter(sreq, sres, chain);
|
super.doFilter(context, sreq, sresp, chain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
92
source/java/org/alfresco/web/bean/jmx/JmxDumperBean.java
Normal file
92
source/java/org/alfresco/web/bean/jmx/JmxDumperBean.java
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2009 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
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* 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 received a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.web.bean.jmx;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
|
||||||
|
import javax.faces.context.FacesContext;
|
||||||
|
import javax.management.MBeanServerConnection;
|
||||||
|
|
||||||
|
import org.alfresco.repo.management.JmxDumpUtil;
|
||||||
|
import org.alfresco.web.app.servlet.FacesHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Backing bean to allow an admin user to dump all JMX Beans and their properties.
|
||||||
|
*/
|
||||||
|
public class JmxDumperBean implements Serializable
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -8690237774052781181L;
|
||||||
|
|
||||||
|
// supporting repository services
|
||||||
|
|
||||||
|
/** The MBean server. */
|
||||||
|
transient private MBeanServerConnection mbeanServer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the mbean server.
|
||||||
|
*
|
||||||
|
* @param mbeanServer
|
||||||
|
* the mbeanServer to set
|
||||||
|
*/
|
||||||
|
public void setMbeanServer(MBeanServerConnection mbeanServer)
|
||||||
|
{
|
||||||
|
this.mbeanServer = mbeanServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the mbean server.
|
||||||
|
*
|
||||||
|
* @return the mbeanServer
|
||||||
|
*/
|
||||||
|
private MBeanServerConnection getMbeanServer()
|
||||||
|
{
|
||||||
|
if (this.mbeanServer == null)
|
||||||
|
{
|
||||||
|
this.mbeanServer = (MBeanServerConnection) FacesHelper.getManagedBean(FacesContext.getCurrentInstance(),
|
||||||
|
"alfrescoMBeanServer");
|
||||||
|
}
|
||||||
|
return this.mbeanServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the command result.
|
||||||
|
*
|
||||||
|
* @return the result
|
||||||
|
* @throws IOException
|
||||||
|
* Signals that an I/O exception has occurred.
|
||||||
|
*/
|
||||||
|
public String getResult() throws IOException
|
||||||
|
{
|
||||||
|
StringWriter result = new StringWriter();
|
||||||
|
PrintWriter out = new PrintWriter(result);
|
||||||
|
JmxDumpUtil.dumpConnection(getMbeanServer(), out);
|
||||||
|
out.close();
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
}
|
11
source/web/META-INF/context.xml
Normal file
11
source/web/META-INF/context.xml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Context>
|
||||||
|
<!-- Uncomment in $CATALINA_BASE/conf/[enginename]/[hostname]/alfresco.xml to define your own datasource. Add value attributes to each of the environment tags below to define your environment settings. -->
|
||||||
|
<!-- Resource defaultTransactionIsolation="-1" defaultAutoCommit="false" maxActive="100" initialSize="10" password="alfresco" username="alfresco" url="jdbc:mysql:///alfresco" driverClassName="org.gjt.mm.mysql.Driver" type="javax.sql.DataSource" auth="Container" name="jdbc/dataSource"/-->
|
||||||
|
<Environment override="false" type="java.lang.Boolean" name="properties/startup.enable" description="A flag that globally enables or disables startup of the major Alfresco subsystems." value="true"/>
|
||||||
|
<Environment override="false" type="java.lang.String" name="properties/dir.root" description="The filesystem directory below which content and index data is stored. Should be on a shared disk if this is a clustered installation."/>
|
||||||
|
<Environment override="false" type="java.lang.String" name="properties/hibernate.dialect" description="The fully qualified name of a org.hibernate.dialect.Dialect subclass that allows Hibernate to generate SQL optimized for a particular relational database. Choose from org.hibernate.dialect.DerbyDialect, org.hibernate.dialect.MySQLInnoDBDialect, org.alfresco.repo.domain.hibernate.dialect.AlfrescoOracle9Dialect, org.alfresco.repo.domain.hibernate.dialect.AlfrescoSybaseAnywhereDialect, org.alfresco.repo.domain.hibernate.dialect.AlfrescoSQLServerDialect, org.hibernate.dialect.PostgreSQLDialect"/>
|
||||||
|
<Environment override="false" type="java.lang.String" name="properties/hibernate.query.substitutions" description="Mapping from tokens in Hibernate queries to SQL tokens. For PostgreSQL, set this to "true TRUE, false FALSE"."/>
|
||||||
|
<Environment override="false" type="java.lang.Boolean" name="properties/hibernate.jdbc.use_get_generated_keys" description="Enable use of JDBC3 PreparedStatement.getGeneratedKeys() to retrieve natively generated keys after insert. Requires JDBC3+ driver. Set to false if your driver has problems with the Hibernate identifier generators. By default, tries to determine the driver capabilities using connection metadata."/>
|
||||||
|
<Environment override="false" type="java.lang.String" name="properties/hibernate.default_schema" description="Qualify unqualified table names with the given schema/tablespace in generated SQL. It may be necessary to set this when the target database has more than one schema."/>
|
||||||
|
</Context>
|
@@ -91,35 +91,46 @@
|
|||||||
|
|
||||||
<filter>
|
<filter>
|
||||||
<filter-name>Authentication Filter</filter-name>
|
<filter-name>Authentication Filter</filter-name>
|
||||||
<filter-class>org.alfresco.web.app.servlet.AuthenticationFilter</filter-class>
|
<description>Authentication filter mapped only to faces URLs. Other URLs generally use proprietary means to talk to the AuthenticationComponent</description>
|
||||||
|
<filter-class>org.alfresco.repo.web.filter.beans.BeanProxyFilter</filter-class>
|
||||||
<!-- For NTLM authentication support use the following filter, also see the filter-mapping section -->
|
<init-param>
|
||||||
<!--
|
<param-name>beanName</param-name>
|
||||||
<filter-class>org.alfresco.web.app.servlet.NTLMAuthenticationFilter</filter-class>
|
<param-value>authenticationFilter</param-value>
|
||||||
-->
|
</init-param>
|
||||||
|
|
||||||
<!-- For Novell IChain support use the following filter -->
|
<!-- For Novell IChain support use the following filter -->
|
||||||
<!--
|
<!--
|
||||||
<filter-class>org.alfresco.web.app.servlet.NovellIChainsHTTPRequestAuthenticationFilter</filter-class>
|
<filter-class>org.alfresco.web.app.servlet.NovellIChainsHTTPRequestAuthenticationFilter</filter-class>
|
||||||
-->
|
-->
|
||||||
</filter>
|
</filter>
|
||||||
|
|
||||||
<!-- For NTLM authentication support use the following filter, also see the filter-mapping section -->
|
|
||||||
<!--
|
|
||||||
<filter>
|
<filter>
|
||||||
<filter-name>WebScript NTLM Authentication Filter</filter-name>
|
<filter-name>Global Authentication Filter</filter-name>
|
||||||
<filter-class>org.alfresco.web.app.servlet.WebScriptNTLMAuthenticationFilter</filter-class>
|
<description>Authentication filter mapped to all authenticated URLs (except web scripts). Mainly for NTLM support</description>
|
||||||
|
<filter-class>org.alfresco.repo.web.filter.beans.BeanProxyFilter</filter-class>
|
||||||
|
<init-param>
|
||||||
|
<param-name>beanName</param-name>
|
||||||
|
<param-value>globalAuthenticationFilter</param-value>
|
||||||
|
</init-param>
|
||||||
</filter>
|
</filter>
|
||||||
-->
|
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<filter-name>WebScript Authentication Filter</filter-name>
|
||||||
|
<description>Authentication filter mapped to web script URLs. Mainly for NTLM support</description>
|
||||||
|
<filter-class>org.alfresco.repo.web.filter.beans.BeanProxyFilter</filter-class>
|
||||||
|
<init-param>
|
||||||
|
<param-name>beanName</param-name>
|
||||||
|
<param-value>webscriptAuthenticationFilter</param-value>
|
||||||
|
</init-param>
|
||||||
|
</filter>
|
||||||
|
|
||||||
<filter>
|
<filter>
|
||||||
<filter-name>WebDAV Authentication Filter</filter-name>
|
<filter-name>WebDAV Authentication Filter</filter-name>
|
||||||
<filter-class>org.alfresco.repo.webdav.auth.AuthenticationFilter</filter-class>
|
<filter-class>org.alfresco.repo.web.filter.beans.BeanProxyFilter</filter-class>
|
||||||
|
<init-param>
|
||||||
<!-- For NTLM authentication support use the following filter -->
|
<param-name>beanName</param-name>
|
||||||
<!--
|
<param-value>webDavAuthenticationFilter</param-value>
|
||||||
<filter-class>org.alfresco.repo.webdav.auth.NTLMAuthenticationFilter</filter-class>
|
</init-param>
|
||||||
-->
|
|
||||||
</filter>
|
</filter>
|
||||||
|
|
||||||
<filter>
|
<filter>
|
||||||
@@ -127,66 +138,66 @@
|
|||||||
<filter-class>org.alfresco.web.app.servlet.AdminAuthenticationFilter</filter-class>
|
<filter-class>org.alfresco.web.app.servlet.AdminAuthenticationFilter</filter-class>
|
||||||
</filter>
|
</filter>
|
||||||
|
|
||||||
|
|
||||||
<!-- For NTLM authentication support enable the following mappings -->
|
|
||||||
<!-- after enabling the NTLMAuthenticationFilter filter class above -->
|
|
||||||
<!--
|
|
||||||
<filter-mapping>
|
<filter-mapping>
|
||||||
<filter-name>Authentication Filter</filter-name>
|
<filter-name>Global Authentication Filter</filter-name>
|
||||||
<url-pattern>/navigate/*</url-pattern>
|
<url-pattern>/navigate/*</url-pattern>
|
||||||
</filter-mapping>
|
</filter-mapping>
|
||||||
|
|
||||||
<filter-mapping>
|
<filter-mapping>
|
||||||
<filter-name>Authentication Filter</filter-name>
|
<filter-name>Global Authentication Filter</filter-name>
|
||||||
<url-pattern>/command/*</url-pattern>
|
<url-pattern>/command/*</url-pattern>
|
||||||
</filter-mapping>
|
</filter-mapping>
|
||||||
|
|
||||||
<filter-mapping>
|
<filter-mapping>
|
||||||
<filter-name>Authentication Filter</filter-name>
|
<filter-name>Global Authentication Filter</filter-name>
|
||||||
<url-pattern>/download/*</url-pattern>
|
<url-pattern>/download/*</url-pattern>
|
||||||
</filter-mapping>
|
</filter-mapping>
|
||||||
|
|
||||||
<filter-mapping>
|
<filter-mapping>
|
||||||
<filter-name>Authentication Filter</filter-name>
|
<filter-name>Global Authentication Filter</filter-name>
|
||||||
<url-pattern>/template/*</url-pattern>
|
<url-pattern>/template/*</url-pattern>
|
||||||
</filter-mapping>
|
</filter-mapping>
|
||||||
|
|
||||||
<filter-mapping>
|
<filter-mapping>
|
||||||
<filter-name>Authentication Filter</filter-name>
|
<filter-name>Global Authentication Filter</filter-name>
|
||||||
<url-pattern>/n/*</url-pattern>
|
<url-pattern>/n/*</url-pattern>
|
||||||
</filter-mapping>
|
</filter-mapping>
|
||||||
|
|
||||||
<filter-mapping>
|
<filter-mapping>
|
||||||
<filter-name>Authentication Filter</filter-name>
|
<filter-name>Global Authentication Filter</filter-name>
|
||||||
<url-pattern>/c/*</url-pattern>
|
<url-pattern>/c/*</url-pattern>
|
||||||
</filter-mapping>
|
</filter-mapping>
|
||||||
|
|
||||||
<filter-mapping>
|
<filter-mapping>
|
||||||
<filter-name>Authentication Filter</filter-name>
|
<filter-name>Global Authentication Filter</filter-name>
|
||||||
<url-pattern>/t/*</url-pattern>
|
<url-pattern>/t/*</url-pattern>
|
||||||
</filter-mapping>
|
</filter-mapping>
|
||||||
|
|
||||||
<filter-mapping>
|
<filter-mapping>
|
||||||
<filter-name>Authentication Filter</filter-name>
|
<filter-name>Global Authentication Filter</filter-name>
|
||||||
<url-pattern>/d/*</url-pattern>
|
<url-pattern>/d/*</url-pattern>
|
||||||
</filter-mapping>
|
</filter-mapping>
|
||||||
|
|
||||||
<filter-mapping>
|
<filter-mapping>
|
||||||
<filter-name>WebScript NTLM Authentication Filter</filter-name>
|
<filter-name>WebScript Authentication Filter</filter-name>
|
||||||
<url-pattern>/wcservice/*</url-pattern>
|
<url-pattern>/wcservice/*</url-pattern>
|
||||||
</filter-mapping>
|
</filter-mapping>
|
||||||
|
|
||||||
<filter-mapping>
|
<filter-mapping>
|
||||||
<filter-name>WebScript NTLM Authentication Filter</filter-name>
|
<filter-name>WebScript Authentication Filter</filter-name>
|
||||||
<url-pattern>/wcs/*</url-pattern>
|
<url-pattern>/wcs/*</url-pattern>
|
||||||
</filter-mapping>
|
</filter-mapping>
|
||||||
|
|
||||||
<filter-mapping>
|
<filter-mapping>
|
||||||
<filter-name>Authentication Filter</filter-name>
|
<filter-name>Global Authentication Filter</filter-name>
|
||||||
<url-pattern>/ajax/*</url-pattern>
|
<url-pattern>/ajax/*</url-pattern>
|
||||||
</filter-mapping>
|
</filter-mapping>
|
||||||
-->
|
|
||||||
|
|
||||||
|
<filter-mapping>
|
||||||
|
<filter-name>Global Authentication Filter</filter-name>
|
||||||
|
<url-pattern>/faces/*</url-pattern>
|
||||||
|
</filter-mapping>
|
||||||
|
|
||||||
<filter-mapping>
|
<filter-mapping>
|
||||||
<filter-name>Authentication Filter</filter-name>
|
<filter-name>Authentication Filter</filter-name>
|
||||||
<url-pattern>/faces/*</url-pattern>
|
<url-pattern>/faces/*</url-pattern>
|
||||||
@@ -237,7 +248,7 @@
|
|||||||
</listener>
|
</listener>
|
||||||
|
|
||||||
<listener>
|
<listener>
|
||||||
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
<listener-class>org.alfresco.web.app.ContextLoaderListener</listener-class>
|
||||||
</listener>
|
</listener>
|
||||||
|
|
||||||
<listener>
|
<listener>
|
||||||
@@ -557,4 +568,58 @@
|
|||||||
<location>/jsp/error.jsp</location>
|
<location>/jsp/error.jsp</location>
|
||||||
</error-page>
|
</error-page>
|
||||||
|
|
||||||
|
<resource-ref>
|
||||||
|
<description>The Alfresco database connection</description>
|
||||||
|
<res-ref-name>jdbc/dataSource</res-ref-name>
|
||||||
|
<res-type>javax.sql.DataSource</res-type>
|
||||||
|
<res-auth>Container</res-auth>
|
||||||
|
</resource-ref>
|
||||||
|
|
||||||
|
<env-entry>
|
||||||
|
<description>A flag that globally enables or disables startup of the major Alfresco subsystems.</description>
|
||||||
|
<env-entry-name>properties/startup.enable</env-entry-name>
|
||||||
|
<env-entry-value>true</env-entry-value>
|
||||||
|
<env-entry-type>java.lang.Boolean</env-entry-type>
|
||||||
|
</env-entry>
|
||||||
|
|
||||||
|
<env-entry>
|
||||||
|
<description>The filesystem directory below which content and index data is stored. Should be on a shared disk
|
||||||
|
if this is a clustered installation.</description>
|
||||||
|
<env-entry-name>properties/dir.root</env-entry-name>
|
||||||
|
<env-entry-type>java.lang.String</env-entry-type>
|
||||||
|
</env-entry>
|
||||||
|
|
||||||
|
<env-entry>
|
||||||
|
<description>The fully qualified name of a org.hibernate.dialect.Dialect subclass that allows Hibernate to
|
||||||
|
generate SQL optimized for a particular relational database. Choose from org.hibernate.dialect.DerbyDialect,
|
||||||
|
org.hibernate.dialect.MySQLInnoDBDialect,
|
||||||
|
org.alfresco.repo.domain.hibernate.dialect.AlfrescoOracle9Dialect,
|
||||||
|
org.alfresco.repo.domain.hibernate.dialect.AlfrescoSybaseAnywhereDialect,
|
||||||
|
org.alfresco.repo.domain.hibernate.dialect.AlfrescoSQLServerDialect, org.hibernate.dialect.PostgreSQLDialect</description>
|
||||||
|
<env-entry-name>properties/hibernate.dialect</env-entry-name>
|
||||||
|
<env-entry-type>java.lang.String</env-entry-type>
|
||||||
|
</env-entry>
|
||||||
|
|
||||||
|
<env-entry>
|
||||||
|
<description>Mapping from tokens in Hibernate queries to SQL tokens. For PostgreSQL, set this to "true
|
||||||
|
TRUE, false FALSE".</description>
|
||||||
|
<env-entry-name>properties/hibernate.query.substitutions</env-entry-name>
|
||||||
|
<env-entry-type>java.lang.String</env-entry-type>
|
||||||
|
</env-entry>
|
||||||
|
|
||||||
|
<env-entry>
|
||||||
|
<description>Enable use of JDBC3 PreparedStatement.getGeneratedKeys() to retrieve natively generated keys
|
||||||
|
after insert. Requires JDBC3+ driver. Set to false if your driver has problems with the Hibernate identifier
|
||||||
|
generators. By default, tries to determine the driver capabilities using connection metadata. </description>
|
||||||
|
<env-entry-name>properties/hibernate.jdbc.use_get_generated_keys</env-entry-name>
|
||||||
|
<env-entry-type>java.lang.Boolean</env-entry-type>
|
||||||
|
</env-entry>
|
||||||
|
|
||||||
|
<env-entry>
|
||||||
|
<description>Qualify unqualified table names with the given schema/tablespace in generated SQL. It may be
|
||||||
|
necessary to set this when the target database has more than one schema.</description>
|
||||||
|
<env-entry-name>properties/hibernate.default_schema</env-entry-name>
|
||||||
|
<env-entry-type>java.lang.String</env-entry-type>
|
||||||
|
</env-entry>
|
||||||
|
|
||||||
</web-app>
|
</web-app>
|
69
source/web/jsp/admin/jmx-dumper.jsp
Normal file
69
source/web/jsp/admin/jmx-dumper.jsp
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<%--
|
||||||
|
* Copyright (C) 2005-2009 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
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* 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:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
--%>
|
||||||
|
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
|
||||||
|
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
|
||||||
|
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
|
||||||
|
<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>
|
||||||
|
|
||||||
|
<%@ page buffer="32kb" contentType="text/html;charset=UTF-8" %>
|
||||||
|
<%@ page isELIgnored="false" %>
|
||||||
|
|
||||||
|
<r:page titleId="title_jmx_dumper">
|
||||||
|
|
||||||
|
<f:view>
|
||||||
|
|
||||||
|
<%-- load a bundle of properties with I18N strings --%>
|
||||||
|
<r:loadBundle var="msg"/>
|
||||||
|
|
||||||
|
<h:form id="jmx-dumper-title">
|
||||||
|
|
||||||
|
<table width="100%">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<h:graphicImage value="/images/logo/AlfrescoLogo32.png" alt="Alfresco" />
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<nobr><h:outputText id="titleJmxDumper" styleClass="mainTitle" value="#{msg.title_jmx_dumper}"/></nobr>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</h:form>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<h:outputText id="contextTitle" styleClass="mainTitle" value="#{msg.title_jmx_output}"/>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<pre><h:outputText id="result" value="#{JmxDumperBean.result}"/></pre>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</f:view>
|
||||||
|
|
||||||
|
</r:page>
|
Reference in New Issue
Block a user