Web Scripts as JSR-168 portlets

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5627 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
David Caruana
2007-05-04 15:11:19 +00:00
parent 1618ac1a83
commit fa8309b777
31 changed files with 1981 additions and 885 deletions

View File

@@ -41,11 +41,11 @@
<td align=center height=40>
<table border=0 cellspacing=8 cellpadding=0>
<tr>
<th><a class="filterLink <#if filter=0>filterLinkSelected</#if>" href="${url.service}?f=0&p=${path}">All Items</a></th>
<th><a class="filterLink <#if filter=1>filterLinkSelected</#if>" href="${url.service}?f=1&p=${path}">Word Documents</a></th>
<th><a class="filterLink <#if filter=2>filterLinkSelected</#if>" href="${url.service}?f=2&p=${path}">HTML Documents</a></th>
<th><a class="filterLink <#if filter=3>filterLinkSelected</#if>" href="${url.service}?f=3&p=${path}">PDF Documents</a></th>
<th><a class="filterLink <#if filter=4>filterLinkSelected</#if>" href="${url.service}?f=4&p=${path}">Recently Modified</a></th>
<th><a class="filterLink <#if filter=0>filterLinkSelected</#if>" href="${scripturl("?f=0&p=${path}")}">All Items</a></th>
<th><a class="filterLink <#if filter=1>filterLinkSelected</#if>" href="${scripturl("?f=1&p=${path}")}">Word Documents</a></th>
<th><a class="filterLink <#if filter=2>filterLinkSelected</#if>" href="${scripturl("?f=2&p=${path}")}">HTML Documents</a></th>
<th><a class="filterLink <#if filter=3>filterLinkSelected</#if>" href="${scripturl("?f=3&p=${path}")}">PDF Documents</a></th>
<th><a class="filterLink <#if filter=4>filterLinkSelected</#if>" href="${scripturl("?f=4&p=${path}")}">Recently Modified</a></th>
</tr>
</table>
</td>

View File

@@ -27,11 +27,11 @@
<td align=center height=40 style="border-left: 1px solid #EBE398;">
<table border=0 cellspacing=8 cellpadding=0>
<tr>
<th><a class="filterLink <#if filter=0>filterLinkSelected</#if>" href="${url.service}?f=0">Tasks to do</a></th>
<th><a class="filterLink <#if filter=1>filterLinkSelected</#if>" href="${url.service}?f=1">Due Today</a></th>
<th><a class="filterLink <#if filter=2>filterLinkSelected</#if>" href="${url.service}?f=2">Next 7 days</a></th>
<th><a class="filterLink <#if filter=3>filterLinkSelected</#if>" href="${url.service}?f=3">No due date</a></th>
<th><a class="filterLink <#if filter=4>filterLinkSelected</#if>" href="${url.service}?f=4">Overdue</a></th>
<th><a class="filterLink <#if filter=0>filterLinkSelected</#if>" href="${scripturl("?f=0")}">Tasks to do</a></th>
<th><a class="filterLink <#if filter=1>filterLinkSelected</#if>" href="${scripturl("?f=1")}">Due Today</a></th>
<th><a class="filterLink <#if filter=2>filterLinkSelected</#if>" href="${scripturl("?f=2")}">Next 7 days</a></th>
<th><a class="filterLink <#if filter=3>filterLinkSelected</#if>" href="${scripturl("?f=3")}">No due date</a></th>
<th><a class="filterLink <#if filter=4>filterLinkSelected</#if>" href="${scripturl("?f=4")}">Overdue</a></th>
</tr>
</table>
</td>
@@ -94,7 +94,7 @@
<table class="taskActions" style="padding-left:16px">
<tr>
<#list t.transitions as wt>
<td><a class="taskAction" href="#" onclick="MyTasks.transitionTask('/command/task/end/${t.id}/${wt.id}', '${url.service}?f=${filter}', 'Workflow action \'${wt.label?html}\' completed.');">${wt.label?html}</a></td>
<td><a class="taskAction" href="#" onclick="MyTasks.transitionTask('/command/task/end/${t.id}/${wt.id}', '${scripturl("?f=${filter}")}', 'Workflow action \'${wt.label?html}\' completed.');">${wt.label?html}</a></td>
</#list>
</tr>
</table>

View File

@@ -4,5 +4,6 @@
<url format="html" template="/search/keyword?q={searchTerms}&amp;p={startPage?}&amp;c={count?}&amp;l={language?}&amp;guest={alf:guest?}"/>
<url format="atom" template="/search/keyword?q={searchTerms}&amp;p={startPage?}&amp;c={count?}&amp;l={language?}&amp;guest={alf:guest?}&amp;format=atom"/>
<url format="rss" template="/search/keyword?q={searchTerms}&amp;p={startPage?}&amp;c={count?}&amp;l={language?}&amp;guest={alf:guest?}&amp;format=rss"/>
<url format="portlet" template="/search/keyword?q={searchTerms}&amp;p={startPage?}&amp;c={count?}&amp;l={language?}&amp;guest={alf:guest?}&amp;format=portlet"/>
<authentication>guest</authentication>
</webscript>

View File

@@ -0,0 +1,33 @@
<table>
<tr>
<td>Results <b>${search.startIndex}</b> - <b>${search.startIndex + search.totalPageItems - 1}</b> of <b>${search.totalResults}</b> for <b>${search.searchTerms}</b> visible to user <b><#if person??>${person.properties.userName}<#else>unknown</#if>.</b></td>
</tr>
</table>
<br>
<table>
<#list search.results as row>
<tr>
<td><img src="${url.context}${row.icon16}"/></td><td><a href="${url.context}${row.url}">${row.name}</a></td>
</tr>
<#if row.properties.description?? == true>
<tr>
<td></td>
<td>${row.properties.description}</td>
</tr>
</#if>
</#list>
</table>
<br>
<table>
<tr>
<td><a href="${scripturl("?q=${search.searchTerms?url}&p=1&c=${search.itemsPerPage}&l=${search.localeId}")}">first</a></td>
<#if search.startPage &gt; 1>
<td><a href="${scripturl("?q=${search.searchTerms?url}&p=${search.startPage - 1}&c=${search.itemsPerPage}&l=${search.localeId}")}">previous</a></td>
</#if>
<td><a href="${scripturl("?q=${search.searchTerms?url}&p=${search.startPage}&c=${search.itemsPerPage}&l=${search.localeId}")}">${search.startPage}</a></td>
<#if search.startPage &lt; search.totalPages>
<td><a href="${scripturl("?q=${search.searchTerms?url}&p=${search.startPage + 1}&c=${search.itemsPerPage}&l=${search.localeId}")}">next</a></td>
</#if>
<td><a href="${scripturl("?q=${search.searchTerms?url}&p=${search.totalPages}&c=${search.itemsPerPage}&l=${search.localeId}")}">last</a></td>
</tr>
</table>

View File

@@ -8,11 +8,7 @@
<!-- -->
<bean id="webscripts.test" class="org.alfresco.web.scripts.TestWebScriptServer">
<property name="registry">
<bean parent="webscripts.registry">
<property name="authenticator" ref="webscripts.authenticator.trusted" />
</bean>
</property>
<property name="registry" ref="webscripts.registry" />
<property name="transactionService" ref="transactionComponent" />
<property name="messages">
<bean class="org.springframework.context.support.ResourceBundleMessageSource">

View File

@@ -63,36 +63,24 @@
<bean id="webscripts.registry" class="org.alfresco.web.scripts.DeclarativeWebScriptRegistry">
<property name="storage" ref="webscripts.storage" />
<property name="authenticator" ref="webscripts.authenticator.webclient" />
<property name="serviceLogger" ref="webscripts.logger" />
<property name="serviceTransaction" ref="webscripts.transaction" />
<property name="formatRegistry" ref="webscripts.formatregistry" />
<property name="defaultWebScript"><value>webscript_default</value></property>
</bean>
<!-- Service Logger -->
<bean id="webscripts.logger" class="org.alfresco.web.scripts.WebScriptLogger" />
<!-- Alfresco Web Client Authenticator (Servlet based) -->
<bean id="webscripts.authenticator.webclient" class="org.alfresco.web.scripts.WebClientAuthenticator" />
<!-- Service Transaction -->
<bean id="webscripts.transaction" class="org.alfresco.web.scripts.WebScriptTransaction">
<property name="transactionService" ref="transactionComponent" />
</bean>
<!-- Alfresco Web Client Authenticator -->
<bean id="webscripts.authenticator.webclient" class="org.alfresco.web.scripts.WebClientAuthenticator">
<!-- HTTP Basic Authenticator (Servlet based) -->
<bean id="webscripts.authenticator.basic" class="org.alfresco.web.scripts.BasicHttpAuthenticator">
<property name="authenticationService" ref="AuthenticationService" />
</bean>
<!-- HTTP Basic Authenticator -->
<bean id="webscripts.authenticator.basic" class="org.alfresco.web.scripts.BasicAuthenticator">
<!-- JSR-168 Authenticator (Portal based) -->
<bean id="webscripts.authenticator.jsr168" class="org.alfresco.web.scripts.portlet.WebClientPortletAuthenticator">
<property name="scriptContext" ref="webscripts.context" />
<property name="authenticationService" ref="AuthenticationService" />
</bean>
<!-- System Authenticator -->
<bean id="webscripts.authenticator.system" class="org.alfresco.web.scripts.SystemAuthenticator" />
<!-- Trusted Authenticator -->
<bean id="webscripts.authenticator.trusted" class="org.alfresco.web.scripts.TrustedAuthenticator" />
<!-- -->
@@ -119,6 +107,7 @@
<prop key="json">application/json</prop>
<prop key="opensearchdescription">application/opensearchdescription+xml</prop>
<prop key="wiki">text/plain</prop>
<prop key="portlet">text/html</prop>
</props>
</property>
</bean>

View File

@@ -26,7 +26,6 @@ package org.alfresco.web.scripts;
import java.io.Writer;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
@@ -36,7 +35,6 @@ import org.alfresco.repo.template.AbsoluteUrlMethod;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.ScriptLocation;
import org.alfresco.service.cmr.repository.TemplateImageResolver;
import org.alfresco.service.cmr.repository.TemplateService;
import org.alfresco.service.descriptor.DescriptorService;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
@@ -174,10 +172,9 @@ public abstract class AbstractWebScript implements WebScript
final protected Map<String, String> createArgModel(WebScriptRequest req)
{
Map<String, String> args = new ScriptableHashMap<String, String>();
Enumeration names = req.getParameterNames();
while (names.hasMoreElements())
String[] names = req.getParameterNames();
for (String name : names)
{
String name = (String)names.nextElement();
args.put(name, req.getParameter(name));
}
return args;
@@ -269,6 +266,7 @@ public abstract class AbstractWebScript implements WebScript
// add template support
model.put("absurl", new AbsoluteUrlMethod(req.getServerPath()));
model.put("scripturl", new ScriptUrlMethod(req, res));
model.put("date", new Date());
model.put(TemplateService.KEY_IMAGE_RESOLVER, getWebScriptRegistry().getTemplateImageResolver());

View File

@@ -1,194 +0,0 @@
/*
* Copyright (C) 2005-2007 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"
*/
package org.alfresco.web.scripts;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.util.Base64;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* HTTP Basic Authentication Interceptor
*
* @author davidc
*/
public class BasicAuthenticator implements MethodInterceptor
{
// Logger
private static final Log logger = LogFactory.getLog(BasicAuthenticator.class);
// dependencies
private AuthenticationService authenticationService;
/**
* @param authenticationService
*/
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
/* (non-Javadoc)
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
*/
public Object invoke(MethodInvocation invocation)
throws Throwable
{
boolean authorized = false;
String currentUser = null;
Object retVal = null;
Object[] args = invocation.getArguments();
WebScriptRequest request = (WebScriptRequest)args[0];
WebScript service = (WebScript)invocation.getThis();
WebScriptDescription description = service.getDescription();
try
{
//
// Determine if user already authenticated
//
currentUser = AuthenticationUtil.getCurrentUserName();
if (logger.isDebugEnabled())
logger.debug("Current authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
//
// validate credentials
//
boolean isGuest = request.isGuest();
String authorization = request.getHeader("Authorization");
if (logger.isDebugEnabled())
{
logger.debug("Web Service authentication required: " + description.getRequiredAuthentication());
logger.debug("Guest login: " + isGuest);
logger.debug("Authorization provided (overrides Guest login): " + (authorization != null && authorization.length() > 0));
}
// authenticate as guest, if service allows
if (((authorization == null || authorization.length() == 0) || isGuest)
&& description.getRequiredAuthentication().equals(RequiredAuthentication.guest))
{
if (logger.isDebugEnabled())
logger.debug("Authenticating as Guest");
authenticationService.authenticateAsGuest();
authorized = true;
}
// authenticate as specified by HTTP Basic Authentication
else if (authorization != null && authorization.length() > 0)
{
try
{
String[] authorizationParts = authorization.split(" ");
if (!authorizationParts[0].equalsIgnoreCase("basic"))
{
throw new WebScriptException("Authorization '" + authorizationParts[0] + "' not supported.");
}
String decodedAuthorisation = new String(Base64.decode(authorizationParts[1]));
String[] parts = decodedAuthorisation.split(":");
if (parts.length == 1)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating ticket " + parts[0]);
// assume a ticket has been passed
authenticationService.validate(parts[0]);
authorized = true;
}
else
{
if (logger.isDebugEnabled())
logger.debug("Authenticating user " + parts[0]);
// assume username and password passed
if (parts[0].equals(AuthenticationUtil.getGuestUserName()))
{
if (description.getRequiredAuthentication().equals(RequiredAuthentication.guest))
{
authenticationService.authenticateAsGuest();
authorized = true;
}
}
else
{
authenticationService.authenticate(parts[0], parts[1].toCharArray());
authorized = true;
}
}
}
catch(AuthenticationException e)
{
// failed authentication
}
}
//
// execute web script or request authorization
//
if (authorized)
{
retVal = invocation.proceed();
}
else
{
if (logger.isDebugEnabled())
logger.debug("Requesting authorization credentials");
WebScriptResponse response = (WebScriptResponse)args[1];
response.setStatus(401);
response.setHeader("WWW-Authenticate", "Basic realm=\"Alfresco\"");
}
}
finally
{
// reset authentication
if (authorized)
{
authenticationService.clearCurrentSecurityContext();
if (currentUser != null)
{
AuthenticationUtil.setCurrentUser(currentUser);
}
if (logger.isDebugEnabled())
logger.debug("Authentication reset: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
}
}
return retVal;
}
}

View File

@@ -0,0 +1,151 @@
/*
* Copyright (C) 2005-2007 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"
*/
package org.alfresco.web.scripts;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.util.Base64;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* HTTP Basic Authentication Interceptor
*
* @author davidc
*/
public class BasicHttpAuthenticator implements WebScriptServletAuthenticator
{
// Logger
private static final Log logger = LogFactory.getLog(BasicHttpAuthenticator.class);
// dependencies
private AuthenticationService authenticationService;
/**
* @param authenticationService
*/
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
/* (non-Javadoc)
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
*/
public void authenticate(RequiredAuthentication required, boolean isGuest, HttpServletRequest req, HttpServletResponse res)
{
boolean authorized = false;
//
// validate credentials
//
String authorization = req.getHeader("Authorization");
if (logger.isDebugEnabled())
{
logger.debug("HTTP Authorization provided: " + (authorization != null && authorization.length() > 0));
}
// authenticate as guest, if service allows
if (isGuest)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating as Guest");
authenticationService.authenticateAsGuest();
authorized = true;
}
// authenticate as specified by HTTP Basic Authentication
else if (authorization != null && authorization.length() > 0)
{
try
{
String[] authorizationParts = authorization.split(" ");
if (!authorizationParts[0].equalsIgnoreCase("basic"))
{
throw new WebScriptException("Authorization '" + authorizationParts[0] + "' not supported.");
}
String decodedAuthorisation = new String(Base64.decode(authorizationParts[1]));
String[] parts = decodedAuthorisation.split(":");
if (parts.length == 1)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating ticket " + parts[0]);
// assume a ticket has been passed
authenticationService.validate(parts[0]);
authorized = true;
}
else
{
if (logger.isDebugEnabled())
logger.debug("Authenticating user " + parts[0]);
// assume username and password passed
if (parts[0].equals(AuthenticationUtil.getGuestUserName()))
{
if (required == RequiredAuthentication.guest)
{
authenticationService.authenticateAsGuest();
authorized = true;
}
}
else
{
authenticationService.authenticate(parts[0], parts[1].toCharArray());
authorized = true;
}
}
}
catch(AuthenticationException e)
{
// failed authentication
}
}
//
// request credentials if not authorized
//
if (!authorized)
{
if (logger.isDebugEnabled())
logger.debug("Requesting authorization credentials");
res.setStatus(401);
res.setHeader("WWW-Authenticate", "Basic realm=\"Alfresco\"");
}
}
}

View File

@@ -37,23 +37,20 @@ import java.util.TreeMap;
import javax.servlet.ServletContext;
import org.alfresco.service.cmr.repository.TemplateImageResolver;
import org.alfresco.util.AbstractLifecycleBean;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
import org.alfresco.web.scripts.WebScriptDescription.RequiredTransaction;
import org.alfresco.web.scripts.WebScriptDescription.URI;
import org.alfresco.web.ui.common.Utils;
import org.aopalliance.intercept.MethodInterceptor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.RegexpMethodPointcutAdvisor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.web.context.ServletContextAware;
@@ -62,17 +59,14 @@ import org.springframework.web.context.ServletContextAware;
*
* @author davidc
*/
public class DeclarativeWebScriptRegistry implements WebScriptRegistry, ApplicationContextAware, ServletContextAware, InitializingBean
public class DeclarativeWebScriptRegistry extends AbstractLifecycleBean
implements WebScriptRegistry, ServletContextAware, InitializingBean
{
// Logger
private static final Log logger = LogFactory.getLog(DeclarativeWebScriptRegistry.class);
private ApplicationContext applicationContext;
private ServletContext servletContext;
private String defaultWebScript;
private MethodInterceptor authenticator;
private MethodInterceptor serviceLogger;
private MethodInterceptor serviceTransaction;
private FormatRegistry formatRegistry;
private WebScriptStorage storage;
private TemplateImageResolver imageResolver;
@@ -101,36 +95,6 @@ public class DeclarativeWebScriptRegistry implements WebScriptRegistry, Applicat
this.storage = storage;
}
/**
* Sets the web script authenticator
*
* @param authenticator
*/
public void setAuthenticator(MethodInterceptor authenticator)
{
this.authenticator = authenticator;
}
/**
* Sets the web script logger
*
* @param serviceLogger
*/
public void setServiceLogger(MethodInterceptor serviceLogger)
{
this.serviceLogger = serviceLogger;
}
/**
* Sets the service transaction
*
* @param serviceTransaction
*/
public void setServiceTransaction(MethodInterceptor serviceTransaction)
{
this.serviceTransaction = serviceTransaction;
}
/**
* Sets the default service implementation bean
*
@@ -159,14 +123,6 @@ public class DeclarativeWebScriptRegistry implements WebScriptRegistry, Applicat
this.servletContext = context;
}
/* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
this.applicationContext = applicationContext;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@@ -181,6 +137,33 @@ public class DeclarativeWebScriptRegistry implements WebScriptRegistry, Applicat
};
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#reset()
*/
public void reset()
{
getTemplateProcessor().resetCache();
getScriptProcessor().resetCache();
initWebScripts();
}
/* (non-Javadoc)
* @see org.alfresco.util.AbstractLifecycleBean#onBootstrap(org.springframework.context.ApplicationEvent)
*/
@Override
protected void onBootstrap(ApplicationEvent event)
{
initWebScripts();
}
/* (non-Javadoc)
* @see org.alfresco.util.AbstractLifecycleBean#onShutdown(org.springframework.context.ApplicationEvent)
*/
@Override
protected void onShutdown(ApplicationEvent event)
{
}
/**
* Initialise Web Scripts
*
@@ -245,56 +228,17 @@ public class DeclarativeWebScriptRegistry implements WebScriptRegistry, Applicat
}
// construct service implementation
ApplicationContext applicationContext = getApplicationContext();
String serviceImplName = (applicationContext.containsBean("webscript." + id)) ? "webscript." + id : defaultWebScript;
AbstractWebScript serviceImpl = (AbstractWebScript)applicationContext.getBean(serviceImplName);
serviceImpl.setDescription(serviceDesc);
serviceImpl.init(this);
// wrap service implementation in appropriate interceptors (e.g. authentication)
WebScript serviceImplIF = (WebScript)serviceImpl;
if (serviceLogger != null && serviceTransaction != null && authenticator != null)
{
ProxyFactory authFactory = new ProxyFactory();
authFactory.addInterface(WebScript.class);
authFactory.setTarget(serviceImplIF);
// logging interceptor
if (serviceLogger != null)
{
RegexpMethodPointcutAdvisor advisor = new RegexpMethodPointcutAdvisor(".*execute", serviceLogger);
authFactory.addAdvisor(advisor);
}
// transaction interceptor
if (serviceDesc.getRequiredTransaction() != RequiredTransaction.none)
{
if (serviceTransaction == null)
{
throw new WebScriptException("Web Script Transaction not specified");
}
RegexpMethodPointcutAdvisor advisor = new RegexpMethodPointcutAdvisor(".*execute", serviceTransaction);
authFactory.addAdvisor(advisor);
}
// authentication interceptor
if (serviceDesc.getRequiredAuthentication() != RequiredAuthentication.none)
{
if (authenticator == null)
{
throw new WebScriptException("Web Script Authenticator not specified");
}
RegexpMethodPointcutAdvisor advisor = new RegexpMethodPointcutAdvisor(".*execute", authenticator);
authFactory.addAdvisor(advisor);
}
serviceImplIF = (WebScript)authFactory.getProxy();
}
if (logger.isDebugEnabled())
logger.debug("Found Web Script " + serviceDescPath + " (id: " + id + ", impl: " + serviceImplName + ", auth: " + serviceDesc.getRequiredAuthentication() + ", trx: " + serviceDesc.getRequiredTransaction() + ")");
// register service and its urls
webscriptsById.put(id, serviceImplIF);
webscriptsById.put(id, serviceImpl);
for (URI uri : serviceDesc.getURIs())
{
// establish static part of url template
@@ -323,7 +267,7 @@ public class DeclarativeWebScriptRegistry implements WebScriptRegistry, Applicat
}
else
{
webscriptsByURL.put(uriIdx, serviceImplIF);
webscriptsByURL.put(uriIdx, serviceImpl);
if (logger.isDebugEnabled())
logger.debug("Registered Web Script URL '" + uriIdx + "'");
@@ -476,7 +420,6 @@ public class DeclarativeWebScriptRegistry implements WebScriptRegistry, Applicat
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getWebScripts()
*/
@@ -554,17 +497,6 @@ public class DeclarativeWebScriptRegistry implements WebScriptRegistry, Applicat
return this.storage.getScriptProcessor();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#reset()
*/
public void reset()
{
getTemplateProcessor().resetCache();
getScriptProcessor().resetCache();
initWebScripts();
}
/**
* Web Script Match
*

View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2005-2007 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"
*/
package org.alfresco.web.scripts;
import java.util.List;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateScalarModel;
/**
* @author David Caruana
*
* Custom FreeMarker Template language method.
* <p>
* Render script url independent of script hosting environment e.g. render inside / outside
* portal.
* <p>
* Usage: scripturl(String url)
*/
public final class ScriptUrlMethod implements TemplateMethodModelEx
{
WebScriptRequest req;
WebScriptResponse res;
/**
* Construct
*
* @param basePath base path used to construct absolute url
*/
public ScriptUrlMethod(WebScriptRequest req, WebScriptResponse res)
{
this.req = req;
this.res = res;
}
/**
* @see freemarker.template.TemplateMethodModel#exec(java.util.List)
*/
public Object exec(List args) throws TemplateModelException
{
String result = "";
if (args.size() == 1)
{
Object arg0 = args.get(0);
if (arg0 instanceof TemplateScalarModel)
{
String arg = ((TemplateScalarModel)arg0).getAsString();
String url = req.getServicePath();
url += arg;
url += (arg.length() > 0) ? "&" : "";
url += "guest=" + (req.isGuest() ? "true" : "");
url += (req.getFormat().length() > 0) ? "&format=" + req.getFormat() : "";
result = res.encodeScriptUrl(url);
}
}
return result;
}
}

View File

@@ -1,94 +0,0 @@
/*
* Copyright (C) 2005-2007 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"
*/
package org.alfresco.web.scripts;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* System Authentication Interceptor
*
* @author davidc
*/
public class SystemAuthenticator implements MethodInterceptor
{
// Logger
private static final Log logger = LogFactory.getLog(SystemAuthenticator.class);
/* (non-Javadoc)
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
*/
public Object invoke(MethodInvocation invocation)
throws Throwable
{
String currentUser = null;
Object retVal = null;
try
{
//
// Determine if user already authenticated
//
currentUser = AuthenticationUtil.getCurrentUserName();
if (logger.isDebugEnabled())
logger.debug("Current authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
//
// Force system user
//
if (logger.isDebugEnabled())
logger.debug("Authenticating as System");
AuthenticationUtil.setSystemUserAsCurrentUser();
//
// Invoke service
//
retVal = invocation.proceed();
}
finally
{
AuthenticationUtil.clearCurrentSecurityContext();
if (currentUser != null)
{
AuthenticationUtil.setCurrentUser(currentUser);
}
if (logger.isDebugEnabled())
logger.debug("Authentication reset: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
}
return retVal;
}
}

View File

@@ -88,6 +88,7 @@ public class TestWebScriptServer
this.registry = registry;
}
/**
* Sets the Messages resource bundle
*
@@ -162,15 +163,9 @@ public class TestWebScriptServer
MockHttpServletRequest req = createRequest("get", uri);
MockHttpServletResponse res = new MockHttpServletResponse();
WebScriptMatch match = registry.findWebScript(req.getMethod(), uri);
if (match == null)
{
throw new WebScriptException("No service bound to uri '" + uri + "'");
}
WebScriptRuntime runtime = new WebScriptServletRuntime(registry, transactionService, null, req, res);
runtime.executeScript();
WebScriptRequest apiReq = new WebScriptRequest(req, match);
WebScriptResponse apiRes = new WebScriptResponse(res);
match.getWebScript().execute(apiReq, apiRes);
return res;
}

View File

@@ -1,91 +0,0 @@
/*
* Copyright (C) 2005-2007 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"
*/
package org.alfresco.web.scripts;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Trusted Authentication Interceptor
*
* Just use the currently authenticated user
*
* @author davidc
*/
public class TrustedAuthenticator implements MethodInterceptor
{
// Logger
private static final Log logger = LogFactory.getLog(TrustedAuthenticator.class);
/* (non-Javadoc)
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
*/
public Object invoke(MethodInvocation invocation)
throws Throwable
{
String currentUser = null;
Object retVal = null;
try
{
//
// Determine if user already authenticated
//
currentUser = AuthenticationUtil.getCurrentUserName();
if (logger.isDebugEnabled())
logger.debug("Current authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
//
// Use current authentication
//
//
// Invoke service
//
retVal = invocation.proceed();
}
finally
{
AuthenticationUtil.clearCurrentSecurityContext();
if (currentUser != null)
{
AuthenticationUtil.setCurrentUser(currentUser);
}
if (logger.isDebugEnabled())
logger.debug("Authentication reset: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
}
return retVal;
}
}

View File

@@ -24,16 +24,16 @@
*/
package org.alfresco.web.scripts;
import javax.servlet.ServletContext;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.web.app.servlet.AuthenticationHelper;
import org.alfresco.web.app.servlet.AuthenticationStatus;
import org.alfresco.web.app.servlet.BaseServlet;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.ServletContextAware;
@@ -44,14 +44,13 @@ import org.springframework.web.context.ServletContextAware;
*
* @author davidc
*/
public class WebClientAuthenticator implements MethodInterceptor, ServletContextAware
public class WebClientAuthenticator implements WebScriptServletAuthenticator, ServletContextAware
{
// Logger
private static final Log logger = LogFactory.getLog(WebClientAuthenticator.class);
// dependencies
private ServletContext context;
private AuthenticationService authenticationService;
/* (non-Javadoc)
@@ -62,52 +61,25 @@ public class WebClientAuthenticator implements MethodInterceptor, ServletContext
this.context = context;
}
/**
* @param authenticationService
*/
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
/* (non-Javadoc)
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
* @see org.alfresco.web.scripts.WebScriptServletAuthenticator#authenticate(org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication, boolean, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public Object invoke(MethodInvocation invocation)
throws Throwable
public void authenticate(RequiredAuthentication required, boolean isGuest, HttpServletRequest req, HttpServletResponse res)
{
String currentUser = null;
Object retVal = null;
Object[] args = invocation.getArguments();
WebScriptRequest request = (WebScriptRequest)args[0];
WebScriptResponse response = (WebScriptResponse)args[1];
WebScript service = (WebScript)invocation.getThis();
WebScriptDescription description = service.getDescription();
AuthenticationStatus status = null;
try
{
//
// Determine if user already authenticated
//
currentUser = AuthenticationUtil.getCurrentUserName();
if (logger.isDebugEnabled())
logger.debug("Current authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
//
// validate credentials
//
String ticket = request.getParameter("ticket");
boolean isGuest = request.isGuest();
String ticket = req.getParameter("ticket");
if (logger.isDebugEnabled())
{
logger.debug("Web Script authentication required: " + description.getRequiredAuthentication());
logger.debug("Guest login: " + isGuest);
logger.debug("Ticket provided: " + (ticket != null && ticket.length() > 0));
logger.debug("Alfresco ticket provided: " + (ticket != null && ticket.length() > 0));
}
if (ticket != null && ticket.length() > 0)
@@ -115,59 +87,43 @@ public class WebClientAuthenticator implements MethodInterceptor, ServletContext
if (logger.isDebugEnabled())
logger.debug("Authenticating ticket " + ticket);
status = AuthenticationHelper.authenticate(context, request, response, ticket);
status = AuthenticationHelper.authenticate(context, req, res, ticket);
}
else
{
if (isGuest && description.getRequiredAuthentication() == RequiredAuthentication.guest)
if (isGuest)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating as Guest");
status = AuthenticationHelper.authenticate(context, request, response, true);
status = AuthenticationHelper.authenticate(context, req, res, true);
}
else
{
if (logger.isDebugEnabled())
logger.debug("Authenticating session");
status = AuthenticationHelper.authenticate(context, request, response, false);
status = AuthenticationHelper.authenticate(context, req, res, false);
}
}
//
// execute web script or request authorization
// if not authorized, redirect to login page
//
if (status != null && status != AuthenticationStatus.Failure)
{
retVal = invocation.proceed();
}
else
if (status == null || status == AuthenticationStatus.Failure)
{
// authentication failed - now need to display the login page to the user, if asked to
if (logger.isDebugEnabled())
logger.debug("Redirecting to Alfresco Login");
BaseServlet.redirectToLoginPage(request, response, context);
BaseServlet.redirectToLoginPage(req, res, context);
}
}
finally
catch(IOException e)
{
if (status != null && status != AuthenticationStatus.Failure)
{
authenticationService.clearCurrentSecurityContext();
if (currentUser != null)
{
AuthenticationUtil.setCurrentUser(currentUser);
}
if (logger.isDebugEnabled())
logger.debug("Authentication reset: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
throw new WebScriptException("Failed to authenticate", e);
}
}
return retVal;
}
}

View File

@@ -1,73 +0,0 @@
/*
* Copyright (C) 2005-2007 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"
*/
package org.alfresco.web.scripts;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Web Script Logger
*
* @author davidc
*/
public class WebScriptLogger implements MethodInterceptor
{
// Logger
private static final Log logger = LogFactory.getLog(WebScriptLogger.class);
/* (non-Javadoc)
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
*/
public Object invoke(MethodInvocation invocation)
throws Throwable
{
Object retVal = null;
if (logger.isDebugEnabled())
{
WebScript service = (WebScript)invocation.getThis();
WebScriptDescription description = service.getDescription();
String user = AuthenticationUtil.getCurrentUserName();
String locale = I18NUtil.getLocale().toString();
logger.debug("Invoking Web Script " + description.getId() + (user == null ? " (unauthenticated)" : " (authenticated as " + user + ")" + " (" + locale + ")"));
long start = System.currentTimeMillis();
retVal = invocation.proceed();
long end = System.currentTimeMillis();
logger.debug("Web Script " + description.getId() + " executed in " + (end - start) + "ms");
}
else
{
retVal = invocation.proceed();
}
return retVal;
}
}

View File

@@ -0,0 +1,318 @@
/*
* Copyright (C) 2005-2007 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"
*/
package org.alfresco.web.scripts;
import java.io.IOException;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.TransactionUtil;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
import org.alfresco.web.scripts.WebScriptDescription.RequiredTransaction;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Encapsulates the execution of a single Web Script.
*
* Provides support for logging, transactions and authentication.
*
* Sub-classes of WebScriptRuntime maintain the execution environment e.g. servlet
* request & response.
*
* A new instance of WebScriptRuntime is required for each new execution environment.
*
* @author davidc
*/
public abstract class WebScriptRuntime
{
// Logger
protected static final Log logger = LogFactory.getLog(WebScriptRuntime.class);
/** Component Dependencies */
private WebScriptRegistry registry;
private TransactionService transactionService;
/**
* Construct
*
* @param registry web script registry
* @param transactionService transaction service
*/
public WebScriptRuntime(WebScriptRegistry registry, TransactionService transactionService)
{
this.registry = registry;
this.transactionService = transactionService;
}
/**
* Execute the Web Script encapsulated by this Web Script Runtime
*/
public void executeScript()
{
long startRuntime = System.currentTimeMillis();
String method = getScriptMethod();
String scriptUrl = getScriptUrl();
try
{
if (logger.isDebugEnabled())
logger.debug("Processing script url (" + method + ") " + scriptUrl);
WebScriptMatch match = registry.findWebScript(method, scriptUrl);
if (match != null)
{
// setup web script context
final WebScriptRequest scriptReq = createRequest(match);
final WebScriptResponse scriptRes = createResponse();
if (logger.isDebugEnabled())
logger.debug("Agent: " + scriptReq.getAgent());
long startScript = System.currentTimeMillis();
final WebScript script = match.getWebScript();
final WebScriptDescription description = script.getDescription();
try
{
if (logger.isDebugEnabled())
{
String user = AuthenticationUtil.getCurrentUserName();
String locale = I18NUtil.getLocale().toString();
logger.debug("Invoking Web Script " + description.getId() + (user == null ? " (unauthenticated)" : " (authenticated as " + user + ")" + " (" + locale + ")"));
}
if (description.getRequiredTransaction() == RequiredTransaction.none)
{
authenticatedExecute(scriptReq, scriptRes);
}
else
{
// encapsulate script within transaction
TransactionUtil.TransactionWork<Object> work = new TransactionUtil.TransactionWork<Object>()
{
public Object doWork() throws Throwable
{
if (logger.isDebugEnabled())
logger.debug("Begin transaction: " + description.getRequiredTransaction());
authenticatedExecute(scriptReq, scriptRes);
if (logger.isDebugEnabled())
logger.debug("End transaction: " + description.getRequiredTransaction());
return null;
}
};
if (description.getRequiredTransaction() == RequiredTransaction.required)
{
TransactionUtil.executeInUserTransaction(transactionService, work);
}
else
{
TransactionUtil.executeInNonPropagatingUserTransaction(transactionService, work);
}
}
}
catch(IOException e)
{
throw new WebScriptException("Failed to execute script", e);
}
finally
{
if (logger.isDebugEnabled())
{
long endScript = System.currentTimeMillis();
logger.debug("Web Script " + description.getId() + " executed in " + (endScript - startScript) + "ms");
}
}
}
else
{
String msg = "Script url (" + method + ") " + scriptUrl + " does not map to a Web Script.";
if (logger.isDebugEnabled())
logger.debug(msg);
throw new WebScriptException(msg);
}
}
finally
{
long endRuntime = System.currentTimeMillis();
if (logger.isDebugEnabled())
logger.debug("Processed script url (" + method + ") " + scriptUrl + " in " + (endRuntime - startRuntime) + "ms");
}
}
/**
* Execute script whilst authenticated
*
* @param scriptReq Web Script Request
* @param scriptRes Web Script Response
* @throws IOException
*/
protected void authenticatedExecute(WebScriptRequest scriptReq, WebScriptResponse scriptRes)
throws IOException
{
WebScript script = scriptReq.getServiceMatch().getWebScript();
WebScriptDescription desc = script.getDescription();
RequiredAuthentication required = desc.getRequiredAuthentication();
boolean isGuest = scriptReq.isGuest();
if (required == RequiredAuthentication.none)
{
wrappedExecute(scriptReq, scriptRes);
}
else if (required == RequiredAuthentication.user && isGuest)
{
throw new WebScriptException("Web Script " + desc.getId() + " requires user authentication; however, a guest has attempted access.");
}
else
{
String currentUser = null;
try
{
//
// Determine if user already authenticated
//
currentUser = AuthenticationUtil.getCurrentUserName();
if (logger.isDebugEnabled())
{
logger.debug("Current authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
logger.debug("Authentication required: " + required);
logger.debug("Guest login: " + isGuest);
}
//
// Apply appropriate authentication to Web Script invocation
//
authenticate(required, isGuest);
//
// Execute Web Script
wrappedExecute(scriptReq, scriptRes);
}
finally
{
//
// Reset authentication for current thread
//
AuthenticationUtil.clearCurrentSecurityContext();
if (currentUser != null)
{
AuthenticationUtil.setCurrentUser(currentUser);
}
if (logger.isDebugEnabled())
logger.debug("Authentication reset: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
}
}
}
/**
* Execute Web Script with pre & post hooks
*
* @param scriptReq Web Script Request
* @param scriptRes Web Script Response
* @throws IOException
*/
protected void wrappedExecute(WebScriptRequest scriptReq, WebScriptResponse scriptRes)
throws IOException
{
boolean execute = preExecute(scriptReq, scriptRes);
if (execute)
{
WebScript script = scriptReq.getServiceMatch().getWebScript();
script.execute(scriptReq, scriptRes);
postExecute(scriptReq, scriptRes);
}
}
/**
* Get the Web Script Method e.g. get, post
*
* @return web script method
*/
protected abstract String getScriptMethod();
/**
* Get the Web Script Url
*
* @return web script url
*/
protected abstract String getScriptUrl();
/**
* Create a Web Script Request
*
* @param match web script matching the script method and url
* @return web script request
*/
protected abstract WebScriptRequest createRequest(WebScriptMatch match);
/**
* Create a Web Script Response
*
* @return web script response
*/
protected abstract WebScriptResponse createResponse();
/**
* Authenticate Web Script execution
*
* @param required required level of authentication
* @param isGuest is the request accessed as Guest
*/
protected abstract void authenticate(RequiredAuthentication required, boolean isGuest);
/**
* Pre-execution hook
*
* @param scriptReq Web Script Request
* @param scriptRes Web Script Response
* @return true => execute script, false => do not execute script
*/
protected abstract boolean preExecute(WebScriptRequest scriptReq, WebScriptResponse scriptRes);
/**
* Post-execution hook
*
* Note: this hook is not invoked if the script is not executed.
*
* @param scriptReq Web Script Request
* @param scriptRes Web Script Response
*/
protected abstract void postExecute(WebScriptRequest scriptReq, WebScriptResponse scriptRes);
}

View File

@@ -31,6 +31,7 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
@@ -49,8 +50,11 @@ public class WebScriptServlet extends HttpServlet
// Logger
private static final Log logger = LogFactory.getLog(WebScriptServlet.class);
// Web Scripts
// Component Dependencies
private DeclarativeWebScriptRegistry registry;
private TransactionService transactionService;
private WebScriptServletAuthenticator authenticator;
@Override
@@ -59,12 +63,21 @@ public class WebScriptServlet extends HttpServlet
super.init();
ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
registry = (DeclarativeWebScriptRegistry)context.getBean("webscripts.registry");
registry.initWebScripts();
transactionService = (TransactionService)context.getBean("transactionComponent");
// retrieve authenticator via servlet initialisation parameter
String authenticatorId = getInitParameter("authenticator");
if (authenticatorId == null || authenticatorId.length() == 0)
{
authenticatorId = "webscripts.authenticator.webclient";
}
Object bean = context.getBean(authenticatorId);
if (bean == null || !(bean instanceof WebScriptServletAuthenticator))
{
throw new ServletException("Initialisation parameter 'authenticator' does not refer to a Web Script authenticator (" + authenticatorId + ")");
}
authenticator = (WebScriptServletAuthenticator)bean;
}
// TODO:
// - authentication (as suggested in http://www.xml.com/pub/a/2003/12/17/dive.html)
/*
@@ -75,48 +88,17 @@ public class WebScriptServlet extends HttpServlet
*/
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
{
long start = System.currentTimeMillis();
try
{
//
// Execute appropriate web scripy
//
// TODO: Handle errors (with appropriate HTTP error responses)
String uri = req.getPathInfo();
if (logger.isDebugEnabled())
logger.debug("Processing request (" + req.getMethod() + ") " + req.getRequestURL() + (req.getQueryString() != null ? "?" + req.getQueryString() : ""));
WebScriptMatch match = registry.findWebScript(req.getMethod(), uri);
if (match != null)
try
{
// setup web script context
WebScriptRequest apiReq = new WebScriptRequest(req, match);
WebScriptResponse apiRes = new WebScriptResponse(res);
if (logger.isDebugEnabled())
logger.debug("Agent: " + apiReq.getAgent());
// execute service
match.getWebScript().execute(apiReq, apiRes);
WebScriptRuntime runtime = new WebScriptServletRuntime(registry, transactionService, authenticator, req, res);
runtime.executeScript();
}
else
catch(Throwable e)
{
if (logger.isDebugEnabled())
logger.debug("Request does not map to service.");
res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
// TODO: add appropriate error detail
}
}
// TODO: exception handling
finally
{
long end = System.currentTimeMillis();
if (logger.isDebugEnabled())
logger.debug("Processed request (" + req.getMethod() + ") " + req.getRequestURL() + (req.getQueryString() != null ? "?" + req.getQueryString() : "") + " in " + (end - start) + "ms");
}
}

View File

@@ -24,33 +24,28 @@
*/
package org.alfresco.web.scripts;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
/**
* API Service Response
* Web Script Authenticator for the HTTP Servlet environment
*
* @author davidc
*/
public class WebScriptResponse extends HttpServletResponseWrapper
public interface WebScriptServletAuthenticator
{
// API Formats
public static final String HTML_FORMAT = "html";
public static final String ATOM_FORMAT = "atom";
public static final String RSS_FORMAT = "rss";
public static final String XML_FORMAT = "xml";
public static final String JSON_FORMAT = "json";
public static final String OPENSEARCH_DESCRIPTION_FORMAT = "opensearchdescription";
/**
* Construct
* Authenticate Web Script execution
*
* @param res
* @param required required level of authentication
* @param isGuest is Guest accessing the web script
* @param req http servlet request
* @param res http servlet response
*/
WebScriptResponse(HttpServletResponse res)
{
super(res);
}
public void authenticate(RequiredAuthentication required, boolean isGuest, HttpServletRequest req, HttpServletResponse res);
}

View File

@@ -24,17 +24,21 @@
*/
package org.alfresco.web.scripts;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* Web Script Request
* HTTP Servlet Web Script Request
*
* @author davidc
*/
public class WebScriptRequest extends HttpServletRequestWrapper
public class WebScriptServletRequest implements WebScriptRequest
{
/** HTTP Request */
private HttpServletRequest req;
/** Service bound to this request */
private WebScriptMatch serviceMatch;
@@ -45,12 +49,22 @@ public class WebScriptRequest extends HttpServletRequestWrapper
* @param req
* @param serviceMatch
*/
WebScriptRequest(HttpServletRequest req, WebScriptMatch serviceMatch)
WebScriptServletRequest(HttpServletRequest req, WebScriptMatch serviceMatch)
{
super(req);
this.req = req;
this.serviceMatch = serviceMatch;
}
/**
* Gets the HTTP Servlet Request
*
* @return HTTP Servlet Request
*/
public HttpServletRequest getHttpServletRequest()
{
return req;
}
/**
* Gets the matching API Service for this request
*
@@ -70,7 +84,15 @@ public class WebScriptRequest extends HttpServletRequestWrapper
*/
public String getServerPath()
{
return getScheme() + "://" + getServerName() + ":" + getServerPort();
return req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getContextPath()
*/
public String getContextPath()
{
return req.getContextPath();
}
/**
@@ -80,7 +102,7 @@ public class WebScriptRequest extends HttpServletRequestWrapper
*/
public String getServiceContextPath()
{
return getContextPath() + getServletPath();
return req.getContextPath() + req.getServletPath();
}
/**
@@ -90,7 +112,7 @@ public class WebScriptRequest extends HttpServletRequestWrapper
*/
public String getServicePath()
{
return getServiceContextPath() + getPathInfo();
return getServiceContextPath() + req.getPathInfo();
}
/**
@@ -100,7 +122,34 @@ public class WebScriptRequest extends HttpServletRequestWrapper
*/
public String getURL()
{
return getServicePath() + (getQueryString() != null ? "?" + getQueryString() : "");
return getServicePath() + (req.getQueryString() != null ? "?" + req.getQueryString() : "");
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getQueryString()
*/
public String getQueryString()
{
return req.getQueryString();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getParameterNames()
*/
public String[] getParameterNames()
{
Set<String> keys = req.getParameterMap().keySet();
String[] names = new String[keys.size()];
keys.toArray(names);
return names;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getParameter(java.lang.String)
*/
public String getParameter(String name)
{
return req.getParameter(name);
}
/**
@@ -117,7 +166,7 @@ public class WebScriptRequest extends HttpServletRequestWrapper
public String getExtensionPath()
{
String servicePath = serviceMatch.getPath();
String extensionPath = getPathInfo();
String extensionPath = req.getPathInfo();
int extIdx = extensionPath.indexOf(servicePath);
if (extIdx != -1)
{
@@ -157,7 +206,7 @@ public class WebScriptRequest extends HttpServletRequestWrapper
*/
public String getAgent()
{
String userAgent = getHeader("user-agent");
String userAgent = req.getHeader("user-agent");
if (userAgent != null)
{
if (userAgent.indexOf("Firefox/") != -1)
@@ -171,4 +220,5 @@ public class WebScriptRequest extends HttpServletRequestWrapper
}
return null;
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2005-2007 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"
*/
package org.alfresco.web.scripts;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* HTTP Servlet Web Script Response
*
* @author davidc
*/
public class WebScriptServletResponse implements WebScriptResponse
{
private HttpServletResponse res;
/**
* Construct
*
* @param res
*/
WebScriptServletResponse(HttpServletResponse res)
{
this.res = res;
}
/**
* Gets the HTTP Servlet Response
*
* @return HTTP Servlet Response
*/
public HttpServletResponse getHttpServletResponse()
{
return res;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#setContentType(java.lang.String)
*/
public void setContentType(String contentType)
{
res.setContentType(contentType);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#getWriter()
*/
public Writer getWriter() throws IOException
{
return res.getWriter();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#getOutputStream()
*/
public OutputStream getOutputStream() throws IOException
{
return res.getOutputStream();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#encodeScriptUrl(java.lang.String)
*/
public String encodeScriptUrl(String url)
{
return url;
}
}

View File

@@ -0,0 +1,128 @@
/*
* Copyright (C) 2005-2007 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"
*/
package org.alfresco.web.scripts;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
/**
* HTTP Servlet Web Script Runtime
*
* @author davidc
*/
public class WebScriptServletRuntime extends WebScriptRuntime
{
private HttpServletRequest req;
private HttpServletResponse res;
private WebScriptServletAuthenticator authenticator;
/**
* Construct
*
* @param registry
* @param transactionService
* @param authenticator
* @param req
* @param res
*/
public WebScriptServletRuntime(WebScriptRegistry registry, TransactionService transactionService, WebScriptServletAuthenticator authenticator, HttpServletRequest req, HttpServletResponse res)
{
super(registry, transactionService);
this.req = req;
this.res = res;
this.authenticator = authenticator;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#getScriptMethod()
*/
@Override
protected String getScriptMethod()
{
return req.getMethod();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#getScriptUrl()
*/
@Override
protected String getScriptUrl()
{
return req.getPathInfo();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#createRequest(org.alfresco.web.scripts.WebScriptMatch)
*/
@Override
protected WebScriptRequest createRequest(WebScriptMatch match)
{
return new WebScriptServletRequest(req, match);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#createResponse()
*/
@Override
protected WebScriptResponse createResponse()
{
return new WebScriptServletResponse(res);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#authenticate(org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication, boolean)
*/
@Override
protected void authenticate(RequiredAuthentication required, boolean isGuest)
{
if (authenticator != null)
{
authenticator.authenticate(required, isGuest, req, res);
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#preExecute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected boolean preExecute(WebScriptRequest scriptReq, WebScriptResponse scriptRes)
{
return true;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#postExecute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected void postExecute(WebScriptRequest scriptReq, WebScriptResponse scriptRes)
{
}
}

View File

@@ -1,100 +0,0 @@
/*
* Copyright (C) 2005-2007 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"
*/
package org.alfresco.web.scripts;
import org.alfresco.repo.transaction.TransactionUtil;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.web.scripts.WebScriptDescription.RequiredTransaction;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Web Script Transaction
*
* @author davidc
*/
public class WebScriptTransaction implements MethodInterceptor
{
// Logger
protected static final Log logger = LogFactory.getLog(WebScriptTransaction.class);
// dependencies
private TransactionService transactionService;
/**
* Sets the transaction service
*
* @param transactionService
*/
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;
}
/* (non-Javadoc)
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
*/
public Object invoke(final MethodInvocation invocation)
throws Throwable
{
WebScript service = (WebScript)invocation.getThis();
final WebScriptDescription description = service.getDescription();
// encapsulate service call within transaction
TransactionUtil.TransactionWork<Object> work = new TransactionUtil.TransactionWork<Object>()
{
public Object doWork() throws Throwable
{
if (logger.isDebugEnabled())
logger.debug("Begin transaction: " + description.getRequiredTransaction());
Object retVal = invocation.proceed();
if (logger.isDebugEnabled())
logger.debug("End transaction: " + description.getRequiredTransaction());
return retVal;
}
};
// execute call within transaction
Object retVal;
if (description.getRequiredTransaction() == RequiredTransaction.required)
{
retVal = TransactionUtil.executeInUserTransaction(transactionService, work);
}
else
{
retVal = TransactionUtil.executeInNonPropagatingUserTransaction(transactionService, work);
}
return retVal;
}
}

View File

@@ -47,6 +47,7 @@ import org.alfresco.web.scripts.FormatRegistry;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptResponse;
import org.alfresco.web.scripts.WebScriptServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Attribute;
@@ -164,7 +165,13 @@ public class SearchProxy extends AbstractWebScript implements InitializingBean
logger.debug("Mapping engine '" + engine + "' (mimetype '" + mimetype + "') to url '" + engineUrl + "'");
// issue request against search engine
SearchEngineHttpProxy proxy = new SearchEngineHttpProxy(req.getServicePath() + "/" + req.getContextPath(), engine, engineUrl, res);
// NOTE: This web script must be executed in a HTTP servlet environment
if (!(res instanceof WebScriptServletResponse))
{
throw new WebScriptException("Search Proxy must be executed in HTTP Servlet environment");
}
HttpServletResponse servletRes = ((WebScriptServletResponse)req).getHttpServletResponse();
SearchEngineHttpProxy proxy = new SearchEngineHttpProxy(req.getServicePath() + "/" + req.getContextPath(), engine, engineUrl, servletRes);
proxy.service();
}

View File

@@ -0,0 +1,158 @@
/*
* Copyright (C) 2005-2007 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"
*/
package org.alfresco.web.scripts.portlet;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.web.app.servlet.AuthenticationHelper;
import org.alfresco.web.bean.repository.User;
import org.alfresco.web.scripts.WebScriptContext;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Portlet authenticator which synchronizes with the Alfresco Web Client authentication
*
* @author davidc
*/
public class WebClientPortletAuthenticator implements WebScriptPortletAuthenticator
{
// Logger
private static final Log logger = LogFactory.getLog(WebClientPortletAuthenticator.class);
// dependencies
private AuthenticationService authenticationService;
private WebScriptContext scriptContext;
/**
* @param authenticationService
*/
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
/**
* @param scriptContext
*/
public void setScriptContext(WebScriptContext scriptContext)
{
this.scriptContext = scriptContext;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.portlet.WebScriptPortletAuthenticator#authenticate(org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication, boolean, javax.portlet.RenderRequest, javax.portlet.RenderResponse)
*/
public void authenticate(RequiredAuthentication required, boolean isGuest, RenderRequest req, RenderResponse res)
{
PortletSession session = req.getPortletSession();
String portalUser = req.getRemoteUser();
if (logger.isDebugEnabled())
{
logger.debug("JSR-168 Remote user: " + portalUser);
}
if (isGuest || portalUser == null)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating as Guest");
// authenticate as guest
AuthenticationUtil.setCurrentUser(AuthenticationUtil.getGuestUserName());
if (logger.isDebugEnabled())
logger.debug("Setting Web Client authentication context for guest");
createWebClientUser(session);
removeSessionInvalidated(session);
}
else
{
if (logger.isDebugEnabled())
logger.debug("Authenticating as user " + portalUser);
AuthenticationUtil.setCurrentUser(portalUser);
// determine if Web Client context needs to be updated
User user = getWebClientUser(session);
if (user == null || !portalUser.equals(user.getUserName()))
{
if (logger.isDebugEnabled())
logger.debug("Setting Web Client authentication context for user " + portalUser);
createWebClientUser(session);
removeSessionInvalidated(session);
}
}
}
/**
* Helper. Remove Web Client session invalidated flag
*
* @param session
*/
private void removeSessionInvalidated(PortletSession session)
{
session.removeAttribute(AuthenticationHelper.SESSION_INVALIDATED, PortletSession.APPLICATION_SCOPE);
}
/**
* Helper. Create Web Client session user
*
* @param session
*/
private void createWebClientUser(PortletSession session)
{
NodeRef personRef = scriptContext.getPerson();
User user = new User(authenticationService.getCurrentUserName(), authenticationService.getCurrentTicket(), personRef);
NodeRef homeRef = scriptContext.getUserHome(personRef);
if (homeRef != null)
{
user.setHomeSpaceId(homeRef.getId());
}
session.setAttribute(AuthenticationHelper.AUTHENTICATION_USER, user, PortletSession.APPLICATION_SCOPE);
}
/**
* Helper. Get Web Client session user
*
* @param session
* @return
*/
private User getWebClientUser(PortletSession session)
{
return (User)session.getAttribute(AuthenticationHelper.AUTHENTICATION_USER, PortletSession.APPLICATION_SCOPE);
}
}

View File

@@ -0,0 +1,287 @@
/*
* Copyright (C) 2005-2007 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"
*/
package org.alfresco.web.scripts.portlet;
import java.io.IOException;
import java.util.Map;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.Portlet;
import javax.portlet.PortletConfig;
import javax.portlet.PortletContext;
import javax.portlet.PortletException;
import javax.portlet.PortletMode;
import javax.portlet.PortletSecurityException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.WindowState;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.web.scripts.DeclarativeWebScriptRegistry;
import org.alfresco.web.scripts.WebScript;
import org.alfresco.web.scripts.WebScriptDescription;
import org.alfresco.web.scripts.WebScriptMatch;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptResponse;
import org.alfresco.web.scripts.WebScriptRuntime;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.WebApplicationContext;
/**
* Generic JSR-168 Portlet for hosting an Alfresco Web Script as a Portlet.
*
* Accepts the following init-config:
*
* scriptUrl => the url of the web script to host e.g. /alfresco/service/mytasks
*
* @author davidc
*/
public class WebScriptPortlet implements Portlet
{
private static Log logger = LogFactory.getLog(WebScriptPortlet.class);
// Portlet initialisation
protected String initScriptUrl = null;
// Component Dependencies
protected DeclarativeWebScriptRegistry registry;
protected TransactionService transactionService;
protected WebScriptPortletAuthenticator authenticator;
/* (non-Javadoc)
* @see javax.portlet.Portlet#init(javax.portlet.PortletConfig)
*/
public void init(PortletConfig config) throws PortletException
{
initScriptUrl = config.getInitParameter("scriptUrl");
PortletContext portletCtx = config.getPortletContext();
WebApplicationContext ctx = (WebApplicationContext)portletCtx.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
registry = (DeclarativeWebScriptRegistry)ctx.getBean("webscripts.registry");
transactionService = (TransactionService)ctx.getBean("transactionComponent");
authenticator = (WebScriptPortletAuthenticator)ctx.getBean("webscripts.authenticator.jsr168");
}
/* (non-Javadoc)
* @see javax.portlet.Portlet#processAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse)
*/
public void processAction(ActionRequest req, ActionResponse res) throws PortletException, PortletSecurityException, IOException
{
Map<String, String[]> params = req.getParameterMap();
for (Map.Entry<String, String[]> param : params.entrySet())
{
String name = param.getKey();
if (name.equals("scriptUrl") || name.startsWith("arg."))
{
res.setRenderParameter(name, param.getValue());
}
}
}
/* (non-Javadoc)
* @see javax.portlet.Portlet#render(javax.portlet.RenderRequest, javax.portlet.RenderResponse)
*/
public void render(RenderRequest req, RenderResponse res) throws PortletException, PortletSecurityException, IOException
{
PortletMode portletMode = req.getPortletMode();
if (PortletMode.VIEW.equals(portletMode))
{
doView(req, res);
}
// else if (PortletMode.HELP.equals(portletMode))
// {
// doHelp(request, response);
// }
// else if (PortletMode.EDIT.equals(portletMode))
// {
// doEdit(request, response);
// }
}
/* (non-Javadoc)
* @see javax.portlet.Portlet#destroy()
*/
public void destroy()
{
}
/**
* Render Web Script view
*
* @param req
* @param res
* @throws PortletException
* @throws PortletSecurityException
* @throws IOException
*/
protected void doView(RenderRequest req, RenderResponse res) throws PortletException, PortletSecurityException, IOException
{
//
// Establish Web Script URL
//
String scriptUrl = req.getParameter("scriptUrl");
if (scriptUrl != null)
{
// build web script url from render request
String scriptUrlArgs = "";
Map<String, String[]> params = req.getParameterMap();
for (Map.Entry<String, String[]> param : params.entrySet())
{
String name = param.getKey();
if (name.startsWith("arg."))
{
String argName = name.substring("arg.".length());
for (String argValue : param.getValue())
{
scriptUrlArgs += (scriptUrlArgs.length() == 0) ? "" : "&";
scriptUrlArgs += argName + "=" + argValue;
}
}
}
scriptUrl += "?" + scriptUrlArgs;
}
else
{
// retrieve initial scriptUrl as configured by Portlet
scriptUrl = initScriptUrl;
if (scriptUrl == null)
{
throw new PortletException("Initial Web script URL has not been specified.");
}
}
//
// Execute Web Script
//
if (logger.isDebugEnabled())
logger.debug("Processing portal render request " + req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + "/" + req.getContextPath() + " (scriptUrl=" + scriptUrl + ")");
WebScriptRuntime runtime = new WebScriptPortalRuntime(req, res, scriptUrl);
runtime.executeScript();
}
/**
* JSR-168 Web Script Runtime
*
* @author davidc
*/
private class WebScriptPortalRuntime extends WebScriptRuntime
{
private RenderRequest req;
private RenderResponse res;
private String[] requestUrlParts;
/**
* Construct
* @param req
* @param res
* @param requestUrl
*/
public WebScriptPortalRuntime(RenderRequest req, RenderResponse res, String requestUrl)
{
super(registry, transactionService);
this.req = req;
this.res = res;
this.requestUrlParts = WebScriptPortletRequest.getScriptUrlParts(requestUrl);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#getScriptMethod()
*/
@Override
protected String getScriptMethod()
{
return "get";
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#getScriptUrl()
*/
@Override
protected String getScriptUrl()
{
return requestUrlParts[2];
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#createRequest(org.alfresco.web.scripts.WebScriptMatch)
*/
@Override
protected WebScriptRequest createRequest(WebScriptMatch match)
{
return new WebScriptPortletRequest(req, requestUrlParts, match);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#createResponse()
*/
@Override
protected WebScriptResponse createResponse()
{
return new WebScriptPortletResponse(res);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#authenticate(org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication, boolean)
*/
@Override
protected void authenticate(RequiredAuthentication required, boolean isGuest)
{
authenticator.authenticate(required, isGuest, req, res);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#preExecute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected boolean preExecute(WebScriptRequest scriptReq, WebScriptResponse scriptRes)
{
// Set Portlet title based on Web Script
WebScript script = scriptReq.getServiceMatch().getWebScript();
WebScriptDescription desc = script.getDescription();
res.setTitle(desc.getShortName());
// Note: Do not render script if portlet window is minimized
return !WindowState.MINIMIZED.equals(req.getWindowState());
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#postExecute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected void postExecute(WebScriptRequest scriptReq, WebScriptResponse scriptRes)
{
}
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2005-2007 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"
*/
package org.alfresco.web.scripts.portlet;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
/**
* Web Script Authenticator for the JSR-168 environment
*
* @author davidc
*/
public interface WebScriptPortletAuthenticator
{
/**
* Authenticate Web Script execution
*
* @param required required level of authentication
* @param isGuest is Guest accessing the web script
* @param req portlet render request
* @param res portlet render response
*/
public void authenticate(RequiredAuthentication required, boolean isGuest, RenderRequest req, RenderResponse res);
}

View File

@@ -0,0 +1,265 @@
/*
* Copyright (C) 2005-2007 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"
*/
package org.alfresco.web.scripts.portlet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.portlet.PortletRequest;
import org.alfresco.web.scripts.WebScriptMatch;
import org.alfresco.web.scripts.WebScriptRequest;
/**
* JSR-168 Web Script Request
*
* @author davidc
*/
public class WebScriptPortletRequest implements WebScriptRequest
{
/** Portlet Request */
private PortletRequest req;
/** Script Url components */
private String contextPath;
private String servletPath;
private String pathInfo;
private String queryString;
private Map<String, String> queryArgs;
/** Service bound to this request */
private WebScriptMatch serviceMatch;
/**
* Splits a portlet scriptUrl into its component parts
*
* @param scriptUrl url e.g. /alfresco/service/mytasks?f=1
* @return url parts [0] = context (e.g. alfresco), [1] = servlet (e.g. service), [2] = script (e.g. mytasks), [3] = args (e.g. f=1)
*/
public static String[] getScriptUrlParts(String scriptUrl)
{
String[] urlParts = new String[4];
String path;
String queryString;
int argsIndex = scriptUrl.indexOf("?");
if (argsIndex != -1)
{
path = scriptUrl.substring(0, argsIndex);
queryString = scriptUrl.substring(argsIndex + 1);
}
else
{
path = scriptUrl;
queryString = null;
}
String[] pathSegments = path.split("/");
String pathInfo = "";
for (int i = 3; i < pathSegments.length; i++)
{
pathInfo += "/" + pathSegments[i];
}
urlParts[0] = "/" + pathSegments[1]; // context path
urlParts[1] = "/" + pathSegments[2]; // servlet path
urlParts[2] = pathInfo; // path info
urlParts[3] = queryString; // query string
return urlParts;
}
/**
* Construct
*
* @param req
* @param scriptUrl
* @param serviceMatch
*/
WebScriptPortletRequest(PortletRequest req, String scriptUrl, WebScriptMatch serviceMatch)
{
this(req, getScriptUrlParts(scriptUrl), serviceMatch);
}
/**
* Construct
*
* @param req
* 'param scriptUrlParts
* @param serviceMatch
*/
WebScriptPortletRequest(PortletRequest req, String[] scriptUrlParts, WebScriptMatch serviceMatch)
{
this.req = req;
this.contextPath = scriptUrlParts[0];
this.servletPath = scriptUrlParts[1];
this.pathInfo = scriptUrlParts[2];
this.queryString = scriptUrlParts[3];
this.queryArgs = new HashMap<String, String>();
if (this.queryString != null)
{
String[] args = this.queryString.split("&");
for (String arg : args)
{
String[] parts = arg.split("=");
// TODO: Handle multi-value parameters
this.queryArgs.put(parts[0], parts.length == 2 ? parts[1] : "");
}
}
this.serviceMatch = serviceMatch;
}
/**
* Gets the Portlet Request
*
* @return Portlet Request
*/
public PortletRequest getPortletRequest()
{
return req;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getServiceMatch()
*/
public WebScriptMatch getServiceMatch()
{
return serviceMatch;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getServerPath()
*/
public String getServerPath()
{
return req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getContextPath()
*/
public String getContextPath()
{
return contextPath;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getServiceContextPath()
*/
public String getServiceContextPath()
{
return getContextPath() + servletPath;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getServicePath()
*/
public String getServicePath()
{
return getServiceContextPath() + pathInfo;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getURL()
*/
public String getURL()
{
return getServicePath() + (queryString != null ? "?" + queryString : "");
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getQueryString()
*/
public String getQueryString()
{
return queryString;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getParameterNames()
*/
public String[] getParameterNames()
{
Set<String> keys = queryArgs.keySet();
String[] names = new String[keys.size()];
keys.toArray(names);
return names;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getParameter(java.lang.String)
*/
public String getParameter(String name)
{
return queryArgs.get(name);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getExtensionPath()
*/
public String getExtensionPath()
{
String servicePath = serviceMatch.getPath();
String extensionPath = pathInfo;
int extIdx = extensionPath.indexOf(servicePath);
if (extIdx != -1)
{
int extLength = (servicePath.endsWith("/") ? servicePath.length() : servicePath.length() + 1);
extensionPath = extensionPath.substring(extIdx + extLength);
}
return extensionPath;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#isGuest()
*/
public boolean isGuest()
{
return Boolean.valueOf(queryArgs.get("guest"));
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getFormat()
*/
public String getFormat()
{
String format = queryArgs.get("format");
return (format == null || format.length() == 0) ? "" : format;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getAgent()
*/
public String getAgent()
{
// NOTE: rely on default agent mappings
return null;
}
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (C) 2005-2007 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"
*/
package org.alfresco.web.scripts.portlet;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import javax.portlet.PortletURL;
import javax.portlet.RenderResponse;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptResponse;
/**
* JSR-168 Web Script Response
*
* @author davidc
*/
public class WebScriptPortletResponse implements WebScriptResponse
{
/** Portlet response */
private RenderResponse res;
/**
* Construct
*
* @param res
*/
WebScriptPortletResponse(RenderResponse res)
{
this.res = res;
}
/**
* Gets the Portlet Render Response
*
* @return render response
*/
public RenderResponse getRenderResponse()
{
return res;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#setContentType(java.lang.String)
*/
public void setContentType(String contentType)
{
res.setContentType(contentType);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#getWriter()
*/
public Writer getWriter() throws IOException
{
return res.getWriter();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#getOutputStream()
*/
public OutputStream getOutputStream() throws IOException
{
return res.getPortletOutputStream();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#encodeScriptUrl(java.lang.String)
*/
public String encodeScriptUrl(String url)
{
WebScriptRequest req = new WebScriptPortletRequest(null, url, null);
PortletURL portletUrl = res.createActionURL();
portletUrl.setParameter("scriptUrl", req.getServicePath());
String[] parameterNames = req.getParameterNames();
for (String parameterName : parameterNames)
{
portletUrl.setParameter("arg." + parameterName, req.getParameter(parameterName));
}
return portletUrl.toString();
}
}

View File

@@ -21,4 +21,68 @@
<short-title>alfresco-client-portlet</short-title>
</portlet-info>
</portlet>
<portlet>
<description>My Tasks</description>
<portlet-name>AlfrescoMyTasks</portlet-name>
<portlet-class>org.alfresco.web.scripts.portlet.WebScriptPortlet</portlet-class>
<init-param>
<name>scriptUrl</name>
<value>/alfresco/service/mytasks</value>
</init-param>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>My Tasks</title>
<short-title>My Tasks</short-title>
</portlet-info>
</portlet>
<portlet>
<description>Document List</description>
<portlet-name>AlfrescoDocList</portlet-name>
<portlet-class>org.alfresco.web.scripts.portlet.WebScriptPortlet</portlet-class>
<init-param>
<name>scriptUrl</name>
<value>/alfresco/service/doclist?p=/Company Home/Guest Home</value>
</init-param>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>Document List</title>
<short-title>Document List</short-title>
</portlet-info>
</portlet>
<portlet>
<description>My Web Forms</description>
<portlet-name>AlfrescoMyWebForms</portlet-name>
<portlet-class>org.alfresco.web.scripts.portlet.WebScriptPortlet</portlet-class>
<init-param>
<name>scriptUrl</name>
<value>/alfresco/service/mywebforms</value>
</init-param>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>My Web Forms</title>
<short-title>My Web Forms</short-title>
</portlet-info>
</portlet>
</portlet-app>

View File

@@ -250,6 +250,10 @@
<servlet>
<servlet-name>apiServlet</servlet-name>
<servlet-class>org.alfresco.web.scripts.WebScriptServlet</servlet-class>
<init-param>
<param-name>authenticator</param-name>
<param-value>webscripts.authenticator.webclient</param-value>
</init-param>
</servlet>
<servlet>