Reversed incorrect checkin

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@7438 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2007-11-26 17:17:01 +00:00
parent 82134bf1f0
commit fe7a8e8ca8
120 changed files with 12732 additions and 2228 deletions

View File

@@ -1,250 +0,0 @@
package org.alfresco.repo.web.scripts;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.TemplateService;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.descriptor.DescriptorService;
import org.alfresco.web.scripts.AbstractRuntimeContainer;
import org.alfresco.web.scripts.Authenticator;
import org.alfresco.web.scripts.Description;
import org.alfresco.web.scripts.ServerModel;
import org.alfresco.web.scripts.WebScript;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptResponse;
import org.alfresco.web.scripts.Description.RequiredAuthentication;
import org.alfresco.web.scripts.Description.RequiredTransaction;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class RepositoryContainer extends AbstractRuntimeContainer
{
// Logger
protected static final Log logger = LogFactory.getLog(RepositoryContainer.class);
/** Component Dependencies */
private Repository repository;
private RepositoryImageResolver imageResolver;
private RetryingTransactionHelper retryingTransactionHelper;
private AuthorityService authorityService;
private PermissionService permissionService;
private DescriptorService descriptorService;
public void setRepository(Repository repository)
{
this.repository = repository;
}
public void setRepositoryImageResolver(RepositoryImageResolver imageResolver)
{
this.imageResolver = imageResolver;
}
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
}
public void setTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
{
this.retryingTransactionHelper = retryingTransactionHelper;
}
public void setDescriptorService(DescriptorService descriptorService)
{
this.descriptorService = descriptorService;
}
public void setAuthorityService(AuthorityService authorityService)
{
this.authorityService = authorityService;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.Container#getDescription()
*/
public ServerModel getDescription()
{
return new RepositoryServerModel(descriptorService.getServerDescriptor());
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.AbstractRuntimeContainer#getScriptParameters()
*/
public Map<String, Object> getScriptParameters()
{
Map<String, Object> params = new HashMap<String, Object>();
params.putAll(super.getScriptParameters());
addRepoParameters(params);
return params;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.AbstractRuntimeContainer#getTemplateParameters()
*/
public Map<String, Object> getTemplateParameters()
{
Map<String, Object> params = new HashMap<String, Object>();
params.putAll(super.getTemplateParameters());
params.put(TemplateService.KEY_IMAGE_RESOLVER, imageResolver.getImageResolver());
addRepoParameters(params);
return params;
}
/**
* Add Repository specific parameters
*
* @param params
*/
private void addRepoParameters(Map<String, Object> params)
{
if (AlfrescoTransactionSupport.getTransactionId() != null)
{
NodeRef rootHome = repository.getRootHome();
if (rootHome != null && permissionService.hasPermission(rootHome, PermissionService.READ).equals(AccessStatus.ALLOWED))
{
params.put("roothome", rootHome);
}
NodeRef companyHome = repository.getCompanyHome();
if (companyHome != null && permissionService.hasPermission(companyHome, PermissionService.READ).equals(AccessStatus.ALLOWED))
{
params.put("companyhome", companyHome);
}
NodeRef person = repository.getPerson();
if (person != null && permissionService.hasPermission(companyHome, PermissionService.READ).equals(AccessStatus.ALLOWED))
{
params.put("person", person);
params.put("userhome", repository.getUserHome(person));
}
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.RuntimeContainer#executeScript(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse, org.alfresco.web.scripts.Authenticator)
*/
public void executeScript(WebScriptRequest scriptReq, WebScriptResponse scriptRes, Authenticator auth)
throws IOException
{
WebScript script = scriptReq.getServiceMatch().getWebScript();
Description desc = script.getDescription();
RequiredAuthentication required = desc.getRequiredAuthentication();
boolean isGuest = scriptReq.isGuest();
if (required == RequiredAuthentication.none)
{
AuthenticationUtil.clearCurrentSecurityContext();
transactionedExecute(script, scriptReq, scriptRes);
}
else if ((required == RequiredAuthentication.user || required == RequiredAuthentication.admin) && isGuest)
{
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "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
//
if (auth == null || auth.authenticate(required, isGuest))
{
if (required == RequiredAuthentication.admin && !authorityService.hasAdminAuthority())
{
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires admin authentication; however, a non-admin has attempted access.");
}
// Execute Web Script
transactionedExecute(script, 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 script within required level of transaction
*
* @param scriptReq
* @param scriptRes
* @throws IOException
*/
protected void transactionedExecute(final WebScript script, final WebScriptRequest scriptReq, final WebScriptResponse scriptRes)
throws IOException
{
final Description description = script.getDescription();
if (description.getRequiredTransaction() == RequiredTransaction.none)
{
script.execute(scriptReq, scriptRes);
}
else
{
// encapsulate script within transaction
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
{
public Object execute() throws Exception
{
if (logger.isDebugEnabled())
logger.debug("Begin transaction: " + description.getRequiredTransaction());
script.execute(scriptReq, scriptRes);
if (logger.isDebugEnabled())
logger.debug("End transaction: " + description.getRequiredTransaction());
return null;
}
};
if (description.getRequiredTransaction() == RequiredTransaction.required)
{
retryingTransactionHelper.doInTransaction(work);
}
else
{
retryingTransactionHelper.doInTransaction(work, false, true);
}
}
}
}

View File

@@ -1,50 +0,0 @@
package org.alfresco.repo.web.scripts;
import javax.servlet.ServletContext;
import org.alfresco.service.cmr.repository.FileTypeImageSize;
import org.alfresco.service.cmr.repository.TemplateImageResolver;
import org.alfresco.web.ui.common.Utils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.context.ServletContextAware;
public class RepositoryImageResolver
implements ServletContextAware, InitializingBean
{
private ServletContext servletContext;
private TemplateImageResolver imageResolver;
/* (non-Javadoc)
* @see org.springframework.web.context.ServletContextAware#setServletContext(javax.servlet.ServletContext)
*/
public void setServletContext(ServletContext context)
{
this.servletContext = context;
}
/*(non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet()
throws Exception
{
this.imageResolver = new TemplateImageResolver()
{
public String resolveImagePathForName(String filename, FileTypeImageSize size)
{
return Utils.getFileTypeImage(servletContext, filename, size);
}
};
}
/**
* @return image resolver
*/
public TemplateImageResolver getImageResolver()
{
return this.imageResolver;
}
}

View File

@@ -1,125 +0,0 @@
package org.alfresco.repo.web.scripts;
import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.alfresco.service.cmr.repository.ScriptException;
import org.alfresco.service.cmr.repository.ScriptLocation;
import org.alfresco.service.cmr.repository.ScriptService;
import org.alfresco.web.scripts.MultiScriptLoader;
import org.alfresco.web.scripts.ScriptContent;
import org.alfresco.web.scripts.ScriptLoader;
import org.alfresco.web.scripts.ScriptProcessor;
import org.alfresco.web.scripts.SearchPath;
import org.alfresco.web.scripts.Store;
import org.alfresco.web.scripts.WebScriptException;
import org.springframework.beans.factory.InitializingBean;
public class RepositoryScriptProcessor implements ScriptProcessor, InitializingBean
{
// dependencies
protected ScriptService scriptService;
protected ScriptLoader scriptLoader;
protected SearchPath searchPath;
/**
* Sets the script service
*
* @param scriptService
*/
public void setScriptService(ScriptService scriptService)
{
this.scriptService = scriptService;
}
public void setSearchPath(SearchPath searchPath)
{
this.searchPath = searchPath;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ScriptProcessor#findScript(java.lang.String)
*/
public ScriptContent findScript(String path)
{
return scriptLoader.getScript(path);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ScriptProcessor#executeScript(java.lang.String, java.util.Map)
*/
public Object executeScript(String path, Map<String, Object> model)
throws ScriptException
{
// locate script within web script stores
ScriptContent scriptContent = findScript(path);
if (scriptContent == null)
{
throw new WebScriptException("Unable to locate script " + path);
}
// execute script
return executeScript(scriptContent, model);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ScriptProcessor#executeScript(org.alfresco.web.scripts.ScriptContent, java.util.Map)
*/
public Object executeScript(ScriptContent content, Map<String, Object> model)
{
return scriptService.executeScript("javascript", new RepositoryScriptLocation(content), model);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ScriptProcessor#reset()
*/
public void reset()
{
// NOOP
}
private static class RepositoryScriptLocation implements ScriptLocation
{
private ScriptContent content;
private RepositoryScriptLocation(ScriptContent content)
{
this.content = content;
}
public InputStream getInputStream()
{
return content.getInputStream();
}
public Reader getReader()
{
return content.getReader();
}
}
/**
* Register script loader from each Web Script Store with Script Processor
*/
public void afterPropertiesSet()
{
List<ScriptLoader> loaders = new ArrayList<ScriptLoader>();
for (Store apiStore : searchPath.getStores())
{
ScriptLoader loader = apiStore.getScriptLoader();
if (loader == null)
{
throw new WebScriptException("Unable to retrieve script loader for Web Script store " + apiStore.getBasePath());
}
loaders.add(loader);
}
scriptLoader = new MultiScriptLoader(loaders.toArray(new ScriptLoader[loaders.size()]));
}
}

View File

@@ -1,159 +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.repo.web.scripts;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.web.scripts.TestWebScriptServer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Stand-alone Web Script Test Server
*
* @author davidc
*/
public class TestWebScriptRepoServer extends TestWebScriptServer
{
private RetryingTransactionHelper retryingTransactionHelper;
private AuthenticationService authenticationService;
/**
* Sets helper that provides transaction callbacks
*/
public void setTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
{
this.retryingTransactionHelper = retryingTransactionHelper;
}
/**
* @param authenticationService
*/
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
/**
* Main entry point.
*/
public static void main(String[] args)
{
try
{
TestWebScriptServer testServer = getTestServer();
testServer.rep();
}
catch(Throwable e)
{
StringWriter strWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(strWriter);
e.printStackTrace(printWriter);
System.out.println(strWriter.toString());
}
finally
{
System.exit(0);
}
}
/**
* Retrieve an instance of the TestWebScriptServer
*
* @return Test Server
*/
public static TestWebScriptServer getTestServer()
{
String[] CONFIG_LOCATIONS = new String[]
{
"classpath:alfresco/application-context.xml",
"classpath:alfresco/web-framework-application-context.xml",
"classpath:alfresco/web-scripts-application-context.xml",
"classpath:alfresco/web-client-application-context.xml"
};
ApplicationContext context = new ClassPathXmlApplicationContext(CONFIG_LOCATIONS);
TestWebScriptServer testServer = (TestWebScriptRepoServer)context.getBean("webscripts.test");
return testServer;
}
/**
* Interpret a single command using the BufferedReader passed in for any data needed.
*
* @param line The unparsed command
* @return The textual output of the command.
*/
@Override
protected String interpretCommand(final String line)
throws IOException
{
try
{
if (username.startsWith("TICKET_"))
{
try
{
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Object>()
{
public Object execute() throws Exception
{
authenticationService.validate(username);
return null;
}
});
return executeCommand(line);
}
finally
{
authenticationService.clearCurrentSecurityContext();
}
}
}
catch(AuthenticationException e)
{
executeCommand("user admin");
}
// execute command in context of currently selected user
return AuthenticationUtil.runAs(new RunAsWork<String>()
{
@SuppressWarnings("synthetic-access")
public String doWork() throws Exception
{
return executeCommand(line);
}
}, username);
}
}

View File

@@ -1,143 +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.repo.web.scripts.facebook;
import java.io.IOException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.web.scripts.Authenticator;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.Description.RequiredAuthentication;
import org.alfresco.web.scripts.facebook.FacebookServletRequest;
import org.alfresco.web.scripts.servlet.ServletAuthenticatorFactory;
import org.alfresco.web.scripts.servlet.WebScriptServletRequest;
import org.alfresco.web.scripts.servlet.WebScriptServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class FacebookAuthenticatorFactory implements ServletAuthenticatorFactory
{
// Logger
private static final Log logger = LogFactory.getLog(FacebookAuthenticator.class);
/* (non-Javadoc)
* @see org.alfresco.web.scripts.servlet.ServletAuthenticatorFactory#create(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public Authenticator create(WebScriptServletRequest req, WebScriptServletResponse res)
{
if (!(req instanceof FacebookServletRequest))
{
throw new WebScriptException("Facebook request is required; instead a " + req.getClass().getName() + " has been provided");
}
return new FacebookAuthenticator((FacebookServletRequest)req, res);
}
/**
* Web Script Authenticator that supports Facebook authentication
* mechanism.
*
* Upon success, the request is authenticated as the Facebook User Id.
*
* @author davidc
*/
public class FacebookAuthenticator implements Authenticator
{
// FBML for Facebook login redirect
private static final String LOGIN_REDIRECT = "<fb:redirect url=\"http://www.facebook.com/login.php?api_key=%s&v=1.0%s\">";
// dependencies
private FacebookServletRequest fbReq;
private WebScriptServletResponse fbRes;
/**
* Construct
*
* @param authenticationService
* @param req
* @param res
*/
public FacebookAuthenticator(FacebookServletRequest req, WebScriptServletResponse res)
{
this.fbReq = req;
this.fbRes = res;
}
/* (non-Javadoc)
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
*/
public boolean authenticate(RequiredAuthentication required, boolean isGuest)
{
String sessionKey = fbReq.getSessionKey();
String user = fbReq.getUserId();
if (logger.isDebugEnabled())
{
logger.debug("fb_sig_session_key = '" + sessionKey + "'");
logger.debug("fb_sig_user = '" + user + "'");
}
if ((sessionKey == null || sessionKey.length() == 0) || (user == null || user.length() == 0))
{
// session has not been established, redirect to login
String apiKey = fbReq.getApiKey();
String canvas = (fbReq.isInCanvas()) ? "&canvas" : "";
if (logger.isDebugEnabled())
{
logger.debug("fb_sig_api_key = '" + apiKey + "'");
logger.debug("fb_sig_in_canvas = '" + canvas + "'");
}
try
{
String redirect = String.format(LOGIN_REDIRECT, apiKey, canvas);
if (logger.isDebugEnabled())
logger.debug("Facebook session not established; redirecting via " + redirect);
fbRes.getWriter().write(redirect);
}
catch (IOException e)
{
throw new WebScriptException("Redirect to login failed", e);
}
return false;
}
if (logger.isDebugEnabled())
logger.debug("Facebook session established; authenticating as user " + user);
// session has been established, authenticate as Facebook user id
AuthenticationUtil.setCurrentUser(user);
return true;
}
}
}

View File

@@ -1,134 +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.repo.web.scripts.portlet;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.web.scripts.Authenticator;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.Description.RequiredAuthentication;
import org.alfresco.web.scripts.portlet.PortletAuthenticatorFactory;
import org.alfresco.web.scripts.portlet.WebScriptPortletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class JSR168PortletAuthenticatorFactory implements PortletAuthenticatorFactory
{
// Logger
private static final Log logger = LogFactory.getLog(JSR168PortletAuthenticatorFactory.class);
// dependencies
private AuthenticationService authenticationService;
/**
* @param authenticationService
*/
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.portlet.PortletAuthenticatorFactory#create(javax.portlet.RenderRequest, javax.portlet.RenderResponse)
*/
public Authenticator create(RenderRequest req, RenderResponse res)
{
return new JSR168PortletAuthenticator(req, res);
}
/**
* Portlet authenticator
*
* @author davidc
*/
public class JSR168PortletAuthenticator implements Authenticator
{
// dependencies
private RenderRequest req;
private RenderResponse res;
/**
* Construct
*
* @param authenticationService
* @param req
* @param res
*/
public JSR168PortletAuthenticator(RenderRequest req, RenderResponse res)
{
this.req = req;
this.res = res;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.portlet.WebScriptPortletAuthenticator#authenticate(org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication, boolean, javax.portlet.RenderRequest, javax.portlet.RenderResponse)
*/
public boolean authenticate(RequiredAuthentication required, boolean isGuest)
{
// first look for the username key in the session - we add this by hand for some portals
// when the WebScriptPortletRequest is created
String portalUser = (String)req.getPortletSession().getAttribute(WebScriptPortletRequest.ALFPORTLETUSERNAME);
if (portalUser == null)
{
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());
}
else
{
if (logger.isDebugEnabled())
logger.debug("Authenticating as user " + portalUser);
if (!authenticationService.authenticationExists(portalUser))
{
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "User " + portalUser + " is not a known Alfresco user");
}
AuthenticationUtil.setCurrentUser(portalUser);
}
return true;
}
}
}

View File

@@ -1,198 +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.repo.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.repo.web.scripts.Repository;
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.Authenticator;
import org.alfresco.web.scripts.Description.RequiredAuthentication;
import org.alfresco.web.scripts.portlet.PortletAuthenticatorFactory;
import org.alfresco.web.scripts.portlet.WebScriptPortletRequest;
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 WebClientPortletAuthenticatorFactory implements PortletAuthenticatorFactory
{
// Logger
private static final Log logger = LogFactory.getLog(WebClientPortletAuthenticatorFactory.class);
// dependencies
private AuthenticationService authenticationService;
private Repository repository;
/**
* @param authenticationService
*/
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
/**
* @param scriptContext
*/
public void setRepository(Repository repository)
{
this.repository = repository;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.portlet.PortletAuthenticatorFactory#create(javax.portlet.RenderRequest, javax.portlet.RenderResponse)
*/
public Authenticator create(RenderRequest req, RenderResponse res)
{
return new WebClientPortletAuthenticator(req, res);
}
public class WebClientPortletAuthenticator implements Authenticator
{
// dependencies
private RenderRequest req;
private RenderResponse res;
/**
* Construct
*
* @param authenticationService
* @param req
* @param res
*/
public WebClientPortletAuthenticator(RenderRequest req, RenderResponse res)
{
this.req = req;
this.res = res;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.Authenticator#authenticate(org.alfresco.web.scripts.Description.RequiredAuthentication, boolean)
*/
public boolean authenticate(RequiredAuthentication required, boolean isGuest)
{
PortletSession session = req.getPortletSession();
// first look for the username key in the session - we add this by hand for some portals
// when the WebScriptPortletRequest is created
String portalUser = (String)req.getPortletSession().getAttribute(WebScriptPortletRequest.ALFPORTLETUSERNAME);
if (portalUser == null)
{
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);
}
}
return true;
}
/**
* 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 = repository.getPerson();
User user = new User(authenticationService.getCurrentUserName(), authenticationService.getCurrentTicket(), personRef);
NodeRef homeRef = repository.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

@@ -1,33 +0,0 @@
package org.alfresco.repo.web.scripts.portlet;
import java.io.IOException;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import javax.portlet.PortletSecurityException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import org.alfresco.web.app.Application;
import org.alfresco.web.scripts.portlet.WebScriptPortlet;
public class WebScriptRepoPortlet extends WebScriptPortlet
{
@Override
public void processAction(ActionRequest req, ActionResponse res) throws PortletException, PortletSecurityException, IOException
{
Application.setInPortalServer(true);
super.processAction(req, res);
}
@Override
public void render(RenderRequest req, RenderResponse res) throws PortletException, PortletSecurityException, IOException
{
Application.setInPortalServer(true);
super.render(req, res);
}
}

View File

@@ -1,204 +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.repo.web.scripts.servlet;
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.Authenticator;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.Description.RequiredAuthentication;
import org.alfresco.web.scripts.servlet.ServletAuthenticatorFactory;
import org.alfresco.web.scripts.servlet.WebScriptServletRequest;
import org.alfresco.web.scripts.servlet.WebScriptServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class BasicHttpAuthenticatorFactory implements ServletAuthenticatorFactory
{
// Logger
private static Log logger = LogFactory.getLog(BasicHttpAuthenticator.class);
// Component dependencies
private AuthenticationService authenticationService;
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
public Authenticator create(WebScriptServletRequest req, WebScriptServletResponse res)
{
return new BasicHttpAuthenticator(req, res);
}
/**
* HTTP Basic Authentication
*
* @author davidc
*/
public class BasicHttpAuthenticator implements Authenticator
{
// dependencies
private WebScriptServletRequest servletReq;
private WebScriptServletResponse servletRes;
/**
* Construct
*
* @param authenticationService
* @param req
* @param res
*/
public BasicHttpAuthenticator(WebScriptServletRequest req, WebScriptServletResponse res)
{
this.servletReq = req;
this.servletRes = res;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.Authenticator#authenticate(org.alfresco.web.scripts.Description.RequiredAuthentication, boolean)
*/
public boolean authenticate(RequiredAuthentication required, boolean isGuest)
{
boolean authorized = false;
//
// validate credentials
//
HttpServletRequest req = servletReq.getHttpServletRequest();
HttpServletResponse res = servletRes.getHttpServletResponse();
String authorization = req.getHeader("Authorization");
String ticket = req.getParameter("alf_ticket");
if (logger.isDebugEnabled())
{
logger.debug("HTTP Authorization provided: " + (authorization != null && authorization.length() > 0));
logger.debug("URL ticket provided: " + (ticket != null && ticket.length() > 0));
}
// authenticate as guest, if service allows
if (isGuest && RequiredAuthentication.guest == required)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating as Guest");
authenticationService.authenticateAsGuest();
authorized = true;
}
// authenticate as specified by explicit ticket on url
else if (ticket != null && ticket.length() > 0)
{
try
{
if (logger.isDebugEnabled())
logger.debug("Authenticating (URL argument) ticket " + ticket);
// assume a ticket has been passed
authenticationService.validate(ticket);
authorized = true;
}
catch(AuthenticationException e)
{
// failed authentication
}
}
// 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 (BASIC HTTP) ticket " + parts[0]);
// assume a ticket has been passed
authenticationService.validate(parts[0]);
authorized = true;
}
else
{
if (logger.isDebugEnabled())
logger.debug("Authenticating (BASIC HTTP) 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\"");
}
return authorized;
}
}
}

View File

@@ -1,164 +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.repo.web.scripts.servlet;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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.Authenticator;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.Description.RequiredAuthentication;
import org.alfresco.web.scripts.servlet.ServletAuthenticatorFactory;
import org.alfresco.web.scripts.servlet.WebScriptServletRequest;
import org.alfresco.web.scripts.servlet.WebScriptServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.ServletContextAware;
public class WebClientAuthenticatorFactory implements ServletAuthenticatorFactory, ServletContextAware
{
// Logger
private static final Log logger = LogFactory.getLog(WebClientAuthenticator.class);
// dependencies
private ServletContext context;
/* (non-Javadoc)
* @see org.springframework.web.context.ServletContextAware#setServletContext(javax.servlet.ServletContext)
*/
public void setServletContext(ServletContext context)
{
this.context = context;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.servlet.ServletAuthenticatorFactory#create(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public Authenticator create(WebScriptServletRequest req, WebScriptServletResponse res)
{
return new WebClientAuthenticator(req, res);
}
/**
* Alfresco Web Client Authentication
*
* @author davidc
*/
public class WebClientAuthenticator implements Authenticator
{
// dependencies
private WebScriptServletRequest servletReq;
private WebScriptServletResponse servletRes;
/**
* Construct
*
* @param authenticationService
* @param req
* @param res
*/
public WebClientAuthenticator(WebScriptServletRequest req, WebScriptServletResponse res)
{
this.servletReq = req;
this.servletRes = res;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptServletAuthenticator#authenticate(org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication, boolean, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public boolean authenticate(RequiredAuthentication required, boolean isGuest)
{
AuthenticationStatus status = null;
try
{
//
// validate credentials
//
HttpServletRequest req = servletReq.getHttpServletRequest();
HttpServletResponse res = servletRes.getHttpServletResponse();
String ticket = req.getParameter("ticket");
if (logger.isDebugEnabled())
{
logger.debug("Alfresco ticket provided: " + (ticket != null && ticket.length() > 0));
}
if (ticket != null && ticket.length() > 0)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating ticket " + ticket);
status = AuthenticationHelper.authenticate(context, req, res, ticket);
}
else
{
if (isGuest && RequiredAuthentication.guest == required)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating as Guest");
status = AuthenticationHelper.authenticate(context, req, res, true);
}
else
{
if (logger.isDebugEnabled())
logger.debug("Authenticating session");
status = AuthenticationHelper.authenticate(context, req, res, false, false);
}
}
//
// if not authorized, redirect to login page
//
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(req, res, context);
}
}
catch(IOException e)
{
throw new WebScriptException("Failed to authenticate", e);
}
return !(status == null || status == AuthenticationStatus.Failure);
}
}
}

View File

@@ -38,6 +38,7 @@ import javax.transaction.UserTransaction;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.template.AbsoluteUrlMethod;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.FileTypeImageSize;
import org.alfresco.service.cmr.repository.NodeRef;

View File

@@ -51,23 +51,22 @@ import org.alfresco.config.ConfigService;
import org.alfresco.config.JNDIConstants;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.repo.template.ClassPathRepoTemplateLoader;
import org.alfresco.service.cmr.avm.AVMNotFoundException;
import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.util.URLEncoder;
import org.alfresco.web.scripts.Cache;
import org.alfresco.web.scripts.Runtime;
import org.alfresco.web.scripts.AbstractRuntime;
import org.alfresco.web.scripts.Authenticator;
import org.alfresco.web.scripts.Match;
import org.alfresco.web.scripts.WebScriptCache;
import org.alfresco.web.scripts.WebScriptMatch;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptRequestURLImpl;
import org.alfresco.web.scripts.WebScriptResponse;
import org.alfresco.web.scripts.WebScriptResponseImpl;
import org.alfresco.web.scripts.Description.RequiredAuthentication;
import org.alfresco.web.scripts.servlet.WebScriptServlet;
import org.alfresco.web.scripts.WebScriptRuntime;
import org.alfresco.web.scripts.WebScriptServlet;
import org.alfresco.web.scripts.WebScriptServletRequest;
import org.alfresco.web.scripts.WebScriptServletResponse;
import org.alfresco.web.scripts.WebScriptURLRequest;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
@@ -78,6 +77,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
/**
@@ -109,7 +109,6 @@ public class PageRendererServlet extends WebScriptServlet
// timeout to reload default page cache from
private static final int DEFAULT_PAGE_CONFIG_CACHE_TIMEOUT = 30000;
private ServiceRegistry serviceRegistry;
private PageTemplateProcessor templateProcessor;
private WebScriptTemplateLoader webscriptTemplateLoader;
private Map<String, ExpiringValueCache<PageDefinition>> defaultPageDefMap = null;
@@ -121,18 +120,15 @@ public class PageRendererServlet extends WebScriptServlet
// init beans
ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
serviceRegistry = (ServiceRegistry)context.getBean("serviceRegistry");
templateProcessor = (PageTemplateProcessor)context.getBean("pagerenderer.templateprocessor");
webscriptTemplateLoader = new WebScriptTemplateLoader();
// TODO: Refactor to use web script stores
// ClassPathRepoTemplateLoader repoLoader = new ClassPathRepoTemplateLoader(
// serviceRegistry.getNodeService(),
// serviceRegistry.getContentService(),
// templateProcessor.getDefaultEncoding());
// templateProcessor.setTemplateLoader(new MultiTemplateLoader(new TemplateLoader[]{
// webscriptTemplateLoader, repoLoader}));
// templateProcessor.initConfig();
ClassPathRepoTemplateLoader repoLoader = new ClassPathRepoTemplateLoader(
serviceRegistry.getNodeService(),
serviceRegistry.getContentService(),
templateProcessor.getDefaultEncoding());
templateProcessor.setTemplateLoader(new MultiTemplateLoader(new TemplateLoader[]{
webscriptTemplateLoader, repoLoader}));
templateProcessor.initConfig();
// we use a specific config service instance
configService = (ConfigService)context.getBean("pagerenderer.config");
@@ -476,7 +472,7 @@ public class PageRendererServlet extends WebScriptServlet
/**
* WebScript runtime for the PageRenderer servlet.
*/
private class PageRendererWebScriptRuntime extends AbstractRuntime
private class PageRendererWebScriptRuntime extends WebScriptRuntime
{
private PageComponent component;
private PageRendererContext context;
@@ -488,7 +484,7 @@ public class PageRendererServlet extends WebScriptServlet
PageRendererWebScriptRuntime(
PageComponent component, PageRendererContext context, String webScript, String executeUrl, String encoding)
{
super(PageRendererServlet.this.container);
super(registry, serviceRegistry);
this.component = component;
this.context = context;
this.webScript = webScript;
@@ -498,14 +494,6 @@ public class PageRendererServlet extends WebScriptServlet
logger.debug("Constructing runtime for url: " + executeUrl);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.Runtime#getName()
*/
public String getName()
{
return "Page Renderer";
}
@Override
protected String getScriptUrl()
{
@@ -513,7 +501,7 @@ public class PageRendererServlet extends WebScriptServlet
}
@Override
protected WebScriptRequest createRequest(Match match)
protected WebScriptRequest createRequest(WebScriptMatch match)
{
// set the component properties as the additional request attributes
Map<String, String> attributes = new HashMap<String, String>();
@@ -521,7 +509,7 @@ public class PageRendererServlet extends WebScriptServlet
// add the "well known" attributes - such as avm store
attributes.put("store", this.context.AVMStore);
attributes.put("theme", this.context.Theme);
return new WebScriptPageRendererRequest(this, scriptUrl, match, attributes);
return new WebScriptPageRendererRequest(scriptUrl, match, attributes);
}
@Override
@@ -534,7 +522,7 @@ public class PageRendererServlet extends WebScriptServlet
this.baOut = new ByteArrayOutputStream(4096);
BufferedWriter wrOut = new BufferedWriter(
encoding == null ? new OutputStreamWriter(baOut) : new OutputStreamWriter(baOut, encoding));
return new WebScriptPageRendererResponse(this, context, component.Id, wrOut, baOut);
return new WebScriptPageRendererResponse(context, component.Id, wrOut, baOut);
}
catch (UnsupportedEncodingException err)
{
@@ -542,6 +530,13 @@ public class PageRendererServlet extends WebScriptServlet
}
}
@Override
protected boolean authenticate(RequiredAuthentication required, boolean isGuest, WebScriptRequest req, WebScriptResponse res)
{
// TODO: what authentication here?
return true;
}
@Override
protected String getScriptMethod()
{
@@ -568,32 +563,21 @@ public class PageRendererServlet extends WebScriptServlet
throw new AlfrescoRuntimeException("Unsupported encoding.", err);
}
}
@Override
protected Authenticator createAuthenticator()
{
return null;
}
}
/**
* Simple implementation of a WebScript URL Request for a webscript on the page
*/
private class WebScriptPageRendererRequest extends WebScriptRequestURLImpl
private class WebScriptPageRendererRequest extends WebScriptURLRequest
{
private Map<String, String> attributes;
WebScriptPageRendererRequest(Runtime runtime, String scriptUrl, Match match, Map<String, String> attributes)
WebScriptPageRendererRequest(String scriptUrl, WebScriptMatch match, Map<String, String> attributes)
{
super(runtime, scriptUrl, match);
super(scriptUrl, match);
this.attributes = attributes;
}
//
// TODO: Refactor attribute methods - implement getScriptParameters and getTemplateParameters instead
//
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getAttribute(java.lang.String)
*/
@@ -632,7 +616,7 @@ public class PageRendererServlet extends WebScriptServlet
/**
* Implementation of a WebScript Response object for PageRenderer servlet
*/
private class WebScriptPageRendererResponse extends WebScriptResponseImpl
private class WebScriptPageRendererResponse implements WebScriptResponse
{
private Writer outWriter;
private OutputStream outStream;
@@ -640,9 +624,8 @@ public class PageRendererServlet extends WebScriptServlet
private String componentId;
public WebScriptPageRendererResponse(
Runtime runtime, PageRendererContext context, String componentId, Writer outWriter, OutputStream outStream)
PageRendererContext context, String componentId, Writer outWriter, OutputStream outStream)
{
super(runtime);
this.context = context;
this.componentId = componentId;
this.outWriter = outWriter;
@@ -678,7 +661,7 @@ public class PageRendererServlet extends WebScriptServlet
// not supported
}
public void setCache(Cache cache)
public void setCache(WebScriptCache cache)
{
// not supported
}

View File

@@ -24,8 +24,7 @@
*/
package org.alfresco.web.app.servlet;
import org.alfresco.web.scripts.PresentationTemplateProcessor;
import org.alfresco.web.scripts.TemplateProcessor;
/**
* Extension to the webscripts TemplateProcessor class to allow the default encoding
@@ -33,7 +32,19 @@ import org.alfresco.web.scripts.PresentationTemplateProcessor;
*
* @author Kevin Roast
*/
public class PageTemplateProcessor extends PresentationTemplateProcessor
public class PageTemplateProcessor extends TemplateProcessor
{
public String getDefaultEncoding()
{
return this.defaultEncoding;
}
}
/**
* Initialise FreeMarker Configuration
*/
public void initConfig()
{
super.initConfig();
templateConfig.setTemplateUpdateDelay(0);
}
}

View File

@@ -26,14 +26,17 @@ package org.alfresco.web.bean.ajax;
import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.alfresco.repo.template.AbsoluteUrlMethod;
import org.alfresco.repo.template.CropContentMethod;
import org.alfresco.repo.template.TemplateNode;
import org.alfresco.repo.template.UrlEncodeMethod;
import org.alfresco.service.cmr.repository.FileTypeImageSize;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;

View File

@@ -32,14 +32,22 @@ import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.alfresco.repo.template.AbsoluteUrlMethod;
import org.alfresco.repo.template.CropContentMethod;
import org.alfresco.repo.template.TemplateNode;
import org.alfresco.repo.template.UrlEncodeMethod;
import org.alfresco.repo.template.Workflow;
import org.alfresco.service.cmr.repository.FileTypeImageSize;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.TemplateImageResolver;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.web.app.servlet.BaseTemplateContentServlet;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.Utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean used by an AJAX control to send information back on the requested workflow task.

View File

@@ -0,0 +1,133 @@
/*
* 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.config;
import java.util.List;
import org.alfresco.config.ConfigElement;
import org.alfresco.config.ConfigException;
import org.alfresco.config.element.ConfigElementAdapter;
/**
* @author David Caruana
*/
public class ServerConfigElement extends ConfigElementAdapter
{
public static final String CONFIG_ELEMENT_ID = "server";
private String scheme = null;
private String hostname = null;
private Integer port = null;
/**
* Default constructor
*/
public ServerConfigElement()
{
super(CONFIG_ELEMENT_ID);
}
/**
* Constructor
*
* @param name Name of the element this config element represents
*/
public ServerConfigElement(String name)
{
super(name);
}
/**
* @see org.alfresco.config.element.ConfigElementAdapter#getChildren()
*/
public List<ConfigElement> getChildren()
{
throw new ConfigException("Reading the Server config via the generic interfaces is not supported");
}
/**
* @see org.alfresco.config.element.ConfigElementAdapter#combine(org.alfresco.config.ConfigElement)
*/
public ConfigElement combine(ConfigElement configElement)
{
ServerConfigElement newElement = (ServerConfigElement)configElement;
ServerConfigElement combinedElement = new ServerConfigElement();
combinedElement.setScheme(newElement.getScheme());
combinedElement.setHostName(newElement.getHostName());
combinedElement.setPort(newElement.getPort());
return combinedElement;
}
/**
* @return server scheme
*/
public String getScheme()
{
return scheme;
}
/**
* @param scheme
*/
public void setScheme(String scheme)
{
this.scheme = scheme;
}
/**
* @return server hostname
*/
public String getHostName()
{
return hostname;
}
/**
* @param hostname
*/
public void setHostName(String hostname)
{
this.hostname = hostname;
}
/**
* @return server port
*/
public Integer getPort()
{
return port;
}
/**
* @param port
*/
public void setPort(Integer port)
{
this.port = port;
}
}

View File

@@ -0,0 +1,83 @@
/*
* 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.config;
import org.alfresco.config.ConfigElement;
import org.alfresco.config.ConfigException;
import org.alfresco.config.xml.elementreader.ConfigElementReader;
import org.dom4j.Element;
/**
* @author David Caruana
*/
public class ServerElementReader implements ConfigElementReader
{
public static final String ELEMENT_SCHEME = "scheme";
public static final String ELEMENT_HOSTNAME = "hostname";
public static final String ELEMENT_PORT = "port";
/**
* @see org.alfresco.config.xml.elementreader.ConfigElementReader#parse(org.dom4j.Element)
*/
@SuppressWarnings("unchecked")
public ConfigElement parse(Element element)
{
ServerConfigElement configElement = new ServerConfigElement();
if (element != null)
{
if (ServerConfigElement.CONFIG_ELEMENT_ID.equals(element.getName()) == false)
{
throw new ConfigException("ServerElementReader can only parse config elements of type '" + ServerConfigElement.CONFIG_ELEMENT_ID + "'");
}
Element schemeElem = element.element(ELEMENT_SCHEME);
if (schemeElem != null)
{
configElement.setScheme(schemeElem.getTextTrim());
}
Element hostnameElem = element.element(ELEMENT_HOSTNAME);
if (hostnameElem != null)
{
configElement.setHostName(hostnameElem.getTextTrim());
}
Element portElem = element.element(ELEMENT_PORT);
if (portElem != null)
{
try
{
Integer port = new Integer(portElem.getTextTrim());
configElement.setPort(port);
}
catch(NumberFormatException e)
{
throw new ConfigException("Server port is not a number", e);
}
}
}
return configElement;
}
}

View File

@@ -0,0 +1,721 @@
/*
* 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.Writer;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.jscript.ScriptableHashMap;
import org.alfresco.repo.template.AbsoluteUrlMethod;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.ScriptLocation;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.TemplateService;
import org.alfresco.service.descriptor.DescriptorService;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
import org.alfresco.web.scripts.WebScriptDescription.RequiredTransaction;
import org.alfresco.web.scripts.facebook.FacebookModel;
import org.alfresco.web.scripts.facebook.FacebookServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Skeleton implementation of a Web Script
*
* @author davidc
*/
public abstract class AbstractWebScript implements WebScript
{
// Logger
private static final Log logger = LogFactory.getLog(AbstractWebScript.class);
// dependencies
private WebScriptContext scriptContext;
private WebScriptRegistry scriptRegistry;
private WebScriptDescription description;
private ServiceRegistry serviceRegistry;
private DescriptorService descriptorService;
// Status Template cache
private Map<String, StatusTemplate> statusTemplates = new HashMap<String, StatusTemplate>();
private ReentrantReadWriteLock statusTemplateLock = new ReentrantReadWriteLock();
//
// Initialisation
//
/**
* @param scriptContext
*/
final public void setScriptContext(WebScriptContext scriptContext)
{
this.scriptContext = scriptContext;
}
/**
* @param serviceRegistry
*/
final public void setServiceRegistry(ServiceRegistry serviceRegistry)
{
this.serviceRegistry = serviceRegistry;
}
/**
* @param descriptorService
*/
final public void setDescriptorService(DescriptorService descriptorService)
{
this.descriptorService = descriptorService;
}
/**
* Sets the Service Description
*
* @param description
*/
final public void setDescription(WebScriptDescription description)
{
this.description = description;
}
/**
* Initialise Web Script
*
* @param scriptRegistry
*/
public void init(WebScriptRegistry scriptRegistry)
{
this.scriptRegistry = scriptRegistry;
this.statusTemplateLock.writeLock().lock();
try
{
this.statusTemplates.clear();
}
finally
{
this.statusTemplateLock.writeLock().unlock();
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScript#getDescription()
*/
final public WebScriptDescription getDescription()
{
return this.description;
}
//
// Service Implementation Helpers
//
/**
* Gets the Repository Context
*
* @return repository context
*/
final public WebScriptContext getRepositoryContext()
{
return this.scriptContext;
}
/**
* Gets the Web Script Registry
*
* @return Web Script Registry
*/
final public WebScriptRegistry getWebScriptRegistry()
{
return this.scriptRegistry;
}
/**
* Gets the Alfresco Service Registry
*
* @return service registry
*/
final public ServiceRegistry getServiceRegistry()
{
return this.serviceRegistry;
}
/**
* Gets the Alfresco Descriptor
*
* @return descriptor
*/
final public DescriptorService getDescriptorService()
{
return this.descriptorService;
}
//
// Scripting Support
//
/**
* Create a map of arguments from Web Script Request (for scripting)
*
* @param req Web Script Request
* @return argument map
*/
final protected Map<String, String> createScriptArgs(WebScriptRequest req)
{
Map<String, String> args = new ScriptableHashMap<String, String>();
String[] names = req.getParameterNames();
for (String name : names)
{
args.put(name, req.getParameter(name));
}
return args;
}
/**
* Create a map of arguments from Web Script Request (for templating)
*
* @param req Web Script Request
* @return argument map
*/
final protected Map<String, String> createTemplateArgs(WebScriptRequest req)
{
Map<String, String> args = new HashMap<String, String>();
String[] names = req.getParameterNames();
for (String name : names)
{
args.put(name, req.getParameter(name));
}
return args;
}
/**
* Create a map of (array) arguments from Web Script Request (for scripting)
*
* @param req Web Script Request
* @return argument map
*/
final protected Map<String, Map<String, String>> createScriptArgsM(WebScriptRequest req)
{
Map<String, Map<String, String>> args = new ScriptableHashMap<String, Map<String, String>>();
String[] names = req.getParameterNames();
for (String name : names)
{
ScriptableHashMap<String, String> values = new ScriptableHashMap<String, String>();
int i = 0;
for (String value : req.getParameterValues(name))
{
values.put(new Integer(i++).toString(), value);
}
args.put(name, values);
}
return args;
}
/**
* Create a map of (array) arguments from Web Script Request (for scripting)
*
* @param req Web Script Request
* @return argument map
*/
final protected Map<String, String[]> createTemplateArgsM(WebScriptRequest req)
{
Map<String, String[]> args = new HashMap<String, String[]>();
String[] names = req.getParameterNames();
for (String name : names)
{
args.put(name, req.getParameterValues(name));
}
return args;
}
/**
* Create a model for script usage
*
* @param req web script request
* @param res web script response
* @param customModel custom model entries
*
* @return script model
*/
final protected Map<String, Object> createScriptModel(WebScriptRequest req, WebScriptResponse res, Map<String, Object> customModel)
{
// create script model
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
// add repository context (only if authenticated and transaction enabled)
if (getDescription().getRequiredAuthentication() != RequiredAuthentication.none &&
getDescription().getRequiredTransaction() != RequiredTransaction.none)
{
NodeRef rootHome = scriptContext.getRootHome();
if (rootHome != null)
{
model.put("roothome", rootHome);
}
NodeRef companyHome = scriptContext.getCompanyHome();
if (companyHome != null)
{
model.put("companyhome", companyHome);
}
NodeRef person = scriptContext.getPerson();
if (person != null)
{
model.put("person", person);
model.put("userhome", scriptContext.getUserHome(person));
}
}
// add web script context
model.put("args", createScriptArgs(req));
model.put("argsM", createScriptArgsM(req));
model.put("guest", req.isGuest());
model.put("url", new URLModel(req));
model.put("server", new ServerModel(descriptorService.getServerDescriptor()));
// TODO: Refactor creation of runtime specific parameters with
// Web Script F/W extraction
if (req instanceof WebScriptServletRequest)
{
model.put("formdata", ((WebScriptServletRequest)req).getFormData());
}
if (req instanceof FacebookServletRequest)
{
model.put("facebook", new FacebookModel(((FacebookServletRequest)req)));
}
// add custom model
if (customModel != null)
{
model.putAll(customModel);
}
// return model
return model;
}
/**
* Create a model for template usage
*
* @param req web script request
* @param res web script response
* @param customModel custom model entries
*
* @return template model
*/
final protected Map<String, Object> createTemplateModel(WebScriptRequest req, WebScriptResponse res, Map<String, Object> customModel)
{
// create template model
Map<String, Object> model = new HashMap<String, Object>(8, 1.0f);
// add repository context
if (getDescription().getRequiredAuthentication() != RequiredAuthentication.none &&
getDescription().getRequiredTransaction() != RequiredTransaction.none)
{
NodeRef rootHome = scriptContext.getRootHome();
if (rootHome != null)
{
model.put("roothome", rootHome);
}
NodeRef companyHome = scriptContext.getCompanyHome();
if (companyHome != null)
{
model.put("companyhome", companyHome);
}
NodeRef person = scriptContext.getPerson();
if (person != null)
{
model.put("person", person);
model.put("userhome", scriptContext.getUserHome(person));
}
}
// add web script context
model.put("args", createTemplateArgs(req));
model.put("argsM", createTemplateArgsM(req));
model.put("guest", req.isGuest());
model.put("url", new URLModel(req));
model.put("webscript", getDescription());
model.put("server", new ServerModel(descriptorService.getServerDescriptor()));
// TODO: Refactor creation of runtime specific parameters with
// Web Script F/W extraction
if (req instanceof FacebookServletRequest)
{
model.put("facebook", new FacebookModel(((FacebookServletRequest)req)));
}
// add template support
model.put("absurl", new AbsoluteUrlMethod(req.getServerPath()));
model.put("scripturl", new ScriptUrlMethod(req, res));
model.put("clienturlfunction", new ClientUrlFunctionMethod(res));
model.put("date", new Date());
model.put(TemplateService.KEY_IMAGE_RESOLVER, getWebScriptRegistry().getTemplateImageResolver());
// add custom model
if (customModel != null)
{
model.putAll(customModel);
}
return model;
}
/**
* Render a template (identified by path)
*
* @param templatePath template path
* @param model model
* @param writer output writer
*/
final protected void renderTemplate(String templatePath, Map<String, Object> model, Writer writer)
{
long start = System.currentTimeMillis();
getWebScriptRegistry().getTemplateProcessor().process(templatePath, model, writer);
if (logger.isDebugEnabled())
logger.debug("Rendered template " + templatePath + " in " + (System.currentTimeMillis() - start) + "ms");
}
/**
* Render a template (contents as string)
* @param template the template
* @param model model
* @param writer output writer
*/
final protected void renderString(String template, Map<String, Object> model, Writer writer)
{
getWebScriptRegistry().getTemplateProcessor().processString(template, model, writer);
}
/**
* Render an explicit response status template
*
* @param req web script request
* @param res web script response
* @param status web script status
* @param format format
* @param model model
* @throws IOException
*/
final protected void sendStatus(WebScriptRequest req, WebScriptResponse res, WebScriptStatus status, WebScriptCache cache, String format, Map<String, Object> model)
throws IOException
{
// locate status template
// NOTE: search order...
// NOTE: package path is recursed to root package
// 1) script located <scriptid>.<format>.<status>.ftl
// 2) script located <scriptid>.<format>.status.ftl
// 3) package located <scriptpath>/<format>.<status>.ftl
// 4) package located <scriptpath>/<format>.status.ftl
// 5) default <status>.ftl
// 6) default status.ftl
int statusCode = status.getCode();
String statusFormat = (format == null) ? "" : format;
String scriptId = getDescription().getId();
StatusTemplate template = getStatusTemplate(scriptId, statusCode, statusFormat);
// render output
String mimetype = getWebScriptRegistry().getFormatRegistry().getMimeType(req.getAgent(), template.format);
if (mimetype == null)
{
throw new WebScriptException("Web Script format '" + template.format + "' is not registered");
}
if (logger.isDebugEnabled())
{
logger.debug("Force success status header in response: " + req.forceSuccessStatus());
logger.debug("Sending status " + statusCode + " (Template: " + template.path + ")");
logger.debug("Rendering response: content type=" + mimetype);
}
res.reset();
res.setCache(cache);
res.setStatus(req.forceSuccessStatus() ? HttpServletResponse.SC_OK : statusCode);
res.setContentType(mimetype + ";charset=UTF-8");
renderTemplate(template.path, model, res.getWriter());
}
/**
* Find status template
*
* Note: This method caches template search results
*
* @param scriptId
* @param statusCode
* @param format
* @return status template (or null if not found)
*/
private StatusTemplate getStatusTemplate(String scriptId, int statusCode, String format)
{
StatusTemplate statusTemplate = null;
statusTemplateLock.readLock().lock();
try
{
String key = statusCode + "." + format;
statusTemplate = statusTemplates.get(key);
if (statusTemplate == null)
{
// Upgrade read lock to write lock
statusTemplateLock.readLock().unlock();
statusTemplateLock.writeLock().lock();
try
{
// Check again
statusTemplate = statusTemplates.get(key);
if (statusTemplate == null)
{
// Locate template in web script store
statusTemplate = getScriptStatusTemplate(scriptId, statusCode, format);
if (statusTemplate == null)
{
WebScriptPath path = getWebScriptRegistry().getPackage(Path.concatPath("/", getDescription().getScriptPath()));
statusTemplate = getPackageStatusTemplate(path, statusCode, format);
if (statusTemplate == null)
{
statusTemplate = getDefaultStatusTemplate(statusCode);
}
}
if (logger.isDebugEnabled())
logger.debug("Caching template " + statusTemplate.path + " for web script " + scriptId + " and status " + statusCode + " (format: " + format + ")");
statusTemplates.put(key, statusTemplate);
}
}
finally
{
// Downgrade lock to read
statusTemplateLock.readLock().lock();
statusTemplateLock.writeLock().unlock();
}
}
return statusTemplate;
}
finally
{
statusTemplateLock.readLock().unlock();
}
}
/**
* Find a script specific status template
*
* @param scriptId
* @param statusCode
* @param format
* @return status template (or null, if not found)
*/
private StatusTemplate getScriptStatusTemplate(String scriptId, int statusCode, String format)
{
String path = scriptId + "." + format + "." + statusCode + ".ftl";
if (getWebScriptRegistry().getTemplateProcessor().hasTemplate(path))
{
return new StatusTemplate(path, format);
}
path = scriptId + "." + format + ".status.ftl";
if (getWebScriptRegistry().getTemplateProcessor().hasTemplate(path))
{
return new StatusTemplate(path, format);
}
return null;
}
/**
* Find a package specific status template
*
* @param scriptPath
* @param statusCode
* @param format
* @return status template (or null, if not found)
*/
private StatusTemplate getPackageStatusTemplate(WebScriptPath scriptPath, int statusCode, String format)
{
while(scriptPath != null)
{
String path = Path.concatPath(scriptPath.getPath(), format + "." + statusCode + ".ftl");
if (getWebScriptRegistry().getTemplateProcessor().hasTemplate(path))
{
return new StatusTemplate(path, format);
}
path = Path.concatPath(scriptPath.getPath(), format + ".status.ftl");
if (getWebScriptRegistry().getTemplateProcessor().hasTemplate(path))
{
return new StatusTemplate(path, format);
}
scriptPath = scriptPath.getParent();
}
return null;
}
/**
* Find default status template
*
* @param statusCode
* @return status template
*/
private StatusTemplate getDefaultStatusTemplate(int statusCode)
{
String path = statusCode + ".ftl";
if (getWebScriptRegistry().getTemplateProcessor().hasTemplate(path))
{
return new StatusTemplate(path, WebScriptResponse.HTML_FORMAT);
}
path = "status.ftl";
if (getWebScriptRegistry().getTemplateProcessor().hasTemplate(path))
{
return new StatusTemplate(path, WebScriptResponse.HTML_FORMAT);
}
throw new WebScriptException("Default status template /status.ftl could not be found");
}
/**
* Execute a script
*
* @param location script location
* @param model model
*/
final protected void executeScript(ScriptLocation location, Map<String, Object> model)
{
long start = System.currentTimeMillis();
getWebScriptRegistry().getScriptProcessor().executeScript(location, model);
if (logger.isDebugEnabled())
logger.debug("Executed script " + location.toString() + " in " + (System.currentTimeMillis() - start) + "ms");
}
/**
* Helper to convert a Web Script Request URL to a Node Ref
*
* 1) Node - {store_type}/{store_id}/{node_id}
*
* Resolve to node via its Node Reference.
*
* 2) Path - {store_type}/{store_id}/{path}
*
* Resolve to node via its display path.
*
* 3) QName - {store_type}/{store_id}/{child_qname_path} TODO: Implement
*
* Resolve to node via its child qname path.
*
* @param referenceType one of node, path or qname
* @return reference array of reference segments (as described above for each reference type)
*/
protected NodeRef findNodeRef(String referenceType, String[] reference)
{
NodeRef nodeRef = null;
// construct store reference
if (reference.length < 3)
{
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Reference " + Arrays.toString(reference) + " is not properly formed");
}
StoreRef storeRef = new StoreRef(reference[0], reference[1]);
NodeService nodeService = serviceRegistry.getNodeService();
if (nodeService.exists(storeRef))
{
if (referenceType.equals("node"))
{
NodeRef urlRef = new NodeRef(storeRef, reference[2]);
if (nodeService.exists(urlRef))
{
nodeRef = urlRef;
}
}
else if (referenceType.equals("path"))
{
// TODO: Allow a root path to be specified - for now, hard-code to Company Home
// NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
NodeRef rootNodeRef = getRepositoryContext().getCompanyHome();
if (reference.length == 3)
{
nodeRef = rootNodeRef;
}
else
{
String[] path = new String[reference.length - /*2*/3];
System.arraycopy(reference, /*2*/3, path, 0, path.length);
try
{
FileFolderService ffService = serviceRegistry.getFileFolderService();
FileInfo fileInfo = ffService.resolveNamePath(rootNodeRef, Arrays.asList(path));
nodeRef = fileInfo.getNodeRef();
}
catch (FileNotFoundException e)
{
// NOTE: return null node ref
}
}
}
else
{
// TODO: Implement 'qname' style
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Web Script Node URL specified an invalid reference style of '" + referenceType + "'");
}
}
return nodeRef;
}
/**
* Status Template
*/
private class StatusTemplate
{
/**
* Construct
*
* @param path
* @param format
*/
private StatusTemplate(String path, String format)
{
this.path = path;
this.format = format;
}
private String path;
private String format;
}
}

View File

@@ -0,0 +1,174 @@
/*
* 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 boolean authenticate(RequiredAuthentication required, boolean isGuest, WebScriptServletRequest preq, WebScriptServletResponse pres)
{
boolean authorized = false;
//
// validate credentials
//
HttpServletRequest req = preq.getHttpServletRequest();
HttpServletResponse res = pres.getHttpServletResponse();
String authorization = req.getHeader("Authorization");
String ticket = req.getParameter("alf_ticket");
if (logger.isDebugEnabled())
{
logger.debug("HTTP Authorization provided: " + (authorization != null && authorization.length() > 0));
logger.debug("URL ticket provided: " + (ticket != null && ticket.length() > 0));
}
// authenticate as guest, if service allows
if (isGuest && RequiredAuthentication.guest == required)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating as Guest");
authenticationService.authenticateAsGuest();
authorized = true;
}
// authenticate as specified by explicit ticket on url
else if (ticket != null && ticket.length() > 0)
{
try
{
if (logger.isDebugEnabled())
logger.debug("Authenticating (URL argument) ticket " + ticket);
// assume a ticket has been passed
authenticationService.validate(ticket);
authorized = true;
}
catch(AuthenticationException e)
{
// failed authentication
}
}
// 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 (BASIC HTTP) ticket " + parts[0]);
// assume a ticket has been passed
authenticationService.validate(parts[0]);
authorized = true;
}
else
{
if (logger.isDebugEnabled())
logger.debug("Authenticating (BASIC HTTP) 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\"");
}
return authorized;
}
}

View File

@@ -0,0 +1,344 @@
/*
* 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.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.repository.ScriptLocation;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.TemplateLoader;
/**
* ClassPath based Web Script Store
*
* @author davidc
*/
public class ClassPathStore implements WebScriptStore, InitializingBean
{
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
protected boolean mustExist = false;
protected String classPath;
protected File fileDir;
/**
* Sets whether the class path must exist
*
* If it must exist, but it doesn't exist, an exception is thrown
* on initialisation of the store
*
* @param mustExist
*/
public void setMustExist(boolean mustExist)
{
this.mustExist = mustExist;
}
/**
* Sets the class path
*
* @param classPath classpath
*/
public void setClassPath(String classPath)
{
this.classPath = classPath;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet()
throws Exception
{
ClassPathResource resource = new ClassPathResource(classPath);
if (resource.exists())
{
fileDir = resource.getFile();
}
else if (mustExist)
{
throw new WebScriptException("Web Script Store classpath:" + classPath + " must exist; it was not found");
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptStore#exists()
*/
public boolean exists()
{
return (fileDir != null);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptStore#getBasePath()
*/
public String getBasePath()
{
return "classpath:" + classPath;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptStore#getDescriptionDocumentPaths()
*/
public String[] getDescriptionDocumentPaths()
{
String[] paths;
try
{
int filePathLength = fileDir.getAbsolutePath().length() +1;
List<String> documentPaths = new ArrayList<String>();
Resource[] resources = resolver.getResources("classpath*:" + classPath + "/**/*.desc.xml");
for (Resource resource : resources)
{
if (resource instanceof FileSystemResource)
{
String documentPath = resource.getFile().getAbsolutePath().substring(filePathLength);
documentPath = documentPath.replace('\\', '/');
documentPaths.add(documentPath);
}
}
paths = documentPaths.toArray(new String[documentPaths.size()]);
}
catch(IOException e)
{
// Note: Ignore: no service description documents found
paths = new String[0];
}
return paths;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptStore#getScriptDocumentPaths(org.alfresco.web.scripts.WebScript)
*/
public String[] getScriptDocumentPaths(WebScript script)
{
String[] paths;
try
{
int filePathLength = fileDir.getAbsolutePath().length() +1;
List<String> documentPaths = new ArrayList<String>();
String scriptPaths = script.getDescription().getId() + ".*";
Resource[] resources = resolver.getResources("classpath*:" + classPath + "/" + scriptPaths);
for (Resource resource : resources)
{
if (resource instanceof FileSystemResource)
{
String documentPath = resource.getFile().getAbsolutePath().substring(filePathLength);
documentPath = documentPath.replace('\\', '/');
documentPaths.add(documentPath);
}
}
paths = documentPaths.toArray(new String[documentPaths.size()]);
}
catch(IOException e)
{
// Note: Ignore: no service description documents found
paths = new String[0];
}
return paths;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptStore#hasDocument(java.lang.String)
*/
public boolean hasDocument(String documentPath)
{
File document = new File(fileDir, documentPath);
return document.exists();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptStore#getDescriptionDocument(java.lang.String)
*/
public InputStream getDocument(String documentPath)
throws IOException
{
File document = new File(fileDir, documentPath);
if (!document.exists())
{
throw new IOException("Document " + documentPath + " does not exist within store " + getBasePath());
}
return new FileInputStream(document);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptStore#createDocument(java.lang.String, java.lang.String)
*/
public void createDocument(String documentPath, String content) throws IOException
{
File document = new File(fileDir, documentPath);
// create directory
File path = document.getParentFile();
path.mkdirs();
// create file
if (!document.createNewFile())
{
throw new IOException("Document " + documentPath + " already exists");
}
OutputStream output = new FileOutputStream(document);
try
{
PrintWriter writer = new PrintWriter(output);
writer.write(content);
writer.flush();
}
finally
{
output.flush();
output.close();
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptStore#getTemplateLoader()
*/
public TemplateLoader getTemplateLoader()
{
FileTemplateLoader loader = null;
try
{
loader = new FileTemplateLoader(fileDir);
}
catch (IOException e)
{
// Note: Can't establish loader, so return null
}
return loader;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptStore#getScriptLoader()
*/
public ScriptLoader getScriptLoader()
{
return new ClassPathScriptLoader();
}
/**
* Class path based script loader
*
* @author davidc
*/
private class ClassPathScriptLoader implements ScriptLoader
{
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ScriptLoader#getScriptLocation(java.lang.String)
*/
public ScriptLocation getScriptLocation(String path)
{
ScriptLocation location = null;
File scriptPath = new File(fileDir, path);
if (scriptPath.exists())
{
location = new ClassPathScriptLocation(scriptPath);
}
return location;
}
}
/**
* Class path script location
*
* @author davidc
*/
private static class ClassPathScriptLocation implements ScriptLocation
{
private File location;
/**
* Construct
*
* @param location
*/
public ClassPathScriptLocation(File location)
{
this.location = location;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.repository.ScriptLocation#getInputStream()
*/
public InputStream getInputStream()
{
try
{
return new FileInputStream(location);
}
catch (FileNotFoundException e)
{
throw new WebScriptException("Unable to retrieve input stream for script " + location.getAbsolutePath());
}
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.repository.ScriptLocation#getReader()
*/
public Reader getReader()
{
try
{
return new InputStreamReader(getInputStream(), "UTF-8");
}
catch (UnsupportedEncodingException e)
{
throw new AlfrescoRuntimeException("Unsupported Encoding", e);
}
}
@Override
public String toString()
{
return location.getAbsolutePath();
}
}
}

View File

@@ -0,0 +1,75 @@
/*
* 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 a client side javascript function to build urls to this service.
*
* <p>
* Usage: clientUrlFunction(String funcName)
*/
public final class ClientUrlFunctionMethod implements TemplateMethodModelEx
{
WebScriptResponse res;
/**
* Construct
*/
public ClientUrlFunctionMethod(WebScriptResponse res)
{
this.res = res;
}
/**
* @see freemarker.template.TemplateMethodModel#exec(java.util.List)
*/
public Object exec(List args) throws TemplateModelException
{
String result = "";
if (args.size() != 0)
{
Object arg0 = args.get(0);
if (arg0 instanceof TemplateScalarModel)
{
String arg = ((TemplateScalarModel)arg0).getAsString();
result = res.getEncodeScriptUrlFunction(arg);
}
}
return result;
}
}

View File

@@ -0,0 +1,267 @@
/*
* 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.Serializable;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.jscript.ScriptableHashMap;
import org.alfresco.repo.jscript.ValueConverter;
import org.alfresco.service.cmr.repository.ScriptLocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Script/template driven based implementation of an Web Script
*
* @author davidc
*/
public class DeclarativeWebScript extends AbstractWebScript
{
// Logger
private static final Log logger = LogFactory.getLog(DeclarativeWebScript.class);
// Script Context
private String basePath;
private ScriptLocation executeScript;
// Javascript Converter
private ValueConverter valueConverter = new ValueConverter();
/* (non-Javadoc)
* @see org.alfresco.web.scripts.AbstractWebScript#init(org.alfresco.web.scripts.WebScriptRegistry)
*/
@Override
public void init(WebScriptRegistry apiRegistry)
{
super.init(apiRegistry);
basePath = getDescription().getId();
// Test for "execute" script
String scriptPath = basePath + ".js";
executeScript = getWebScriptRegistry().getScriptProcessor().findScript(scriptPath);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScript#execute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
final public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException
{
// retrieve requested format
String format = req.getFormat();
if (format == null || format.length() == 0)
{
format = getDescription().getDefaultFormat();
}
try
{
// establish mimetype from format
String mimetype = getWebScriptRegistry().getFormatRegistry().getMimeType(req.getAgent(), format);
if (mimetype == null)
{
throw new WebScriptException("Web Script format '" + format + "' is not registered");
}
// construct model for script / template
WebScriptStatus status = new WebScriptStatus();
WebScriptCache cache = new WebScriptCache(getDescription().getRequiredCache());
Map<String, Object> model = executeImpl(req, status, cache);
if (model == null)
{
model = new HashMap<String, Object>(7, 1.0f);
}
model.put("status", status);
model.put("cache", cache);
// extract any request attributes and add them to the model - this is useful for requests
// that wish to pass further arbituary data into a webscript model
for (String name : req.getAttributeNames())
{
model.put(name, req.getAttribute(name));
}
// execute script if it exists
if (executeScript != null)
{
if (logger.isDebugEnabled())
logger.debug("Executing script " + executeScript);
Map<String, Object> scriptModel = createScriptModel(req, res, model);
// add return model allowing script to add items to template model
Map<String, Object> returnModel = new ScriptableHashMap<String, Object>();
scriptModel.put("model", returnModel);
executeScript(executeScript, scriptModel);
mergeScriptModelIntoTemplateModel(returnModel, model);
}
// create model for template rendering
Map<String, Object> templateModel = createTemplateModel(req, res, model);
// is a redirect to a status specific template required?
if (status.getRedirect())
{
sendStatus(req, res, status, cache, format, templateModel);
}
else
{
// render output
int statusCode = status.getCode();
if (statusCode != HttpServletResponse.SC_OK && !req.forceSuccessStatus())
{
logger.debug("Force success status header in response: " + req.forceSuccessStatus());
logger.debug("Setting status " + statusCode);
res.setStatus(statusCode);
}
// apply cache
res.setCache(cache);
String callback = req.getJSONCallback();
if (format.equals(WebScriptResponse.JSON_FORMAT) && callback != null)
{
if (logger.isDebugEnabled())
logger.debug("Rendering JSON callback response: content type=" + MimetypeMap.MIMETYPE_TEXT_JAVASCRIPT + ", status=" + statusCode + ", callback=" + callback);
// NOTE: special case for wrapping JSON results in a javascript function callback
res.setContentType(MimetypeMap.MIMETYPE_TEXT_JAVASCRIPT + ";charset=UTF-8");
res.getOutputStream().write((callback + "(").getBytes());
}
else
{
if (logger.isDebugEnabled())
logger.debug("Rendering response: content type=" + mimetype + ", status=" + statusCode);
res.setContentType(mimetype + ";charset=UTF-8");
}
// render response according to requested format
renderFormatTemplate(format, templateModel, res.getWriter());
if (format.equals(WebScriptResponse.JSON_FORMAT) && callback != null)
{
// NOTE: special case for wrapping JSON results in a javascript function callback
res.getOutputStream().write(")".getBytes());
}
}
}
catch(Throwable e)
{
if (logger.isInfoEnabled())
logger.info("Caught exception & redirecting to status template: " + e.getMessage());
// extract status code, if specified
int statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
if (e instanceof WebScriptException)
{
statusCode = ((WebScriptException)e).getStatus();
}
// send status
WebScriptStatus status = new WebScriptStatus();
status.setCode(statusCode);
status.setMessage(e.getMessage());
status.setException(e);
WebScriptCache cache = new WebScriptCache();
cache.setNeverCache(true);
Map<String, Object> customModel = new HashMap<String, Object>();
customModel.put("status", status);
Map<String, Object> templateModel = createTemplateModel(req, res, customModel);
sendStatus(req, res, status, cache, format, templateModel);
}
}
/**
* Merge script generated model into template-ready model
*
* @param scriptModel script model
* @param templateModel template model
*/
@SuppressWarnings("unchecked")
final private void mergeScriptModelIntoTemplateModel(Map<String, Object> scriptModel, Map<String, Object> templateModel)
{
for (Map.Entry<String, Object> entry : scriptModel.entrySet())
{
// retrieve script model value
Object value = entry.getValue();
Object templateValue = (value instanceof Serializable) ? valueConverter.convertValueForRepo((Serializable)value) : value;
templateModel.put(entry.getKey(), templateValue);
}
}
/**
* Execute custom Java logic
*
* @param req Web Script request
* @param status Web Script status
* @return custom service model
*/
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
return null;
}
/**
* Execute custom Java logic
*
* @param req Web Script request
* @param status Web Script status
* @param cache Web Script cache
* @return custom service model
*/
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status, WebScriptCache cache)
{
// NOTE: Redirect to those web scripts implemented before cache support
return executeImpl(req, status);
}
/**
* Render a template (of given format) to the Web Script Response
*
* @param format template format (null, default format)
* @param model data model to render
* @param writer where to output
*/
final protected void renderFormatTemplate(String format, Map<String, Object> model, Writer writer)
{
format = (format == null) ? "" : format;
String templatePath = basePath + "." + format + ".ftl";
if (logger.isDebugEnabled())
logger.debug("Rendering template '" + templatePath + "'");
renderTemplate(templatePath, model, writer);
}
}

View File

@@ -0,0 +1,788 @@
/*
* 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.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.servlet.ServletContext;
import org.alfresco.service.cmr.repository.FileTypeImageSize;
import org.alfresco.service.cmr.repository.TemplateImageResolver;
import org.alfresco.util.AbstractLifecycleBean;
import org.alfresco.web.scripts.WebScriptDescription.FormatStyle;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
import org.alfresco.web.scripts.WebScriptDescription.RequiredTransaction;
import org.alfresco.web.ui.common.Utils;
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.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.web.context.ServletContextAware;
/**
* Registry of declarative (scripted/template driven) Web Scripts
*
* @author davidc
*/
public class DeclarativeWebScriptRegistry extends AbstractLifecycleBean
implements WebScriptRegistry, ServletContextAware, InitializingBean
{
// Logger
private static final Log logger = LogFactory.getLog(DeclarativeWebScriptRegistry.class);
private ServletContext servletContext;
private String defaultWebScript;
private FormatRegistry formatRegistry;
private WebScriptStorage storage;
private TemplateImageResolver imageResolver;
// map of web scripts by id
// NOTE: The map is sorted by id (ascending order)
private Map<String, WebScript> webscriptsById = new TreeMap<String, WebScript>();
// map of web scripts by url
// NOTE: The map is sorted by url (descending order)
private Map<String, URLIndex> webscriptsByURL = new TreeMap<String, URLIndex>(Collections.reverseOrder());
// map of web script packages by path
private Map<String, Path> packageByPath = new TreeMap<String, Path>();
// map of web script uris by path
private Map<String, Path> uriByPath = new TreeMap<String, Path>();
//
// Initialisation
//
/**
* Sets the available Web Script Stores
*
* @param storage
*/
public void setStorage(WebScriptStorage storage)
{
this.storage = storage;
}
/**
* Sets the default service implementation bean
*
* @param defaultWebScript
*/
public void setDefaultWebScript(String defaultWebScript)
{
this.defaultWebScript = defaultWebScript;
}
/**
* Sets the response format registry
*
* @param formatRegistry
*/
public void setFormatRegistry(FormatRegistry formatRegistry)
{
this.formatRegistry = formatRegistry;
}
/* (non-Javadoc)
* @see org.springframework.web.context.ServletContextAware#setServletContext(javax.servlet.ServletContext)
*/
public void setServletContext(ServletContext context)
{
this.servletContext = context;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception
{
this.imageResolver = new TemplateImageResolver()
{
public String resolveImagePathForName(String filename, FileTypeImageSize size)
{
return Utils.getFileTypeImage(servletContext, filename, size);
}
};
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#reset()
*/
public void reset()
{
long startTime = System.currentTimeMillis();
try
{
getTemplateProcessor().resetCache();
getScriptProcessor().resetCache();
initWebScripts();
}
finally
{
if (logger.isInfoEnabled())
logger.info("Registered " + webscriptsById.size() + " Web Scripts, " + webscriptsByURL.size() + " URLs (in " + (System.currentTimeMillis() - startTime) + "ms)");
}
}
/* (non-Javadoc)
* @see org.alfresco.util.AbstractLifecycleBean#onBootstrap(org.springframework.context.ApplicationEvent)
*/
@Override
protected void onBootstrap(ApplicationEvent event)
{
reset();
}
/* (non-Javadoc)
* @see org.alfresco.util.AbstractLifecycleBean#onShutdown(org.springframework.context.ApplicationEvent)
*/
@Override
protected void onShutdown(ApplicationEvent event)
{
}
/**
* Initialise Web Scripts
*
* Note: Each invocation of this method resets the list of the services
*/
private void initWebScripts()
{
if (logger.isDebugEnabled())
logger.debug("Initialising Web Scripts");
// clear currently registered services
webscriptsById.clear();
webscriptsByURL.clear();
packageByPath.clear();
packageByPath.put("/", new Path("/"));
uriByPath.clear();
uriByPath.put("/", new Path("/"));
// register services
for (WebScriptStore apiStore : storage.getStores())
{
if (logger.isDebugEnabled())
logger.debug("Locating Web Scripts within " + apiStore.getBasePath());
String[] serviceDescPaths = apiStore.getDescriptionDocumentPaths();
for (String serviceDescPath : serviceDescPaths)
{
try
{
// build service description
WebScriptDescription serviceDesc = null;
InputStream serviceDescIS = null;
try
{
serviceDescIS = apiStore.getDocument(serviceDescPath);
serviceDesc = createDescription(apiStore, serviceDescPath, serviceDescIS);
}
catch(IOException e)
{
throw new WebScriptException("Failed to read Web Script description document " + apiStore.getBasePath() + serviceDescPath, e);
}
finally
{
try
{
if (serviceDescIS != null) serviceDescIS.close();
}
catch(IOException e)
{
// NOTE: ignore close exception
}
}
// determine if service description has been registered
String id = serviceDesc.getId();
if (webscriptsById.containsKey(id))
{
// move to next service
if (logger.isDebugEnabled())
{
WebScript existingService = webscriptsById.get(id);
WebScriptDescription existingDesc = existingService.getDescription();
String msg = "Web Script description document " + serviceDesc.getStorePath() + "/" + serviceDesc.getDescPath();
msg += " overridden by " + existingDesc.getStorePath() + "/" + existingDesc.getDescPath();
logger.debug(msg);
}
continue;
}
// construct service implementation
ApplicationContext applicationContext = getApplicationContext();
String beanName = "webscript." + id.replace('/', '.');
String serviceImplName = (applicationContext.containsBean(beanName)) ? beanName : defaultWebScript;
AbstractWebScript serviceImpl = (AbstractWebScript)applicationContext.getBean(serviceImplName);
serviceImpl.setDescription(serviceDesc);
serviceImpl.init(this);
if (logger.isDebugEnabled())
logger.debug("Found Web Script " + id + " (desc: " + serviceDescPath + ", impl: " + serviceImplName + ", auth: " +
serviceDesc.getRequiredAuthentication() + ", trx: " + serviceDesc.getRequiredTransaction() + ", format style: " +
serviceDesc.getFormatStyle() + ", default format: " + serviceDesc.getDefaultFormat() + ")");
// register service and its urls
webscriptsById.put(id, serviceImpl);
for (String uriTemplate : serviceDesc.getURIs())
{
// establish static part of url template
boolean wildcard = false;
boolean extension = true;
int queryArgIdx = uriTemplate.indexOf('?');
if (queryArgIdx != -1)
{
uriTemplate = uriTemplate.substring(0, queryArgIdx);
}
int tokenIdx = uriTemplate.indexOf('{');
if (tokenIdx != -1)
{
uriTemplate = uriTemplate.substring(0, tokenIdx);
wildcard = true;
}
if (serviceDesc.getFormatStyle() != WebScriptDescription.FormatStyle.argument)
{
int extIdx = uriTemplate.lastIndexOf(".");
if (extIdx != -1)
{
uriTemplate = uriTemplate.substring(0, extIdx);
}
extension = false;
}
// index service by static part of url (ensuring no other service has already claimed the url)
String uriIdx = serviceDesc.getMethod().toString() + ":" + uriTemplate;
if (webscriptsByURL.containsKey(uriIdx))
{
URLIndex urlIndex = webscriptsByURL.get(uriIdx);
WebScript existingService = urlIndex.script;
if (!existingService.getDescription().getId().equals(serviceDesc.getId()))
{
String msg = "Web Script document " + serviceDesc.getDescPath() + " is attempting to define the url '" + uriIdx + "' already defined by " + existingService.getDescription().getDescPath();
throw new WebScriptException(msg);
}
}
else
{
URLIndex urlIndex = new URLIndex(uriTemplate, wildcard, extension, serviceImpl);
webscriptsByURL.put(uriIdx, urlIndex);
if (logger.isDebugEnabled())
logger.debug("Registered Web Script URL '" + uriIdx + "'");
}
}
// build path indexes to web script
registerPackage(serviceImpl);
registerURIs(serviceImpl);
}
catch(WebScriptException e)
{
if (logger.isWarnEnabled())
{
Throwable c = e;
String cause = c.getMessage();
while (c.getCause() != null && !c.getCause().equals(c))
{
c = c.getCause();
cause += " ; " + c.getMessage();
}
String msg = "Unable to register script " + apiStore.getBasePath() + "/" + serviceDescPath + " due to error: " + cause;
logger.warn(msg);
}
else
{
throw e;
}
}
}
}
}
/**
* Register a Web Script Package
*
* @param script
*/
private void registerPackage(WebScript script)
{
WebScriptDescription desc = script.getDescription();
Path path = packageByPath.get("/");
String[] parts = desc.getScriptPath().split("/");
for (String part : parts)
{
Path subpath = packageByPath.get(Path.concatPath(path.getPath(), part));
if (subpath == null)
{
subpath = path.createChildPath(part);
packageByPath.put(subpath.getPath(), subpath);
}
path = subpath;
}
path.addScript(script);
}
/**
* Register a Web Script URI
*
* @param script
*/
private void registerURIs(WebScript script)
{
WebScriptDescription desc = script.getDescription();
for (String uri : desc.getURIs())
{
Path path = uriByPath.get("/");
String[] parts = uri.split("/");
for (String part : parts)
{
if (part.indexOf("?") != -1)
{
part = part.substring(0, part.indexOf("?"));
}
Path subpath = uriByPath.get(Path.concatPath(path.getPath(), part));
if (subpath == null)
{
subpath = path.createChildPath(part);
uriByPath.put(subpath.getPath(), subpath);
}
path = subpath;
}
path.addScript(script);
}
}
/**
* Create an Web Script Description
*
* @param store
* @param serviceDescPath
* @param serviceDoc
*
* @return web script service description
*/
private WebScriptDescription createDescription(WebScriptStore store, String serviceDescPath, InputStream serviceDoc)
{
SAXReader reader = new SAXReader();
try
{
// retrieve script path
int iPathIdx = serviceDescPath.lastIndexOf('/');
String scriptPath = serviceDescPath.substring(0, iPathIdx == -1 ? 0 : iPathIdx);
// retrieve script id
String id = serviceDescPath.substring(0, serviceDescPath.lastIndexOf(".desc.xml"));
// retrieve http method
int methodIdx = id.lastIndexOf('.');
if (methodIdx == -1 || (methodIdx == id.length() - 1))
{
throw new WebScriptException("Unable to establish HTTP Method from web script description: naming convention must be <name>.<method>.desc.xml");
}
String method = id.substring(methodIdx + 1).toUpperCase();
// parse description document
Document document = reader.read(serviceDoc);
Element rootElement = document.getRootElement();
if (!rootElement.getName().equals("webscript"))
{
throw new WebScriptException("Expected <webscript> root element - found <" + rootElement.getName() + ">");
}
// retrieve short name
Element shortNameElement = rootElement.element("shortname");
if (shortNameElement == null || shortNameElement.getTextTrim() == null || shortNameElement.getTextTrim().length() == 0)
{
throw new WebScriptException("Expected <shortname> value");
}
String shortName = shortNameElement.getTextTrim();
// retrieve description
String description = null;
Element descriptionElement = rootElement.element("description");
if (descriptionElement != null)
{
description = descriptionElement.getTextTrim();
}
// retrieve urls
List urlElements = rootElement.elements("url");
if (urlElements == null || urlElements.size() == 0)
{
throw new WebScriptException("Expected at least one <url> element");
}
List<String> uris = new ArrayList<String>();
Iterator iterElements = urlElements.iterator();
while(iterElements.hasNext())
{
// retrieve url element
Element urlElement = (Element)iterElements.next();
// retrieve url template
String template = urlElement.getTextTrim();
if (template == null || template.length() == 0)
{
// NOTE: for backwards compatibility only
template = urlElement.attributeValue("template");
if (template == null || template.length() == 0)
{
throw new WebScriptException("Expected <url> element value");
}
}
uris.add(template);
}
// retrieve authentication
RequiredAuthentication reqAuth = RequiredAuthentication.none;
Element authElement = rootElement.element("authentication");
if (authElement != null)
{
String reqAuthStr = authElement.getTextTrim();
if (reqAuthStr == null || reqAuthStr.length() == 0)
{
throw new WebScriptException("Expected <authentication> value");
}
reqAuth = RequiredAuthentication.valueOf(reqAuthStr);
if (reqAuth == null)
{
throw new WebScriptException("Authentication '" + reqAuthStr + "' is not a valid value");
}
}
// retrieve transaction
RequiredTransaction reqTrx = (reqAuth == RequiredAuthentication.none) ? RequiredTransaction.none : RequiredTransaction.required;
Element trxElement = rootElement.element("transaction");
if (trxElement != null)
{
String reqTrxStr = trxElement.getTextTrim();
if (reqTrxStr == null || reqTrxStr.length() == 0)
{
throw new WebScriptException("Expected <transaction> value");
}
reqTrx = RequiredTransaction.valueOf(reqTrxStr);
if (reqTrx == null)
{
throw new WebScriptException("Transaction '" + reqTrxStr + "' is not a valid value");
}
}
// retrieve format
String defaultFormat = "html";
FormatStyle formatStyle = FormatStyle.any;
Element formatElement = rootElement.element("format");
if (formatElement != null)
{
// establish if default is set explicitly
String attrDefaultValue = formatElement.attributeValue("default");
if (attrDefaultValue != null)
{
defaultFormat = (attrDefaultValue.length() == 0) ? null : attrDefaultValue;
}
// establish format declaration style
String formatStyleStr = formatElement.getTextTrim();
if (formatStyleStr != null && formatStyleStr.length() > 0)
{
formatStyle = FormatStyle.valueOf(formatStyleStr);
if (formatStyle == null)
{
throw new WebScriptException("Format Style '" + formatStyle + "' is not a valid value");
}
}
}
// retrieve caching
WebScriptCache cache = new WebScriptCache();
Element cacheElement = rootElement.element("cache");
if (cacheElement != null)
{
Element neverElement = cacheElement.element("never");
if (neverElement != null)
{
String neverStr = neverElement.getTextTrim();
boolean neverBool = (neverStr == null || neverStr.length() == 0) ? true : Boolean.valueOf(neverStr);
cache.setNeverCache(neverBool);
}
Element publicElement = cacheElement.element("public");
if (publicElement != null)
{
String publicStr = publicElement.getTextTrim();
boolean publicBool = (publicStr == null || publicStr.length() == 0) ? true : Boolean.valueOf(publicStr);
cache.setIsPublic(publicBool);
}
Element revalidateElement = cacheElement.element("mustrevalidate");
if (revalidateElement != null)
{
String revalidateStr = revalidateElement.getTextTrim();
boolean revalidateBool = (revalidateStr == null || revalidateStr.length() == 0) ? true : Boolean.valueOf(revalidateStr);
cache.setMustRevalidate(revalidateBool);
}
}
// construct service description
WebScriptDescriptionImpl serviceDesc = new WebScriptDescriptionImpl();
serviceDesc.setStore(store);
serviceDesc.setScriptPath(scriptPath);
serviceDesc.setDescPath(serviceDescPath);
serviceDesc.setId(id);
serviceDesc.setShortName(shortName);
serviceDesc.setDescription(description);
serviceDesc.setRequiredAuthentication(reqAuth);
serviceDesc.setRequiredTransaction(reqTrx);
serviceDesc.setRequiredCache(cache);
serviceDesc.setMethod(method);
serviceDesc.setUris(uris.toArray(new String[uris.size()]));
serviceDesc.setDefaultFormat(defaultFormat);
serviceDesc.setFormatStyle(formatStyle);
return serviceDesc;
}
catch(DocumentException e)
{
throw new WebScriptException("Failed to parse web script description document " + serviceDescPath, e);
}
catch(WebScriptException e)
{
throw new WebScriptException("Failed to parse web script description document " + serviceDescPath, e);
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getPackage(java.lang.String)
*/
public WebScriptPath getPackage(String scriptPackage)
{
return packageByPath.get(scriptPackage);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getUri(java.lang.String)
*/
public WebScriptPath getUri(String scriptUri)
{
return uriByPath.get(scriptUri);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getWebScripts()
*/
public Collection<WebScript> getWebScripts()
{
return webscriptsById.values();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getWebScript(java.lang.String)
*/
public WebScript getWebScript(String id)
{
return webscriptsById.get(id);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#findWebScript(java.lang.String, java.lang.String)
*/
public WebScriptMatch findWebScript(String method, String uri)
{
long startTime = System.currentTimeMillis();
// TODO: Replace with more efficient approach
String matchedPath = null;
DeclarativeWebScriptMatch apiServiceMatch = null;
String match = method.toString().toUpperCase() + ":" + uri;
String matchNoExt = method.toString().toUpperCase() + ":" + ((uri.indexOf('.') != -1) ? uri.substring(0, uri.indexOf('.')) : uri);
// locate full match - on URI and METHOD
for (Map.Entry<String, URLIndex> entry : webscriptsByURL.entrySet())
{
URLIndex urlIndex = entry.getValue();
String index = entry.getKey();
String test = urlIndex.includeExtension ? match : matchNoExt;
if ((urlIndex.wildcardPath && test.startsWith(index)) || (!urlIndex.wildcardPath && test.equals(index)))
{
apiServiceMatch = new DeclarativeWebScriptMatch(urlIndex.path, urlIndex.script);
break;
}
else if ((urlIndex.wildcardPath && uri.startsWith(urlIndex.path)) || (!urlIndex.wildcardPath && uri.equals(urlIndex.path)))
{
matchedPath = urlIndex.path;
}
}
// locate URI match
if (apiServiceMatch == null && matchedPath != null)
{
apiServiceMatch = new DeclarativeWebScriptMatch(matchedPath);
}
if (logger.isDebugEnabled())
logger.debug("Web Script index lookup for uri " + uri + " took " + (System.currentTimeMillis() - startTime) + "ms");
return apiServiceMatch;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getContext()
*/
public ServletContext getContext()
{
return servletContext;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getFormatRegistry()
*/
public FormatRegistry getFormatRegistry()
{
return this.formatRegistry;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getTemplateProcessor()
*/
public TemplateProcessor getTemplateProcessor()
{
return this.storage.getTemplateProcessor();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getTemplateImageResolver()
*/
public TemplateImageResolver getTemplateImageResolver()
{
return this.imageResolver;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getScriptProcessor()
*/
public ScriptProcessor getScriptProcessor()
{
return this.storage.getScriptProcessor();
}
/**
* Web Script Match
*
* @author davidc
*/
public static class DeclarativeWebScriptMatch implements WebScriptMatch
{
private String path;
private WebScript service;
private Kind kind;
/**
* Construct
*
* @param path
* @param service
*/
public DeclarativeWebScriptMatch(String path, WebScript service)
{
this.kind = Kind.FULL;
this.path = path;
this.service = service;
}
/**
* Construct
*
* @param path
* @param service
*/
public DeclarativeWebScriptMatch(String path)
{
this.kind = Kind.URI;
this.path = path;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptMatch#getKind()
*/
public Kind getKind()
{
return this.kind;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptMatch#getPath()
*/
public String getPath()
{
return path;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptMatch#getWebScript()
*/
public WebScript getWebScript()
{
return service;
}
@Override
public String toString()
{
return path;
}
}
/**
* Web Script URL Index Entry
*/
private static class URLIndex
{
private URLIndex(String path, boolean wildcardPath, boolean includeExtension, WebScript script)
{
this.path = path;
this.wildcardPath = wildcardPath;
this.includeExtension = includeExtension;
this.script = script;
}
private String path;
private boolean wildcardPath;
private boolean includeExtension;
private WebScript script;
}
}

View File

@@ -0,0 +1,333 @@
/*
* 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.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.jscript.Scopeable;
import org.alfresco.repo.jscript.ScriptNode;
import org.alfresco.repo.jscript.ScriptNode.ScriptContent;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
/**
* Form Data
*
* @author davidc
*/
public class FormData implements Serializable, Scopeable
{
private static final long serialVersionUID = 1832644544828452385L;
private Scriptable scope;
private HttpServletRequest req;
private ServletFileUpload upload;
private Map<String, FormField> fields = null;
private Map<String, String> parameters = null;
private Map<String, ScriptContent> files = null;
private String encoding = null;
/**
* Construct
*
* @param req
*/
public FormData(HttpServletRequest req)
{
this.req = req;
}
/* (non-Javadoc)
* @see org.alfresco.repo.jscript.Scopeable#setScope(org.mozilla.javascript.Scriptable)
*/
public void setScope(Scriptable scope)
{
this.scope = scope;
}
/**
* Determine if multi-part form data has been provided
*
* @return true => multi-part
*/
public boolean getIsMultiPart()
{
return upload.isMultipartContent(req);
}
/**
* Determine if form data has specified field
*
* @param name field to look for
* @return true => form data contains field
*/
public boolean hasField(String name)
{
Map<String, FormField> fields = getFieldsMap();
return fields.containsKey(name);
}
/**
* Gets the Form fields
*
* @return array of FormField
*/
public Scriptable getFields()
{
Map<String, FormField> fieldsMap = getFieldsMap();
Object[] fields = new Object[fieldsMap.values().size()];
fieldsMap.values().toArray(fields);
return Context.getCurrentContext().newArray(this.scope, fields);
}
/**
* Gets parameters encoded in the form data
*
* @return map (name, value) of parameters
*/
/*package*/ Map<String, String> getParameters()
{
return getParametersMap();
}
/**
* Gets files encoded in form data
*
* @return map (name, ScriptContent) of files
*/
/*package*/ Map<String, ScriptContent> getFiles()
{
return getFilesMap();
}
/**
* Helper to parse servlet request form data
*
* @return map of all form fields
*/
private Map<String, FormField> getFieldsMap()
{
// NOTE: This class is not thread safe - it is expected to be constructed on each thread.
if (fields == null)
{
FileItemFactory factory = new DiskFileItemFactory();
upload = new ServletFileUpload(factory);
encoding = req.getCharacterEncoding();
upload.setHeaderEncoding(encoding);
try
{
List<FileItem> fileItems = upload.parseRequest(req);
fields = new HashMap<String, FormField>();
for (FileItem fileItem : fileItems)
{
FormField formField = new FormField(fileItem);
fields.put(fileItem.getFieldName(), formField);
}
}
catch(FileUploadException e)
{
// NOTE: assume no files can be located
fields = Collections.emptyMap();
}
}
return fields;
}
/**
* Helper to parse servlet request form data
*
* @return map of all form parameters
*/
private Map<String, String> getParametersMap()
{
if (parameters == null)
{
Map<String, FormField> fields = getFieldsMap();
parameters = new HashMap<String, String>();
for (Map.Entry<String, FormField> entry : fields.entrySet())
{
FormField field = entry.getValue();
if (!field.getIsFile())
{
parameters.put(entry.getKey(), field.getValue());
}
}
}
return parameters;
}
/**
* Helper to parse servlet request form data
*
* @return map of all form files
*/
private Map<String, ScriptContent> getFilesMap()
{
if (files == null)
{
Map<String, FormField> fields = getFieldsMap();
files = new HashMap<String, ScriptContent>();
for (Map.Entry<String, FormField> entry : fields.entrySet())
{
FormField field = entry.getValue();
if (field.getIsFile())
{
files.put(entry.getKey(), field.getContent());
}
}
}
return files;
}
/**
* Form Field
*
* @author davidc
*/
public class FormField implements Serializable
{
private FileItem file;
/**
* Construct
*
* @param file
*/
public FormField(FileItem file)
{
this.file = file;
}
/**
* @return field name
*/
public String getName()
{
return file.getFieldName();
}
public String jsGet_name()
{
return getName();
}
/**
* @return true => field represents a file
*/
public boolean getIsFile()
{
return !file.isFormField();
}
public boolean jsGet_isFile()
{
return getIsFile();
}
/**
* @return field value (for file, attempts conversion to string)
*/
public String getValue()
{
try
{
return (file.isFormField() && encoding != null) ? file.getString(encoding) : file.getString();
}
catch (UnsupportedEncodingException e)
{
throw new AlfrescoRuntimeException("Unable to decode form field", e);
}
}
public String jsGet_value()
{
return getValue();
}
/**
* @return field as content
*/
public ScriptContent getContent()
{
try
{
return new ScriptNode.ScriptContentStream(file.getInputStream(), getMimetype(), null);
}
catch(IOException e)
{
return null;
}
}
public ScriptContent jsGet_content()
{
return getContent();
}
/**
* @return mimetype
*/
public String getMimetype()
{
return file.getContentType();
}
public String jsGet_mimetype()
{
return getMimetype();
}
/**
* @return filename (only for file fields, otherwise null)
*/
public String getFilename()
{
// workaround a bug in IE where the full path is returned
return FilenameUtils.getName(file.getName());
}
public String jsGet_filename()
{
return getFilename();
}
}
}

View File

@@ -0,0 +1,83 @@
/*
* 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.Map;
import org.springframework.beans.factory.InitializingBean;
/**
* A map of mimetypes indexed by format.
*
* @author davidc
*/
public class FormatMap implements InitializingBean
{
private FormatRegistry registry;
private String agent;
private Map<String, String> formats;
/**
* Sets the Format Registry
*
* @param registry
*/
public void setRegistry(FormatRegistry registry)
{
this.registry = registry;
}
/**
* Sets the User Agent for which the formats apply
*
* @param agent
*/
public void setAgent(String agent)
{
this.agent = agent;
}
/**
* Sets the formats
*
* @param formats
*/
public void setFormats(Map<String, String> formats)
{
this.formats = formats;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception
{
// Add formats to format registry
registry.addFormats(agent, formats);
}
}

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;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Maintains a registry of mimetypes (indexed by format and user agent)
*
* @author davidc
*/
public class FormatRegistry
{
// Logger
private static final Log logger = LogFactory.getLog(FormatRegistry.class);
private Map<String, String> formats;
private Map<String, String> mimetypes;
private Map<String, Map<String, String>> agentFormats;
private Map<String, Map<String, String>> agentMimetypes;
/**
* Construct
*/
public FormatRegistry()
{
formats = new HashMap<String, String>();
mimetypes = new HashMap<String, String>();
agentFormats = new HashMap<String, Map<String, String>>();
agentMimetypes = new HashMap<String, Map<String, String>>();
}
/**
* Add formats
*
* @param agent
* @param formatsToAdd
*/
public void addFormats(String agent, Map<String, String> formatsToAdd)
{
// retrieve formats list for agent
Map<String, String> formatsForAgent = formats;
Map<String, String> mimetypesForAgent = mimetypes;
if (agent != null)
{
formatsForAgent = agentFormats.get(agent);
if (formatsForAgent == null)
{
formatsForAgent = new HashMap<String, String>();
mimetypesForAgent = new HashMap<String, String>();
agentFormats.put(agent, formatsForAgent);
agentMimetypes.put(agent, mimetypesForAgent);
}
}
for (Map.Entry<String, String> entry : formatsToAdd.entrySet())
{
if (logger.isWarnEnabled())
{
String mimetype = formatsForAgent.get(entry.getKey());
if (mimetype != null)
{
logger.warn("Replacing mime type '" + mimetype + "' with '" + entry.getValue() + "' for Web Script format '" + entry.getKey() + "' (agent: " + agent + ")");
}
}
formatsForAgent.put(entry.getKey(), entry.getValue());
mimetypesForAgent.put(entry.getValue(), entry.getKey());
if (logger.isDebugEnabled())
logger.debug("Registered Web Script format '" + entry.getKey() + "' with mime type '" + entry.getValue() + "' (agent: " + agent + ")");
}
}
/**
* Gets the mimetype for the specified user agent and format
*
* @param agent
* @param format
* @return mimetype (or null, if one is not registered)
*/
public String getMimeType(String agent, String format)
{
String mimetype = null;
if (agent != null)
{
Map<String, String> formatsForAgent = agentFormats.get(agent);
if (formatsForAgent != null)
{
mimetype = formatsForAgent.get(format);
}
}
if (mimetype == null)
{
mimetype = formats.get(format);
}
return mimetype;
}
/**
* Gets the format for the specified user agent and mimetype
*
* @param agent
* @param mimetype
* @return format (or null, if one is not registered)
*/
public String getFormat(String agent, String mimetype)
{
String format = null;
if (agent != null)
{
Map<String, String> mimetypesForAgent = agentMimetypes.get(agent);
if (mimetypesForAgent != null)
{
format = mimetypesForAgent.get(mimetype);
}
}
if (format == null)
{
format = mimetypes.get(mimetype);
}
return format;
}
}

View File

@@ -0,0 +1,66 @@
/*
* 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.service.cmr.repository.ScriptLocation;
/**
* Composite script loader
*
* @author davidc
*/
public class MultiScriptLoader implements ScriptLoader
{
private ScriptLoader[] loaders;
/**
* Construct
*
* @param loaders
*/
public MultiScriptLoader(ScriptLoader[] loaders)
{
this.loaders = loaders;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ScriptLoader#getScriptLocation(java.lang.String)
*/
public ScriptLocation getScriptLocation(String path)
{
ScriptLocation location = null;
for (ScriptLoader loader : loaders)
{
location = loader.getScriptLocation(path);
if (location != null)
{
break;
}
}
return location;
}
}

View File

@@ -0,0 +1,149 @@
/*
* 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.Map;
import java.util.TreeMap;
/**
* Basic implementation of a Web Script Path
*
* Used for package & url trees.
*
* @author davidc
*/
public class Path implements WebScriptPath
{
private String path;
private Path parent = null;
private Map<String, Path> children = new TreeMap<String, Path>();
private Map<String, WebScript> scripts = new TreeMap<String, WebScript>();
/**
* Helper to concatenate paths
*
* @param path1
* @param path2
* @return concatenated path
*/
public static String concatPath(String path1, String path2)
{
return path1.equals("/") ? path1 + path2 : path1 + "/" + path2;
}
/**
* Construct
*
* @param path
*/
public Path(String path)
{
this.path = path;
}
/**
* Create a Child Path
*
* @param path child path name
* @return child path
*/
public Path createChildPath(String path)
{
Path child = new Path(concatPath(this.path, path));
child.parent = this;
children.put(child.path, child);
return child;
}
/**
* Associate Web Script with Path
*
* @param script
*/
public void addScript(WebScript script)
{
scripts.put(script.getDescription().getId(), script);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptPath#getChildren()
*/
public WebScriptPath[] getChildren()
{
WebScriptPath[] childrenArray = new WebScriptPath[children.size()];
return children.values().toArray(childrenArray);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptPath#getScripts()
*/
public WebScript[] getScripts()
{
WebScript[] scriptsArray = new WebScript[scripts.size()];
return scripts.values().toArray(scriptsArray);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptPath#getName()
*/
public String getName()
{
String name = "";
int i = path.lastIndexOf("/");
if (i != -1 && i != (path.length() -1))
{
name = path.substring(i + 1);
}
return name;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptPath#getParent()
*/
public WebScriptPath getParent()
{
return parent;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptPath#getPath()
*/
public String getPath()
{
return path;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString()
{
return path;
}
}

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts;
package org.alfresco.web.scripts;
import java.io.IOException;
import java.io.InputStream;
@@ -46,17 +46,13 @@ import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.ScriptLocation;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.util.AbstractLifecycleBean;
import org.alfresco.web.scripts.ScriptContent;
import org.alfresco.web.scripts.ScriptLoader;
import org.alfresco.web.scripts.Store;
import org.alfresco.web.scripts.WebScript;
import org.alfresco.web.scripts.WebScriptException;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -71,7 +67,7 @@ import freemarker.cache.TemplateLoader;
*
* @author davidc
*/
public class RepoStore implements Store, ApplicationContextAware, ApplicationListener
public class RepoStore implements WebScriptStore, ApplicationContextAware, ApplicationListener
{
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
protected boolean mustExist = false;
@@ -626,21 +622,21 @@ public class RepoStore implements Store, ApplicationContextAware, ApplicationLis
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ScriptLoader#getScriptLocation(java.lang.String)
*/
public ScriptContent getScript(final String path)
public ScriptLocation getScriptLocation(final String path)
{
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<ScriptContent>()
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<ScriptLocation>()
{
public ScriptContent doWork() throws Exception
public ScriptLocation doWork() throws Exception
{
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<ScriptContent>()
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<ScriptLocation>()
{
public ScriptContent execute() throws Exception
public ScriptLocation execute() throws Exception
{
ScriptContent location = null;
ScriptLocation location = null;
NodeRef nodeRef = findNodeRef(path);
if (nodeRef != null)
{
location = new RepoScriptContent(path, nodeRef);
location = new RepoScriptLocation(path, nodeRef);
}
return location;
}
@@ -655,7 +651,7 @@ public class RepoStore implements Store, ApplicationContextAware, ApplicationLis
*
* @author davidc
*/
private class RepoScriptContent implements ScriptContent
private class RepoScriptLocation implements ScriptLocation
{
protected String path;
protected NodeRef nodeRef;
@@ -665,7 +661,7 @@ public class RepoStore implements Store, ApplicationContextAware, ApplicationLis
*
* @param location
*/
public RepoScriptContent(String path, NodeRef nodeRef)
public RepoScriptLocation(String path, NodeRef nodeRef)
{
this.path = path;
this.nodeRef = nodeRef;

View File

@@ -0,0 +1,46 @@
/*
* 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.service.cmr.repository.ScriptLocation;
/**
* Locate a script
*
* @author davidc
*/
public interface ScriptLoader
{
/**
* Gets the script location for the script at the specified path
*
* @param path path within api store
* @return script location (or null, if script does not exist at path)
*/
ScriptLocation getScriptLocation(String path);
}

View File

@@ -0,0 +1,119 @@
/*
* 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.Map;
import org.alfresco.service.cmr.repository.ScriptException;
import org.alfresco.service.cmr.repository.ScriptLocation;
import org.alfresco.service.cmr.repository.ScriptService;
/**
* Script Processor for use in Web Script
*
* @author davidc
*/
public class ScriptProcessor
{
// dependencies
private ScriptService scriptService;
// script loader
private ScriptLoader scriptLoader;
/**
* Sets the script service
*
* @param scriptService
*/
public void setScriptService(ScriptService scriptService)
{
this.scriptService = scriptService;
}
/**
* Sets the script loader
*
* @param scriptLoader
*/
public void setScriptLoader(ScriptLoader scriptLoader)
{
this.scriptLoader = scriptLoader;
}
/**
* Find a script at the specified path (within registered Web Script stores)
*
* @param path script path
* @return script location (or null, if not found)
*/
public ScriptLocation findScript(String path)
{
return scriptLoader.getScriptLocation(path);
}
/**
* Execute script
*
* @param path script path
* @param model model
* @return script result
* @throws ScriptException
*/
public Object executeScript(String path, Map<String, Object> model)
throws ScriptException
{
// locate script within web script stores
ScriptLocation scriptLocation = findScript(path);
if (scriptLocation == null)
{
throw new WebScriptException("Unable to locate script " + path);
}
// execute script
return executeScript(scriptLocation, model);
}
/**
* Execute script
*
* @param location script location
* @param model model
* @return script result
*/
public Object executeScript(ScriptLocation location, Map<String, Object> model)
{
return scriptService.executeScript("javascript", location, model);
}
/**
* Reset script cache
*/
public void resetCache()
{
// NOOP
}
}

View File

@@ -0,0 +1,114 @@
/*
* 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 org.alfresco.web.scripts.WebScriptDescription.FormatStyle;
import freemarker.template.TemplateBooleanModel;
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() != 0)
{
Object arg0 = args.get(0);
boolean prefixServiceUrl = true;
if (args.size() == 2 && args.get(1) instanceof TemplateBooleanModel)
{
prefixServiceUrl = ((TemplateBooleanModel)args.get(1)).getAsBoolean();
}
if (arg0 instanceof TemplateScalarModel)
{
String arg = ((TemplateScalarModel)arg0).getAsString();
StringBuffer buf = new StringBuffer(128);
buf.append(prefixServiceUrl ? req.getServicePath() : "");
buf.append(arg);
if (arg.length() != 0)
{
if (arg.indexOf('?') == -1)
{
buf.append('?');
}
else
{
buf.append('&');
}
}
else
{
buf.append('?');
}
buf.append("guest=" + (req.isGuest() ? "true" : ""));
if (req.getFormatStyle() == FormatStyle.argument)
{
buf.append("&format=");
buf.append(req.getFormat());
}
result = res.encodeScriptUrl(buf.toString());
}
}
return result;
}
}

View File

@@ -1,122 +1,169 @@
/*
* 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.repo.web.scripts;
import org.alfresco.service.descriptor.Descriptor;
import org.alfresco.web.scripts.ServerModel;
/**
* Script / Template Model representing Repository Server meta-data
*
* @author davidc
*/
public class RepositoryServerModel implements ServerModel
{
private Descriptor serverDescriptor;
/**
* Construct
*
* @param serverDescriptor
*/
/*package*/ RepositoryServerModel(Descriptor serverDescriptor)
{
this.serverDescriptor = serverDescriptor;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ServerModel#getContainerName()
*/
public String getContainerName()
{
return "Repository";
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ServerModel#getVersionMajor()
*/
public String getVersionMajor()
{
return serverDescriptor.getVersionMajor();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ServerModel#getVersionMinor()
*/
public String getVersionMinor()
{
return serverDescriptor.getVersionMinor();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ServerModel#getVersionRevision()
*/
public String getVersionRevision()
{
return serverDescriptor.getVersionRevision();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ServerModel#getVersionLabel()
*/
public String getVersionLabel()
{
return serverDescriptor.getVersionLabel();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ServerModel#getVersionBuild()
*/
public String getVersionBuild()
{
return serverDescriptor.getVersionBuild();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ServerModel#getVersion()
*/
public String getVersion()
{
return serverDescriptor.getVersion();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ServerModel#getEdition()
*/
public String getEdition()
{
return serverDescriptor.getEdition();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ServerModel#getSchema()
*/
public int getSchema()
{
return serverDescriptor.getSchema();
}
}
/*
* 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.service.descriptor.Descriptor;
/**
* Script / Template Model representing Repository Server meta-data
*
* @author davidc
*/
public class ServerModel
{
private Descriptor serverDescriptor;
/**
* Construct
*
* @param serverDescriptor
*/
/*package*/ ServerModel(Descriptor serverDescriptor)
{
this.serverDescriptor = serverDescriptor;
}
/**
* Gets the major version number, e.g. <u>1</u>.2.3
*
* @return major version number
*/
public String getVersionMajor()
{
return serverDescriptor.getVersionMajor();
}
public String jsGet_versionMajor()
{
return getVersionMajor();
}
/**
* Gets the minor version number, e.g. 1.<u>2</u>.3
*
* @return minor version number
*/
public String getVersionMinor()
{
return serverDescriptor.getVersionMinor();
}
public String jsGet_versionMinor()
{
return getVersionMinor();
}
/**
* Gets the version revision number, e.g. 1.2.<u>3</u>
*
* @return revision number
*/
public String getVersionRevision()
{
return serverDescriptor.getVersionRevision();
}
public String jsGet_versionRevision()
{
return getVersionRevision();
}
/**
* Gets the version label
*
* @return the version label
*/
public String getVersionLabel()
{
return serverDescriptor.getVersionLabel();
}
public String jsGet_versionLabel()
{
return getVersionLabel();
}
/**
* Gets the build number
*
* @return the build number i.e. build-1
*/
public String getVersionBuild()
{
return serverDescriptor.getVersionBuild();
}
public String jsGet_versionBuild()
{
return getVersionBuild();
}
/**
* Gets the full version number
*
* @return full version number as major.minor.revision (label)
*/
public String getVersion()
{
return serverDescriptor.getVersion();
}
public String jsGet_version()
{
return getVersion();
}
/**
* Gets the edition
*
* @return the edition
*/
public String getEdition()
{
return serverDescriptor.getEdition();
}
public String jsGet_edition()
{
return getEdition();
}
/**
* Gets the schema number
*
* @return a positive integer
*/
public int getSchema()
{
return serverDescriptor.getSchema();
}
public int jsGet_schema()
{
return getSchema();
}
}

View File

@@ -1,205 +1,218 @@
package org.alfresco.repo.web.scripts;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.repo.template.FreeMarkerProcessor;
import org.alfresco.repo.template.QNameAwareObjectWrapper;
import org.alfresco.service.cmr.repository.ProcessorExtension;
import org.alfresco.util.AbstractLifecycleBean;
import org.alfresco.web.scripts.SearchPath;
import org.alfresco.web.scripts.Store;
import org.alfresco.web.scripts.TemplateProcessor;
import org.alfresco.web.scripts.WebScriptException;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import freemarker.cache.MruCacheStorage;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
public class RepositoryTemplateProcessor extends FreeMarkerProcessor
implements TemplateProcessor, ApplicationContextAware, ApplicationListener
{
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
protected SearchPath searchPath;
protected String defaultEncoding;
protected Configuration templateConfig;
protected FreeMarkerProcessor freeMarkerProcessor;
/* (non-Javadoc)
* @see org.alfresco.repo.template.FreeMarkerProcessor#setDefaultEncoding(java.lang.String)
*/
public void setDefaultEncoding(String defaultEncoding)
{
this.defaultEncoding = defaultEncoding;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.TemplateProcessor#getDefaultEncoding()
*/
public String getDefaultEncoding()
{
return this.defaultEncoding;
}
public void setSearchPath(SearchPath searchPath)
{
this.searchPath = searchPath;
}
/**
* Set the freemarker processor
*
* @param freeMarkerProcessor the free marker processor
*/
public void setFreeMarkerProcessor(FreeMarkerProcessor freeMarkerProcessor)
{
this.freeMarkerProcessor = freeMarkerProcessor;
}
/* (non-Javadoc)
* @see org.alfresco.repo.template.FreeMarkerProcessor#getConfig()
*/
@Override
protected Configuration getConfig()
{
return templateConfig;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.TemplateProcessor#reset()
*/
public void reset()
{
if (templateConfig != null)
{
templateConfig.clearTemplateCache();
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.TemplateProcessor#hasTemplate(java.lang.String)
*/
public boolean hasTemplate(String templatePath)
{
boolean hasTemplate = false;
try
{
Template template = templateConfig.getTemplate(templatePath);
hasTemplate = (template != null);
}
catch(FileNotFoundException e)
{
// NOTE: return false as template is not found
}
catch(IOException e)
{
throw new WebScriptException("Failed to retrieve template " + templatePath, e);
}
return hasTemplate;
}
/**
* Initialise FreeMarker Configuration
*/
protected void initConfig()
{
Configuration config = new Configuration();
// setup template cache
config.setCacheStorage(new MruCacheStorage(20, 100));
config.setTemplateUpdateDelay(0);
// setup template loaders
List<TemplateLoader> loaders = new ArrayList<TemplateLoader>();
for (Store apiStore : searchPath.getStores())
{
TemplateLoader loader = apiStore.getTemplateLoader();
if (loader == null)
{
throw new WebScriptException("Unable to retrieve template loader for Web Script store " + apiStore.getBasePath());
}
loaders.add(loader);
}
MultiTemplateLoader loader = new MultiTemplateLoader(loaders.toArray(new TemplateLoader[loaders.size()]));
config.setTemplateLoader(loader);
// use our custom object wrapper that can deal with QNameMap objects directly
config.setObjectWrapper(new QNameAwareObjectWrapper());
// rethrow any exception so we can deal with them
config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
// turn off locale sensitive lookup - to save numerous wasted calls to nodeservice.exists()
config.setLocalizedLookup(false);
// set template encoding
if (defaultEncoding != null)
{
config.setDefaultEncoding(defaultEncoding);
}
// set output encoding
config.setOutputEncoding("UTF-8");
templateConfig = config;
}
/**
* Tempory fix to initialise this template processor with the freeMarker extensions expected by
* the templates.
*/
private void initProcessorExtensions()
{
for (ProcessorExtension processorExtension : this.freeMarkerProcessor.getProcessorExtensions())
{
this.registerProcessorExtension(processorExtension);
}
}
/* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
lifecycle.setApplicationContext(applicationContext);
}
/* (non-Javadoc)
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/
public void onApplicationEvent(ApplicationEvent event)
{
lifecycle.onApplicationEvent(event);
}
/**
* Hooks into Spring Application Lifecycle
*/
private class ProcessorLifecycle extends AbstractLifecycleBean
{
@Override
protected void onBootstrap(ApplicationEvent event)
{
initConfig();
initProcessorExtensions();
}
@Override
protected void onShutdown(ApplicationEvent event)
{
}
}
}
/*
* 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.FileNotFoundException;
import java.io.IOException;
import org.alfresco.repo.template.FreeMarkerProcessor;
import org.alfresco.repo.template.QNameAwareObjectWrapper;
import org.alfresco.service.cmr.repository.ProcessorExtension;
import org.alfresco.util.AbstractLifecycleBean;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import freemarker.cache.MruCacheStorage;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
/**
* FreeMarker Processor for use in Web Scripts
*
* Adds the ability to:
* - specify template loaders
* - caching of templates
*
* @author davidc
*/
public class TemplateProcessor extends FreeMarkerProcessor implements ApplicationContextAware, ApplicationListener
{
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
protected TemplateLoader templateLoader = null;
protected String defaultEncoding;
protected Configuration templateConfig;
protected FreeMarkerProcessor freeMarkerProcessor;
/* (non-Javadoc)
* @see org.alfresco.repo.template.FreeMarkerProcessor#setDefaultEncoding(java.lang.String)
*/
public void setDefaultEncoding(String defaultEncoding)
{
this.defaultEncoding = defaultEncoding;
}
/* (non-Javadoc)
* @see org.alfresco.repo.template.FreeMarkerProcessor#getConfig()
*/
@Override
protected Configuration getConfig()
{
return templateConfig;
}
/**
* Sets the Template Loader
*
* @param templateLoader template loader
*/
public void setTemplateLoader(TemplateLoader templateLoader)
{
this.templateLoader = templateLoader;
}
/**
* Set the freemarker processor
*
* @param freeMarkerProcessor the free marker processor
*/
public void setFreeMarkerProcessor(FreeMarkerProcessor freeMarkerProcessor)
{
this.freeMarkerProcessor = freeMarkerProcessor;
}
/**
* Reset template cache
*/
public void resetCache()
{
if (templateConfig != null)
{
templateConfig.clearTemplateCache();
}
}
/**
* Determines if a template exists
*
* @param template
* @return true => exists
*/
public boolean hasTemplate(String templatePath)
{
boolean hasTemplate = false;
try
{
Template template = templateConfig.getTemplate(templatePath);
hasTemplate = (template != null);
}
catch(FileNotFoundException e)
{
// NOTE: return false as template is not found
}
catch(IOException e)
{
throw new WebScriptException("Failed to retrieve template " + templatePath, e);
}
return hasTemplate;
}
/**
* Initialise FreeMarker Configuration
*/
protected void initConfig()
{
Configuration config = new Configuration();
// setup template cache
config.setCacheStorage(new MruCacheStorage(20, 100));
// setup template loaders
config.setTemplateLoader(templateLoader);
// use our custom object wrapper that can deal with QNameMap objects directly
config.setObjectWrapper(new QNameAwareObjectWrapper());
// rethrow any exception so we can deal with them
config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
// turn off locale sensitive lookup - to save numerous wasted calls to nodeservice.exists()
config.setLocalizedLookup(false);
// set template encoding
if (defaultEncoding != null)
{
config.setDefaultEncoding(defaultEncoding);
}
// set output encoding
config.setOutputEncoding("UTF-8");
templateConfig = config;
}
/**
* Tempory fix to initialise this template processor with the freeMarker extensions expected by
* the templates.
*/
private void initProcessorExtensions()
{
for (ProcessorExtension processorExtension : this.freeMarkerProcessor.getProcessorExtensions())
{
this.registerProcessorExtension(processorExtension);
}
}
/* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
lifecycle.setApplicationContext(applicationContext);
}
/* (non-Javadoc)
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/
public void onApplicationEvent(ApplicationEvent event)
{
lifecycle.onApplicationEvent(event);
}
/**
* Hooks into Spring Application Lifecycle
*/
private class ProcessorLifecycle extends AbstractLifecycleBean
{
@Override
protected void onBootstrap(ApplicationEvent event)
{
initConfig();
initProcessorExtensions();
}
@Override
protected void onShutdown(ApplicationEvent event)
{
}
}
}

View File

@@ -0,0 +1,536 @@
/*
* 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.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.config.Config;
import org.alfresco.config.ConfigService;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.web.config.ServerConfigElement;
import org.springframework.context.ApplicationContext;
import org.springframework.context.MessageSource;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
/**
* Stand-alone Web Script Test Server
*
* @author davidc
*/
public class TestWebScriptServer
{
// dependencies
protected AuthenticationService authenticationService;
protected DeclarativeWebScriptRegistry registry;
protected ConfigService configService;
protected ServiceRegistry serviceRegistry;
protected RetryingTransactionHelper retryingTransactionHelper;
/** Server Configuration */
private ServerConfigElement serverConfig;
/** The reader for interaction. */
private BufferedReader fIn;
/** Last command issued */
private String lastCommand = null;
/** Current user */
private String username = "admin";
/** Current headers */
private Map<String, String> headers = new HashMap<String, String>();
/** I18N Messages */
private MessageSource m_messages;
/**
* Sets helper that provides transaction callbacks
*/
public void setTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
{
this.retryingTransactionHelper = retryingTransactionHelper;
}
/**
* Sets the Web Script Registry
*
* @param registry
*/
public void setRegistry(DeclarativeWebScriptRegistry registry)
{
this.registry = registry;
}
/**
* Sets the Service Registry
*
* @param registry
*/
public void setServiceRegistry(ServiceRegistry serviceRegistry)
{
this.serviceRegistry = serviceRegistry;
}
/**
* Sets the Config Service
*
* @param configService
*/
public void setConfigService(ConfigService configService)
{
this.configService = configService;
}
/**
* @param authenticationService
*/
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
/**
* Sets the Messages resource bundle
*
* @param messages
* @throws IOException
*/
public void setMessages(MessageSource messages)
throws IOException
{
this.m_messages = messages;
}
/**
* Initialise the Test Web Script Server
*
* @throws Exception
*/
public void init()
{
Config config = configService.getConfig("Server");
serverConfig = (ServerConfigElement)config.getConfigElement(ServerConfigElement.CONFIG_ELEMENT_ID);
}
/**
* Main entry point.
*/
public static void main(String[] args)
{
try
{
TestWebScriptServer testServer = getTestServer();
testServer.rep();
}
catch(Throwable e)
{
StringWriter strWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(strWriter);
e.printStackTrace(printWriter);
System.out.println(strWriter.toString());
}
finally
{
System.exit(0);
}
}
/**
* Retrieve an instance of the TestWebScriptServer
*
* @return Test Server
*/
public static TestWebScriptServer getTestServer()
{
String[] CONFIG_LOCATIONS = new String[]
{
"classpath:alfresco/application-context.xml",
"classpath:alfresco/web-scripts-application-context.xml",
"classpath:alfresco/web-client-application-context.xml",
"classpath:alfresco/web-scripts-application-context-test.xml"
};
ApplicationContext context = new ClassPathXmlApplicationContext(CONFIG_LOCATIONS);
TestWebScriptServer testServer = (TestWebScriptServer)context.getBean("webscripts.test");
testServer.init();
return testServer;
}
/**
* Submit a Web Script Request
*
* @param method http method
* @param uri web script uri (relative to /alfresco/service)
* @return response
* @throws IOException
*/
public MockHttpServletResponse submitRequest(String method, String uri)
throws IOException
{
MockHttpServletRequest req = createRequest(method, uri);
MockHttpServletResponse res = new MockHttpServletResponse();
WebScriptRuntime runtime = new WebScriptServletRuntime(registry, serviceRegistry, null, req, res, serverConfig);
runtime.executeScript();
return res;
}
/**
* Submit a Web Script Request
*
* @param method http method
* @param uri web script uri (relative to /alfresco/service)
* @param headers headers
* @return response
* @throws IOException
*/
public MockHttpServletResponse submitRequest(String method, String uri, Map<String, String> headers)
throws IOException
{
MockHttpServletRequest req = createRequest(method, uri);
for (Map.Entry<String, String> header: headers.entrySet())
{
req.addHeader(header.getKey(), header.getValue());
}
MockHttpServletResponse res = new MockHttpServletResponse();
WebScriptRuntime runtime = new WebScriptServletRuntime(registry, serviceRegistry, null, req, res, serverConfig);
runtime.executeScript();
return res;
}
/**
* A Read-Eval-Print loop.
*/
/*package*/ void rep()
{
// accept commands
fIn = new BufferedReader(new InputStreamReader(System.in));
while (true)
{
System.out.print("ok> ");
try
{
// get command
final String line = fIn.readLine();
if (line.equals("exit") || line.equals("quit"))
{
return;
}
// execute command in context of currently selected user
long startms = System.currentTimeMillis();
System.out.print(interpretCommand(line));
System.out.println("" + (System.currentTimeMillis() - startms) + "ms");
}
catch (Exception e)
{
e.printStackTrace(System.err);
System.out.println("");
}
}
}
/**
* Interpret a single command using the BufferedReader passed in for any data needed.
*
* @param line The unparsed command
* @return The textual output of the command.
*/
private String interpretCommand(final String line)
throws IOException
{
try
{
if (username.startsWith("TICKET_"))
{
try
{
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Object>()
{
public Object execute() throws Exception
{
authenticationService.validate(username);
return null;
}
});
return executeCommand(line);
}
finally
{
authenticationService.clearCurrentSecurityContext();
}
}
}
catch(AuthenticationException e)
{
executeCommand("user admin");
}
// execute command in context of currently selected user
return AuthenticationUtil.runAs(new RunAsWork<String>()
{
@SuppressWarnings("synthetic-access")
public String doWork() throws Exception
{
return executeCommand(line);
}
}, username);
}
/**
* Execute a single command using the BufferedReader passed in for any data needed.
*
* TODO: Use decent parser!
*
* @param line The unparsed command
* @return The textual output of the command.
*/
private String executeCommand(String line)
throws IOException
{
String[] command = line.split(" ");
if (command.length == 0)
{
command = new String[1];
command[0] = line;
}
ByteArrayOutputStream bout = new ByteArrayOutputStream();
PrintStream out = new PrintStream(bout);
// repeat last command?
if (command[0].equals("r"))
{
if (lastCommand == null)
{
return "No command entered yet.";
}
return "repeating command " + lastCommand + "\n\n" + interpretCommand(lastCommand);
}
// remember last command
lastCommand = line;
// execute command
if (command[0].equals("help"))
{
String helpFile = m_messages.getMessage("testserver.help", null, null);
ClassPathResource helpResource = new ClassPathResource(helpFile);
byte[] helpBytes = new byte[500];
InputStream helpStream = helpResource.getInputStream();
try
{
int read = helpStream.read(helpBytes);
while (read != -1)
{
bout.write(helpBytes, 0, read);
read = helpStream.read(helpBytes);
}
}
finally
{
helpStream.close();
}
}
else if (command[0].equals("user"))
{
if (command.length == 2)
{
username = command[1];
}
out.println("using user " + username);
}
else if (command[0].equals("get") ||
command[0].equals("put") ||
command[0].equals("post") ||
command[0].equals("delete"))
{
String uri = (command.length > 1) ? command[1] : null;
MockHttpServletResponse res = submitRequest(command[0], uri, headers);
bout.write(("Response status: " + res.getStatus()).getBytes());
out.println();
bout.write(res.getContentAsByteArray());
out.println();
}
else if (command[0].equals("tunnel"))
{
if (command.length < 4)
{
return "Syntax Error.\n";
}
if (command[1].equals("param"))
{
String uri = command[3];
if (uri.indexOf('?') == -1)
{
uri += "?alf:method=" + command[2];
}
else
{
uri += "&alf:method=" + command[2];
}
MockHttpServletResponse res = submitRequest("post", uri, headers);
bout.write(res.getContentAsByteArray());
out.println();
}
else if (command[1].equals("header"))
{
Map<String, String> tunnelheaders = new HashMap<String, String>();
tunnelheaders.putAll(headers);
tunnelheaders.put("X-HTTP-Method-Override", command[2]);
MockHttpServletResponse res = submitRequest("post", command[3], tunnelheaders);
bout.write(res.getContentAsByteArray());
out.println();
}
else
{
return "Syntax Error.\n";
}
}
else if (command[0].equals("header"))
{
if (command.length == 1)
{
for (Map.Entry<String, String> entry : headers.entrySet())
{
out.println(entry.getKey() + " = " + entry.getValue());
}
}
else if (command.length == 2)
{
String[] param = command[1].split("=");
if (param.length == 0)
{
return "Syntax Error.\n";
}
if (param.length == 1)
{
headers.remove(param[0]);
out.println("deleted header " + param[0]);
}
else if (param.length == 2)
{
headers.put(param[0], param[1]);
out.println("set header " + param[0] + " = " + headers.get(param[0]));
}
else
{
return "Syntax Error.\n";
}
}
else
{
return "Syntax Error.\n";
}
}
else if (command[0].equals("reset"))
{
registry.reset();
out.println("Registry reset.");
}
else
{
return "Syntax Error.\n";
}
out.flush();
String retVal = new String(bout.toByteArray());
out.close();
return retVal;
}
/**
* Create a Mock HTTP Servlet Request
*
* @param method
* @param uri
* @return mock http servlet request
* @throws UnsupportedEncodingException
*/
private MockHttpServletRequest createRequest(String method, String uri)
throws UnsupportedEncodingException
{
MockHttpServletRequest req = new MockHttpServletRequest(method, uri);
req.setContextPath("/alfresco");
req.setServletPath("/service");
if (uri != null)
{
int iArgIndex = uri.indexOf('?');
if (iArgIndex != -1 && iArgIndex != uri.length() -1)
{
String uriArgs = uri.substring(iArgIndex +1);
String[] args = uriArgs.split("&");
for (String arg : args)
{
String[] parts = arg.split("=");
req.addParameter(parts[0], (parts.length == 2) ? URLDecoder.decode(parts[1], "UTF-8") : null);
}
req.setQueryString(URLDecoder.decode(uriArgs, "UTF-8"));
}
String requestURI = "/alfresco/service" + (iArgIndex == -1 ? uri : uri.substring(0, iArgIndex));
req.setRequestURI(URLDecoder.decode(requestURI, "UTF-8"));
}
return req;
}
}

View File

@@ -0,0 +1,174 @@
/*
* 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;
/**
* Script / Template Model representing Web Script URLs
*
* @author davidc
*/
public class URLModel
{
private WebScriptRequest req;
/**
* Construct
*
* @param req
* @param res
*/
URLModel(WebScriptRequest req)
{
this.req = req;
}
/**
* Gets the Context Path
*
* e.g. /alfresco
*
* @return context path
*/
public String getContext()
{
return req.getContextPath();
}
public String jsGet_context()
{
return getContext();
}
/**
* Gets the Service Context Path
*
* e.g. /alfresco/service
*
* @return service context path
*/
public String getServiceContext()
{
return req.getServiceContextPath();
}
public String jsGet_serviceContext()
{
return getServiceContext();
}
/**
* Gets the Service Path
*
* e.g. /alfresco/service/search/keyword
*
* @return service path
*/
public String getService()
{
return req.getServicePath();
}
public String jsGet_service()
{
return getService();
}
/**
* Gets the full path
*
* e.g. /alfresco/service/search/keyword?q=term
*
* @return service path
*/
public String getFull()
{
return req.getURL();
}
public String jsGet_full()
{
return getFull();
}
/**
* Gets the URL arguments (query string)
*
* @return args (query string)
*/
public String getArgs()
{
String args = req.getQueryString();
return (args == null) ? "" : args;
}
public String jsGet_args()
{
return getArgs();
}
/**
* Gets the matching service path
*
* e.g.
* a) service registered path = /search/engine
* b) request path = /search/engine/external
*
* => /search/engine
*
* @return matching path
*/
public String getMatch()
{
return req.getServiceMatch().getPath();
}
public String jsGet_match()
{
return getMatch();
}
/**
* Gets the Service Extension Path
*
* e.g.
* a) service registered path = /search/engine
* b) request path = /search/engine/external
*
* => /external
*
* @return extension path
*/
public String getExtension()
{
return req.getExtensionPath();
}
public String jsGet_extension()
{
return getExtension();
}
}

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 java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.ServletContextAware;
/**
* Alfresco Web Client Authentication Interceptor
*
* @author davidc
*/
public class WebClientAuthenticator implements WebScriptServletAuthenticator, ServletContextAware
{
// Logger
private static final Log logger = LogFactory.getLog(WebClientAuthenticator.class);
// dependencies
private ServletContext context;
/* (non-Javadoc)
* @see org.springframework.web.context.ServletContextAware#setServletContext(javax.servlet.ServletContext)
*/
public void setServletContext(ServletContext context)
{
this.context = context;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptServletAuthenticator#authenticate(org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication, boolean, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public boolean authenticate(RequiredAuthentication required, boolean isGuest, WebScriptServletRequest preq, WebScriptServletResponse pres)
{
AuthenticationStatus status = null;
try
{
//
// validate credentials
//
HttpServletRequest req = preq.getHttpServletRequest();
HttpServletResponse res = pres.getHttpServletResponse();
String ticket = req.getParameter("ticket");
if (logger.isDebugEnabled())
{
logger.debug("Alfresco ticket provided: " + (ticket != null && ticket.length() > 0));
}
if (ticket != null && ticket.length() > 0)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating ticket " + ticket);
status = AuthenticationHelper.authenticate(context, req, res, ticket);
}
else
{
if (isGuest && RequiredAuthentication.guest == required)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating as Guest");
status = AuthenticationHelper.authenticate(context, req, res, true);
}
else
{
if (logger.isDebugEnabled())
logger.debug("Authenticating session");
status = AuthenticationHelper.authenticate(context, req, res, false, false);
}
}
//
// if not authorized, redirect to login page
//
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(req, res, context);
}
}
catch(IOException e)
{
throw new WebScriptException("Failed to authenticate", e);
}
return !(status == null || status == AuthenticationStatus.Failure);
}
}

View File

@@ -0,0 +1,53 @@
/*
* 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;
/**
* Web Script
*
* @author davidc
*/
public interface WebScript
{
/**
* Gets the Service Description
*
* @return service description
*/
public WebScriptDescription getDescription();
/**
* Execute service
*
* @param req
* @param res
* @throws IOException
*/
public void execute(WebScriptRequest req, WebScriptResponse res)
throws IOException;
}

View File

@@ -0,0 +1,162 @@
/*
* 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.Date;
/**
* Web Script Cache
*
* Records the desired cache requirements for the Web Script
*
* @author davidc
*/
public class WebScriptCache implements WebScriptDescription.RequiredCache
{
private boolean neverCache = true;
private boolean isPublic = false;
private boolean mustRevalidate = true;
private Date lastModified = null;
private String eTag = null;
private Long maxAge = null;
/**
* Construct
*/
public WebScriptCache()
{
}
/**
* Construct
*
* @param requiredCache
*/
public WebScriptCache(WebScriptDescription.RequiredCache requiredCache)
{
neverCache = requiredCache.getNeverCache();
isPublic = requiredCache.getIsPublic();
mustRevalidate = requiredCache.getMustRevalidate();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription.RequiredCache#getNeverCache()
*/
public boolean getNeverCache()
{
return neverCache;
}
/**
* @param neverCache
*/
public void setNeverCache(boolean neverCache)
{
this.neverCache = neverCache;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription.RequiredCache#getIsPublic()
*/
public boolean getIsPublic()
{
return isPublic;
}
/**
* @param isPublic
*/
public void setIsPublic(boolean isPublic)
{
this.isPublic = isPublic;
}
/**
* @return last modified
*/
public Date getLastModified()
{
return lastModified;
}
/**
* @param lastModified
*/
public void setLastModified(Date lastModified)
{
this.lastModified = lastModified;
}
/**
* @return ETag
*/
public String getETag()
{
return eTag;
}
/**
* @param tag ETag
*/
public void setETag(String tag)
{
eTag = tag;
}
/**
* @return Max Age (seconds)
*/
public Long getMaxAge()
{
return maxAge;
}
/**
* @param maxAge Max Age (seconds)
*/
public void setMaxAge(Long maxAge)
{
this.maxAge = maxAge;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription.RequiredCache#getMustRevalidate()
*/
public boolean getMustRevalidate()
{
return mustRevalidate;
}
/**
* @param mustRevalidate
*/
public void setMustRevalidate(boolean mustRevalidate)
{
this.mustRevalidate = mustRevalidate;
}
}

View File

@@ -22,20 +22,14 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts;
package org.alfresco.web.scripts;
import java.util.Arrays;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
@@ -43,7 +37,6 @@ import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.util.AbstractLifecycleBean;
import org.alfresco.web.scripts.WebScriptException;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -56,7 +49,7 @@ import org.springframework.context.ApplicationListener;
*
* @author davidc
*/
public class Repository implements ApplicationContextAware, ApplicationListener
public class WebScriptContext implements ApplicationContextAware, ApplicationListener
{
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
@@ -65,7 +58,6 @@ public class Repository implements ApplicationContextAware, ApplicationListener
private NamespaceService namespaceService;
private SearchService searchService;
private NodeService nodeService;
private FileFolderService fileFolderService;
private PersonService personService;
// company home
@@ -131,17 +123,7 @@ public class Repository implements ApplicationContextAware, ApplicationListener
{
this.nodeService = nodeService;
}
/**
* Sets the file folder service
*
* @param nodeService
*/
public void setFileFolderService(FileFolderService fileFolderService)
{
this.fileFolderService = fileFolderService;
}
/**
* Sets the person service
*
@@ -254,79 +236,4 @@ public class Repository implements ApplicationContextAware, ApplicationListener
return (NodeRef)nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
}
/**
* Helper to convert a Web Script Request URL to a Node Ref
*
* 1) Node - {store_type}/{store_id}/{node_id}
*
* Resolve to node via its Node Reference.
*
* 2) Path - {store_type}/{store_id}/{path}
*
* Resolve to node via its display path.
*
* 3) QName - {store_type}/{store_id}/{child_qname_path} TODO: Implement
*
* Resolve to node via its child qname path.
*
* @param referenceType one of node, path or qname
* @return reference array of reference segments (as described above for each reference type)
*/
public NodeRef findNodeRef(String referenceType, String[] reference)
{
NodeRef nodeRef = null;
// construct store reference
if (reference.length < 3)
{
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Reference " + Arrays.toString(reference) + " is not properly formed");
}
StoreRef storeRef = new StoreRef(reference[0], reference[1]);
if (nodeService.exists(storeRef))
{
if (referenceType.equals("node"))
{
NodeRef urlRef = new NodeRef(storeRef, reference[2]);
if (nodeService.exists(urlRef))
{
nodeRef = urlRef;
}
}
else if (referenceType.equals("path"))
{
// TODO: Allow a root path to be specified - for now, hard-code to Company Home
// NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
NodeRef rootNodeRef = getCompanyHome();
if (reference.length == 3)
{
nodeRef = rootNodeRef;
}
else
{
String[] path = new String[reference.length - /*2*/3];
System.arraycopy(reference, /*2*/3, path, 0, path.length);
try
{
FileInfo fileInfo = fileFolderService.resolveNamePath(rootNodeRef, Arrays.asList(path));
nodeRef = fileInfo.getNodeRef();
}
catch (FileNotFoundException e)
{
// NOTE: return null node ref
}
}
}
else
{
// TODO: Implement 'qname' style
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Web Script Node URL specified an invalid reference style of '" + referenceType + "'");
}
}
return nodeRef;
}
}

View File

@@ -0,0 +1,196 @@
/*
* 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.InputStream;
/**
* Web Script Description
*
* @author davidc
*/
public interface WebScriptDescription
{
/**
* Enumeration of "required" Authentication level
*/
public enum RequiredAuthentication
{
none,
guest,
user,
admin
}
/**
* Enumeration of "required" Transaction level
*/
public enum RequiredTransaction
{
none,
required,
requiresnew
}
/**
* Caching requirements
*/
public interface RequiredCache
{
/**
* Determine if Web Script should ever be cached
*
* @return true => do not cache, false => caching may or not occur
*/
public boolean getNeverCache();
/**
* Determine if Web Script content is for public caching
*
* @return true => content is public, so allow cache
*/
public boolean getIsPublic();
/**
* Must cache re-validate to ensure content is fresh
*
* @return true => must re-validate
*/
public boolean getMustRevalidate();
}
/**
* Enumeration of ways to specify format
*/
public enum FormatStyle
{
any, // any of the following styles
extension, // /a/b/c.x
argument // /a/b/c?format=x
}
/**
* Gets the root path of the store of this web script
*
* @return root path of store
*/
public String getStorePath();
/**
* Gets the path within the store of this web script
*
* @return path within store
*/
public String getScriptPath();
/**
* Gets the path of the description xml document for this web script
*
* @return document location (path)
*/
public String getDescPath();
/**
* Gets the description xml document for this web script
*
* @return source document
*/
public InputStream getDescDocument()
throws IOException;
/**
* Gets the id of this service
*
* @return service id
*/
public String getId();
/**
* Gets the short name of this service
*
* @return service short name
*/
public String getShortName();
/**
* Gets the description of this service
*/
public String getDescription();
/**
* Gets the required authentication level for execution of this service
*
* @return the required authentication level
*/
public RequiredAuthentication getRequiredAuthentication();
/**
* Gets the required transaction level
*
* @return the required transaction level
*/
public RequiredTransaction getRequiredTransaction();
/**
* Gets the required level of caching
* @return
*/
public RequiredCache getRequiredCache();
/**
* Gets the HTTP method this service is bound to
*
* @return HTTP method
*/
public String getMethod();
/**
* Gets the URIs this service supports
*
* @return array of URIs in order specified in service description document
*/
public String[] getURIs();
/**
* Gets the style of Format discriminator supported by this web script
*
* @return format style
*/
public FormatStyle getFormatStyle();
/**
* Gets the default response format
*
* Note: the default response format is the first listed in the service
* description document
*
* @return default response format (or null, if format not known until run-time)
*/
public String getDefaultFormat();
}

View File

@@ -0,0 +1,296 @@
/*
* 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.InputStream;
/**
* Implementation of a Web Script Description
*
* @author davidc
*/
public class WebScriptDescriptionImpl implements WebScriptDescription
{
private WebScriptStore store;
private String scriptPath;
private String descPath;
private String id;
private String shortName;
private String description;
private RequiredAuthentication requiredAuthentication;
private RequiredTransaction requiredTransaction;
private RequiredCache requiredCache;
private FormatStyle formatStyle;
private String httpMethod;
private String[] uris;
private String defaultFormat;
/**
* Sets the web description store
*
* @param store store
*/
public void setStore(WebScriptStore store)
{
this.store = store;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getStorePath()
*/
public String getStorePath()
{
return store.getBasePath();
}
/**
* Sets the script path
*
* @param scriptPath
*/
public void setScriptPath(String scriptPath)
{
this.scriptPath = scriptPath;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getScriptPath()
*/
public String getScriptPath()
{
return scriptPath;
}
/**
* Sets the desc path
*
* @param descPath
*/
public void setDescPath(String descPath)
{
this.descPath = descPath;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getDescPath()
*/
public String getDescPath()
{
return descPath;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getDescDocument()
*/
public InputStream getDescDocument()
throws IOException
{
return store.getDocument(descPath);
}
/**
* Sets the service id
*
* @param id
*/
public void setId(String id)
{
this.id = id;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getId()
*/
public String getId()
{
return this.id;
}
/**
* Sets the service short name
*
* @param shortName
*/
public void setShortName(String shortName)
{
this.shortName = shortName;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getShortName()
*/
public String getShortName()
{
return this.shortName;
}
/**
* Sets the service description
*
* @param description
*/
public void setDescription(String description)
{
this.description = description;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getDescription()
*/
public String getDescription()
{
return this.description;
}
/**
* Sets the required level of authentication
*
* @param requiredAuthentication
*/
public void setRequiredAuthentication(RequiredAuthentication requiredAuthentication)
{
this.requiredAuthentication = requiredAuthentication;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getRequiredAuthentication()
*/
public RequiredAuthentication getRequiredAuthentication()
{
return this.requiredAuthentication;
}
/**
* Sets the required level of transaction
*
* @param requiredTransaction
*/
public void setRequiredTransaction(RequiredTransaction requiredTransaction)
{
this.requiredTransaction = requiredTransaction;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getRequiredTransaction()
*/
public RequiredTransaction getRequiredTransaction()
{
return this.requiredTransaction;
}
/**
* Sets the required cache
*
* @param requiredCache
*/
public void setRequiredCache(RequiredCache requiredCache)
{
this.requiredCache = requiredCache;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getRequiredCache()
*/
public RequiredCache getRequiredCache()
{
return this.requiredCache;
}
/**
* Sets the format style
*
* @param formatStyle
*/
public void setFormatStyle(FormatStyle formatStyle)
{
this.formatStyle = formatStyle;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getFormatStyle()
*/
public FormatStyle getFormatStyle()
{
return this.formatStyle;
}
/**
* Sets the service http method
*
* @param httpMethod
*/
public void setMethod(String httpMethod)
{
this.httpMethod = httpMethod;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getMethod()
*/
public String getMethod()
{
return this.httpMethod;
}
/**
* Sets the service URIs
*
* @param uris
*/
public void setUris(String[] uris)
{
this.uris = uris;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getURIs()
*/
public String[] getURIs()
{
return this.uris;
}
/**
* Sets the default response format
*
* @param defaultFormat
*/
public void setDefaultFormat(String defaultFormat)
{
this.defaultFormat = defaultFormat;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getDefaultFormat()
*/
public String getDefaultFormat()
{
return this.defaultFormat;
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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.HttpServletResponse;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* Web Script Exceptions.
*
* @author David Caruana
*/
public class WebScriptException extends AlfrescoRuntimeException
{
private static final long serialVersionUID = -7338963365877285084L;
private int status = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
public WebScriptException(int status, String msgId)
{
this(msgId);
this.status = status;
}
public WebScriptException(String msgId)
{
super(msgId);
}
public WebScriptException(String msgId, Throwable cause)
{
super(msgId, cause);
}
public WebScriptException(String msgId, Object ... args)
{
super(msgId, args);
}
public WebScriptException(String msgId, Throwable cause, Object ... args)
{
super(msgId, args, cause);
}
public int getStatus()
{
return status;
}
}

View File

@@ -0,0 +1,62 @@
/*
* 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;
/**
* Represents a URL request to Web Script match
*
* @author davidc
*/
public interface WebScriptMatch
{
public enum Kind
{
/** URL request matches on URI only */
URI,
/** URL request matches on URI and Method */
FULL
};
/**
* Gets the kind of Match
*/
public Kind getKind();
/**
* Gets the part of the request URL that matched the Web Script URL Template
*
* @return matching url path
*/
public String getPath();
/**
* Gets the matching web script
*
* @return service (or null, if match kind is URI)
*/
public WebScript getWebScript();
}

View File

@@ -0,0 +1,70 @@
/*
* 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;
/**
* Web Script Path
*
* @author davidc
*/
public interface WebScriptPath
{
/**
* Gets the full path
*
* @return path
*/
public String getPath();
/**
* Gets the name of the path (last path segment)
*
* @return name
*/
public String getName();
/**
* Gets the parent path
*
* @return path
*/
public WebScriptPath getParent();
/**
* Gets the child paths
*
* @return child paths
*/
public WebScriptPath[] getChildren();
/**
* Gets Web Scripts associated with this path
*
* @return web scripts
*/
public WebScript[] getScripts();
}

View File

@@ -0,0 +1,120 @@
/*
* 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.Collection;
import javax.servlet.ServletContext;
import org.alfresco.service.cmr.repository.TemplateImageResolver;
/**
* Web Scripts Registry
*
* @author davidc
*/
public interface WebScriptRegistry
{
/**
* Gets a Web Script Package
*
* @param packagePath
* @return web script path representing package
*/
public WebScriptPath getPackage(String packagePath);
/**
* Gets a Web Script URL
*
* @param uriPath
* @return web script path representing uri
*/
public WebScriptPath getUri(String uriPath);
/**
* Gets all Web Scripts
*
* @return web scripts
*/
public Collection<WebScript> getWebScripts();
/**
* Gets a Web Script by Id
*
* @param id web script id
* @return web script
*/
public WebScript getWebScript(String id);
/**
* Gets a Web Script given an HTTP Method and URI
*
* @param method http method
* @param uri uri
* @return service match (pair of service and uri that matched)
*/
public WebScriptMatch findWebScript(String method, String uri);
/**
* Gets the Servlet Context
*
* @return servlet context
*/
public ServletContext getContext();
/**
* Gets the response format registry
*
* @return response format registry
*/
public FormatRegistry getFormatRegistry();
/**
* Gets the Template Processor
*
* @return template processor
*/
public TemplateProcessor getTemplateProcessor();
/**
* Gets the Template Image Resolver
*
* @return template image resolver
*/
public TemplateImageResolver getTemplateImageResolver();
/**
* Gets the Script Processor
*
* @return script processor
*/
public ScriptProcessor getScriptProcessor();
/**
* Resets the Registry
*/
public void reset();
}

View File

@@ -0,0 +1,199 @@
/*
* 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.web.scripts.WebScriptDescription.FormatStyle;
/**
* Web Script Request
*
* @author davidc
*/
public interface WebScriptRequest
{
/**
* Gets the matching API Service for this request
*
* @return the service match
*/
public WebScriptMatch getServiceMatch();
/**
* Get server portion of the request
*
* e.g. scheme://host:port
*
* @return server path
*/
public String getServerPath();
/**
* Gets the Alfresco Context Path
*
* @return context url e.g. /alfresco
*/
public String getContextPath();
/**
* Gets the Alfresco Web Script Context Path
*
* @return service url e.g. /alfresco/service
*/
public String getServiceContextPath();
/**
* Gets the Alfresco Service Path
*
* @return service url e.g. /alfresco/service/search/keyword
*/
public String getServicePath();
/**
* Gets the full request URL
*
* @return request url e.g. /alfresco/service/search/keyword?q=term
*/
public String getURL();
/**
* Gets the service specific path
*
* @return request path e.g. /search/keyword
*/
public String getPathInfo();
/**
* Gets the query String
*
* @return query string e.g. q=alfresco&format=atom
*/
public String getQueryString();
/**
* Gets the names of all parameters on the Url
*
* @return the names (empty, if none)
*/
public String[] getParameterNames();
/**
* Gets the value of the named parameter
*
* @param name parameter name
* @return parameter value (or null, if parameter does not exist)
*/
public String getParameter(String name);
/**
* Gets the (array) value of the named parameter
*
* Note: An array of one item is returned when a "single value" named parameter
* is requested
*
* @param name parameter name
* @return array of values (or null, if parameter does not exist)
*/
public String[] getParameterValues(String name);
/**
*
* @return
*/
public String[] getAttributeNames();
/**
*
* @param name
* @return
*/
public Object getAttribute(String name);
/**
*
* @return
*/
public Object[] getAttributeValues();
/**
* Gets the path extension beyond the path registered for this service
*
* e.g.
* a) service registered path = /search/engine
* b) request path = /search/engine/external
*
* => /external
*
* @return extension path
*/
public String getExtensionPath();
/**
* Determine if Guest User?
*
* @return true => guest user
*/
public boolean isGuest();
/**
* Get Requested Format
*
* @return content type requested
*/
public String getFormat();
/**
* Get the style the Format was specified in
*
* @return format style (excludes any)
*/
public FormatStyle getFormatStyle();
/**
* Get User Agent
*
* TODO: Expand on known agents
*
* @return MSIE / Firefox
*/
public String getAgent();
/**
* Get the JSON callback method
*
* @return method (or null, if not specified)
*/
public String getJSONCallback();
/**
* Force response to return SUCCESS (200) code
*
* Note: This is to support clients who cannot support non-success codes
* e.g. Flash player
*
* @return true => force return of 200, otherwise return status explicitly set
*/
public boolean forceSuccessStatus();
}

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 org.alfresco.web.scripts.WebScriptDescription.FormatStyle;
/**
* Basic Implementation of a Web Script Request
*
* @author davidc
*/
public abstract class WebScriptRequestImpl implements WebScriptRequest
{
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getExtensionPath()
*/
public String getExtensionPath()
{
String extensionPath = "";
WebScriptMatch match = getServiceMatch();
if (match != null)
{
String matchPath = getServiceMatch().getPath();
String pathInfo = getPathInfo();
if (pathInfo != null)
{
extensionPath = pathInfo.substring(matchPath.length());
}
}
return extensionPath;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#isGuest()
*/
public boolean isGuest()
{
return Boolean.valueOf(getParameter("guest"));
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getFormat()
*/
public String getFormat()
{
String format = null;
WebScriptMatch match = getServiceMatch();
if (match != null)
{
FormatStyle style = getServiceMatch().getWebScript().getDescription().getFormatStyle();
// extract format from extension
if (style == FormatStyle.extension || style == FormatStyle.any)
{
String pathInfo = getPathInfo();
if (pathInfo != null)
{
int extIdx = pathInfo.lastIndexOf('.');
if (extIdx != -1)
{
format = pathInfo.substring(extIdx +1);
}
}
}
// extract format from argument
if (style == FormatStyle.argument || style == FormatStyle.any)
{
String argFormat = getParameter("format");
if (argFormat != null)
{
if (format != null && format.length() > 0)
{
throw new WebScriptException("Format specified both in extension and format argument");
}
format = argFormat;
}
}
}
return (format == null || format.length() == 0) ? "" : format;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getFormatStyle()
*/
public FormatStyle getFormatStyle()
{
WebScriptMatch match = getServiceMatch();
if (match == null)
{
return FormatStyle.any;
}
FormatStyle style = match.getWebScript().getDescription().getFormatStyle();
if (style != FormatStyle.any)
{
return style;
}
else
{
String argFormat = getParameter("format");
if (argFormat != null && argFormat.length() > 0)
{
return FormatStyle.argument;
}
else
{
return FormatStyle.extension;
}
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getJSONCallback()
*/
public String getJSONCallback()
{
return getParameter("alf_callback");
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#forceSuccessStatus()
*/
public boolean forceSuccessStatus()
{
return false;
}
}

View File

@@ -0,0 +1,108 @@
/*
* 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;
/**
* Web Script Response
*
* @author davidc
*/
public interface WebScriptResponse
{
// 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";
/**
* Sets the Response Status
*
* @param status
*/
public void setStatus(int status);
/**
* Sets the Content Type
*
* @param contentType
*/
public void setContentType(String contentType);
/**
* Sets the Cache control
*
* @param cache cache control
*/
public void setCache(WebScriptCache cache);
/**
* Gets the Writer
*
* @return writer
* @throws IOException
*/
public Writer getWriter() throws IOException;
/**
* Gets the Output Stream
*
* @return output stream
* @throws IOException
*/
public OutputStream getOutputStream() throws IOException;
/**
* Clears response buffer
*/
public void reset();
/**
* Encode a script URL
*
* Note: Some Web Script Runtime environments (e.g. JSR-168, JSF) require urls to be re-written.
*
* @param url to encode
* @return encoded url
*/
public String encodeScriptUrl(String url);
/**
* Return a client side javascript function to build urls to this service
*
* @param name Generated function name
*
* @return javascript function definition
*/
public String getEncodeScriptUrlFunction(String name);
}

View File

@@ -0,0 +1,453 @@
/*
* 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.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.security.AuthorityService;
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 ServiceRegistry serviceRegistry;
private RetryingTransactionHelper retryingTransactionHelper;
private AuthorityService authorityService;
/**
* Construct
*
* @param registry web script registry
* @param serviceRegistry service registry
*/
public WebScriptRuntime(WebScriptRegistry registry, ServiceRegistry serviceRegistry)
{
this.registry = registry;
this.serviceRegistry = serviceRegistry;
this.authorityService = serviceRegistry.getAuthorityService();
this.retryingTransactionHelper = serviceRegistry.getRetryingTransactionHelper();
}
/**
* Execute the Web Script encapsulated by this Web Script Runtime
*/
public void executeScript()
{
long startRuntime = System.currentTimeMillis();
String method = getScriptMethod();
String scriptUrl = null;
try
{
// extract script url
scriptUrl = getScriptUrl();
if (scriptUrl == null || scriptUrl.length() == 0)
{
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Script URL not specified");
}
if (logger.isDebugEnabled())
logger.debug("Processing script url (" + method + ") " + scriptUrl);
WebScriptMatch match = registry.findWebScript(method, scriptUrl);
if (match == null || match.getKind() == WebScriptMatch.Kind.URI)
{
if (match == null)
{
String msg = "Script url " + scriptUrl + " does not map to a Web Script.";
if (logger.isDebugEnabled())
logger.debug(msg);
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, msg);
}
else
{
String msg = "Script url " + scriptUrl + " does not support the method " + method;
if (logger.isDebugEnabled())
logger.debug(msg);
throw new WebScriptException(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
}
}
// create web script request & response
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();
String reqFormat = scriptReq.getFormat();
String format = (reqFormat == null || reqFormat.length() == 0) ? "default" : scriptReq.getFormat();
WebScriptDescription desc = scriptReq.getServiceMatch().getWebScript().getDescription();
logger.debug("Format style: " + desc.getFormatStyle() + ", Default format: " + desc.getDefaultFormat());
logger.debug("Invoking Web Script " + description.getId() + (user == null ? " (unauthenticated)" : " (authenticated as " + user + ") (format " + format + ") (" + locale + ")"));
}
// execute script within required level of authentication
authenticatedExecute(scriptReq, scriptRes);
}
finally
{
if (logger.isDebugEnabled())
{
long endScript = System.currentTimeMillis();
logger.debug("Web Script " + description.getId() + " executed in " + (endScript - startScript) + "ms");
}
}
}
catch(Throwable e)
{
if (logger.isInfoEnabled())
logger.info("Caught exception & redirecting to status template: " + e.getMessage());
if (logger.isDebugEnabled())
{
StringWriter writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
e.printStackTrace(printWriter);
logger.debug("Caught exception: " + writer.toString());
}
// extract status code, if specified
int statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
if (e instanceof WebScriptException)
{
statusCode = ((WebScriptException)e).getStatus();
}
// create web script status for status template rendering
WebScriptStatus status = new WebScriptStatus();
status.setCode(statusCode);
status.setMessage(e.getMessage());
status.setException(e);
// create basic model for status template rendering
WebScriptRequest req = createRequest(null);
WebScriptResponse res = createResponse();
Map<String, Object> model = new HashMap<String, Object>();
model.put("status", status);
model.put("url", new URLModel(req));
model.put("server", new ServerModel(serviceRegistry.getDescriptorService().getServerDescriptor()));
model.put("date", new Date());
// locate status template
// NOTE: search order...
// 1) root located <status>.ftl
// 2) root located status.ftl
String templatePath = getStatusCodeTemplate(statusCode);
if (!registry.getTemplateProcessor().hasTemplate(templatePath))
{
templatePath = getStatusTemplate();
if (!registry.getTemplateProcessor().hasTemplate(templatePath))
{
throw new WebScriptException("Failed to find status template " + templatePath + " (format: " + WebScriptResponse.HTML_FORMAT + ")");
}
}
// render output
if (logger.isDebugEnabled())
{
logger.debug("Force success status header in response: " + req.forceSuccessStatus());
logger.debug("Sending status " + statusCode + " (Template: " + templatePath + ")");
logger.debug("Rendering response: content type=" + MimetypeMap.MIMETYPE_HTML);
}
res.reset();
WebScriptCache cache = new WebScriptCache();
cache.setNeverCache(true);
res.setCache(cache);
res.setStatus(req.forceSuccessStatus() ? HttpServletResponse.SC_OK : statusCode);
res.setContentType(MimetypeMap.MIMETYPE_HTML + ";charset=UTF-8");
try
{
registry.getTemplateProcessor().process(templatePath, model, res.getWriter());
}
catch (IOException e1)
{
throw new WebScriptException("Internal error", e1);
}
}
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)
{
transactionedExecute(scriptReq, scriptRes);
}
else if ((required == RequiredAuthentication.user || required == RequiredAuthentication.admin) && isGuest)
{
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "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
//
if (authenticate(required, isGuest, scriptReq, scriptRes))
{
if (required == RequiredAuthentication.admin && !authorityService.hasAdminAuthority())
{
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires admin authentication; however, a non-admin has attempted access.");
}
// Execute Web Script
transactionedExecute(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 script within required level of transaction
*
* @param scriptReq
* @param scriptRes
* @throws IOException
*/
protected void transactionedExecute(final WebScriptRequest scriptReq, final WebScriptResponse scriptRes)
throws IOException
{
final WebScript script = scriptReq.getServiceMatch().getWebScript();
final WebScriptDescription description = script.getDescription();
if (description.getRequiredTransaction() == RequiredTransaction.none)
{
wrappedExecute(scriptReq, scriptRes);
}
else
{
// encapsulate script within transaction
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
{
public Object execute() throws Exception
{
if (logger.isDebugEnabled())
logger.debug("Begin transaction: " + description.getRequiredTransaction());
wrappedExecute(scriptReq, scriptRes);
if (logger.isDebugEnabled())
logger.debug("End transaction: " + description.getRequiredTransaction());
return null;
}
};
if (description.getRequiredTransaction() == RequiredTransaction.required)
{
retryingTransactionHelper.doInTransaction(work);
}
else
{
retryingTransactionHelper.doInTransaction(work, false, true);
}
}
}
/**
* 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
*
* @return true if authorised, false otherwise
*/
// TODO: DC - This method to be refactored during Web Script F/W extraction
protected abstract boolean authenticate(RequiredAuthentication required, boolean isGuest, WebScriptRequest req, WebScriptResponse res);
/**
* Pre-execution hook
*
* @param scriptReq Web Script Request
* @param scriptRes Web Script Response
* @return true => execute script, false => do not execute script
*/
protected boolean preExecute(WebScriptRequest scriptReq, WebScriptResponse scriptRes)
{
return true;
}
/**
* 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 void postExecute(WebScriptRequest scriptReq, WebScriptResponse scriptRes)
{
}
protected String getStatusCodeTemplate(int statusCode)
{
return "/" + statusCode + ".ftl";
}
protected String getStatusTemplate()
{
return "/status.ftl";
}
}

View File

@@ -0,0 +1,132 @@
/*
* 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 javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.config.Config;
import org.alfresco.config.ConfigService;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.web.config.ServerConfigElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* Entry point for Web Scripts
*
* @author davidc
*/
public class WebScriptServlet extends HttpServlet
{
private static final long serialVersionUID = 4209892938069597860L;
// Logger
private static final Log logger = LogFactory.getLog(WebScriptServlet.class);
// Component Dependencies
protected DeclarativeWebScriptRegistry registry;
protected ServiceRegistry serviceRegistry;
protected WebScriptServletAuthenticator authenticator;
protected ConfigService configService;
/** Host Server Configuration */
protected static ServerConfigElement serverConfig;
@Override
public void init() throws ServletException
{
super.init();
ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
registry = (DeclarativeWebScriptRegistry)context.getBean("webscripts.registry");
serviceRegistry = (ServiceRegistry)context.getBean(ServiceRegistry.SERVICE_REGISTRY);
configService = (ConfigService)context.getBean("webClientConfigService");
// retrieve authenticator via servlet initialisation parameter
String authenticatorId = getInitParameter("authenticator");
if (authenticatorId == null || authenticatorId.length() == 0)
{
authenticatorId = getDefaultAuthenticator();
}
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;
// retrieve host server configuration
Config config = configService.getConfig("Server");
serverConfig = (ServerConfigElement)config.getConfigElement(ServerConfigElement.CONFIG_ELEMENT_ID);
// servlet specific initialisation
initServlet(context);
}
/*
* (non-Javadoc)
*
* @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
{
if (logger.isDebugEnabled())
logger.debug("Processing request (" + req.getMethod() + ") " + req.getRequestURL() + (req.getQueryString() != null ? "?" + req.getQueryString() : ""));
if (req.getCharacterEncoding() == null)
{
req.setCharacterEncoding("UTF-8");
}
WebScriptRuntime runtime = new WebScriptServletRuntime(registry, serviceRegistry, authenticator, req, res, serverConfig);
runtime.executeScript();
}
/**
* Servlet specific initialisation
*
* @param context
*/
protected void initServlet(ApplicationContext context)
{
// NOOP
}
/**
* @return default authenticator (bean name)
*/
protected String getDefaultAuthenticator()
{
return "webscripts.authenticator.webclient";
}
}

View File

@@ -0,0 +1,48 @@
/*
* 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.web.scripts.WebScriptDescription.RequiredAuthentication;
/**
* Web Script Authenticator for the HTTP Servlet environment
*
* @author davidc
*/
public interface WebScriptServletAuthenticator
{
/**
* Authenticate Web Script execution
*
* @param required required level of authentication
* @param isGuest is Guest accessing the web script
* @param req http servlet request
* @param res http servlet response
*
* @return true if authorised to execute the script, false otherwise
*/
// TODO: DC - This method to be refactored during Web Script F/W extraction
public boolean authenticate(RequiredAuthentication required, boolean isGuest, WebScriptServletRequest req, WebScriptServletResponse res);
}

View File

@@ -0,0 +1,357 @@
/*
* 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.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.web.config.ServerConfigElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* HTTP Servlet Web Script Request
*
* @author davidc
*/
public class WebScriptServletRequest extends WebScriptRequestImpl
{
// Logger
private static final Log logger = LogFactory.getLog(WebScriptServletRequest.class);
/** Server Config */
private ServerConfigElement serverConfig;
/** HTTP Request */
private HttpServletRequest req;
/** Service bound to this request */
private WebScriptMatch serviceMatch;
/** Form data associated with multipart/form-data */
private FormData formData;
/**
* Construct
*
* @param req
* @param serviceMatch
*/
public WebScriptServletRequest(HttpServletRequest req, WebScriptMatch serviceMatch)
{
this(null, req, serviceMatch);
}
/**
* Construct
*
* @param serverConfig
* @param req
* @param serviceMatch
*/
public WebScriptServletRequest(ServerConfigElement serverConfig, HttpServletRequest req, WebScriptMatch serviceMatch)
{
this.serverConfig = serverConfig;
this.req = req;
this.serviceMatch = serviceMatch;
String contentType = req.getContentType();
if (logger.isDebugEnabled())
logger.debug("Content Type: " + contentType);
if (contentType != null && contentType.startsWith("multipart/form-data"))
{
formData = new FormData(req);
}
}
/**
* Gets the HTTP Servlet Request
*
* @return HTTP Servlet Request
*/
public HttpServletRequest getHttpServletRequest()
{
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 getServerScheme() + "://" + getServerName() + ":" + getServerPort();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getContextPath()
*/
public String getContextPath()
{
return req.getContextPath();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getServiceContextPath()
*/
public String getServiceContextPath()
{
return req.getContextPath() + req.getServletPath();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getServicePath()
*/
public String getServicePath()
{
String pathInfo = getPathInfo();
return getServiceContextPath() + ((pathInfo == null) ? "" : pathInfo);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getURL()
*/
public String getURL()
{
return getServicePath() + (req.getQueryString() != null ? "?" + req.getQueryString() : "");
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getPathInfo()
*/
public String getPathInfo()
{
// NOTE: Don't use req.getPathInfo() - it truncates the path at first semi-colon in Tomcat
String requestURI = req.getRequestURI();
String pathInfo = requestURI.substring(getServiceContextPath().length());
try
{
return URLDecoder.decode(pathInfo, "UTF-8");
}
catch(UnsupportedEncodingException e)
{
throw new WebScriptException("Failed to retrieve path info", e);
}
}
/* (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()
{
if (formData == null)
{
Set<String> keys = req.getParameterMap().keySet();
String[] names = new String[keys.size()];
keys.toArray(names);
return names;
}
else
{
Set<String> keys = formData.getParameters().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)
{
if (formData == null)
{
return req.getParameter(name);
}
else
{
return formData.getParameters().get(name);
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getArrayParameter(java.lang.String)
*/
public String[] getParameterValues(String name)
{
if (formData == null)
{
return req.getParameterValues(name);
}
else
{
String value = formData.getParameters().get(name);
return (value == null ) ? new String[] {} : new String[] {value};
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getAttribute(java.lang.String)
*/
public Object getAttribute(String name)
{
return null;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getAttributeNames()
*/
public String[] getAttributeNames()
{
return new String[0];
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getAttributeValues()
*/
public Object[] getAttributeValues()
{
return new String[0];
}
/**
* Get User Agent
*
* TODO: Expand on known agents
*
* @return MSIE / Firefox
*/
public String getAgent()
{
String userAgent = req.getHeader("user-agent");
if (userAgent != null)
{
if (userAgent.indexOf("Firefox/") != -1)
{
return "Firefox";
}
else if (userAgent.indexOf("MSIE") != -1)
{
return "MSIE";
}
}
return null;
}
/**
* Get Server Scheme
*
* @return server scheme
*/
private String getServerScheme()
{
String scheme = null;
if (serverConfig != null)
{
scheme = serverConfig.getScheme();
}
if (scheme == null)
{
scheme = req.getScheme();
}
return scheme;
}
/**
* Get Server Name
*
* @return server name
*/
private String getServerName()
{
String name = null;
if (serverConfig != null)
{
name = serverConfig.getHostName();
}
if (name == null)
{
name = req.getServerName();
}
return name;
}
/**
* Get Server Port
*
* @return server name
*/
private int getServerPort()
{
Integer port = null;
if (serverConfig != null)
{
port = serverConfig.getPort();
}
if (port == null)
{
port = req.getServerPort();
}
return port;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequestImpl#forceSuccessStatus()
*/
@Override
public boolean forceSuccessStatus()
{
String forceSuccess = req.getHeader("alf-force-success-response");
return Boolean.valueOf(forceSuccess);
}
/**
* Gets the Form data associated with this request
*
* @return form data, or null if request is not multipart/form-data encoded
*/
public FormData getFormData()
{
return formData;
}
}

View File

@@ -0,0 +1,218 @@
/*
* 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 java.text.SimpleDateFormat;
import java.util.TimeZone;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.util.CachingDateFormat;
import org.alfresco.web.ui.common.Utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* HTTP Servlet Web Script Response
*
* @author davidc
*/
public class WebScriptServletResponse implements WebScriptResponse
{
// Logger
private static final Log logger = LogFactory.getLog(WebScriptServletResponse.class);
// Servlet Response
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#setStatus(int)
*/
public void setStatus(int status)
{
res.setStatus(status);
}
/* (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#setCache(org.alfresco.web.scripts.WebScriptCache)
*/
public void setCache(WebScriptCache cache)
{
// set Cache-Control
String cacheControl = "";
String pragma = "";
if (cache.getIsPublic())
{
cacheControl += "public";
}
if (cache.getNeverCache())
{
cacheControl += (cacheControl.length() > 0 ? ", " : "") + "no-cache";
pragma += (pragma.length() > 0) ? ", " : "" + "no-cache";
}
if (cache.getMaxAge() != null && cache.getNeverCache() == false)
{
cacheControl += (cacheControl.length() > 0 ? ", " : "") + " max-age=" + cache.getMaxAge();
}
if (cache.getMustRevalidate() && cache.getNeverCache() == false)
{
cacheControl += (cacheControl.length() > 0 ? ", " : "") + " must-revalidate";
}
if (cacheControl.length() > 0)
{
res.setHeader("Cache-Control", cacheControl);
if (logger.isDebugEnabled())
logger.debug("Cache - set response header Cache-Control: " + cacheControl);
}
if (pragma.length() > 0)
{
res.setHeader("Pragma", pragma);
if (logger.isDebugEnabled())
logger.debug("Cache - set response header Pragma: " + pragma);
}
// set ETag
if (cache.getETag() != null)
{
String eTag = "\"" + cache.getETag() + "\"";
res.setHeader("ETag", eTag);
if (logger.isDebugEnabled())
logger.debug("Cache - set response header ETag: " + eTag);
}
// set Last Modified
if (cache.getLastModified() != null)
{
res.setDateHeader("Last-Modified", cache.getLastModified().getTime());
if (logger.isDebugEnabled())
{
SimpleDateFormat formatter = getHTTPDateFormat();
String lastModified = formatter.format(cache.getLastModified());
logger.debug("Cache - set response header Last-Modified: " + lastModified);
}
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#reset()
*/
public void reset()
{
try
{
res.reset();
}
catch(IllegalStateException e)
{
}
}
/* (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;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#getEncodeScriptUrlFunction(java.lang.String)
*/
public String getEncodeScriptUrlFunction(String name)
{
return Utils.encodeJavascript(ENCODE_FUNCTION.replace("$name$", name));
}
private static final String ENCODE_FUNCTION = "{ $name$: function(url) { return url; } }";
/**
* Helper to return a HTTP Date Formatter
*
* @return HTTP Date Formatter
*/
private static SimpleDateFormat getHTTPDateFormat()
{
if (s_dateFormat.get() != null)
{
return s_dateFormat.get();
}
SimpleDateFormat formatter = CachingDateFormat.getDateFormat("EEE, dd MMM yyyy kk:mm:ss zzz", false);
formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
s_dateFormat.set(formatter);
return s_dateFormat.get();
}
private static ThreadLocal<SimpleDateFormat> s_dateFormat = new ThreadLocal<SimpleDateFormat>();
}

View File

@@ -0,0 +1,149 @@
/*
* 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.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.web.config.ServerConfigElement;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
/**
* HTTP Servlet Web Script Runtime
*
* @author davidc
*/
public class WebScriptServletRuntime extends WebScriptRuntime
{
protected HttpServletRequest req;
protected HttpServletResponse res;
protected WebScriptServletAuthenticator authenticator;
protected ServerConfigElement serverConfig;
/**
* Construct
*
* @param registry
* @param serviceRegistry
* @param authenticator
* @param req
* @param res
*/
public WebScriptServletRuntime(WebScriptRegistry registry, ServiceRegistry serviceRegistry, WebScriptServletAuthenticator authenticator,
HttpServletRequest req, HttpServletResponse res, ServerConfigElement serverConfig)
{
super(registry, serviceRegistry);
this.req = req;
this.res = res;
this.authenticator = authenticator;
this.serverConfig = serverConfig;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#getScriptMethod()
*/
@Override
protected String getScriptMethod()
{
// Is this an overloaded POST request?
String method = req.getMethod();
if (method.equalsIgnoreCase("post"))
{
boolean overloadParam = false;
String overload = req.getHeader("X-HTTP-Method-Override");
if (overload == null || overload.length() == 0)
{
overload = req.getParameter("alf_method");
overloadParam = true;
}
if (overload != null && overload.length() > 0)
{
if (logger.isDebugEnabled())
logger.debug("POST is tunnelling method '" + overload + "' as specified by " + (overloadParam ? "alf_method parameter" : "X-HTTP-Method-Override header"));
method = overload;
}
}
return method;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#getScriptUrl()
*/
@Override
protected String getScriptUrl()
{
// NOTE: Don't use req.getPathInfo() - it truncates the path at first semi-colon in Tomcat
String requestURI = req.getRequestURI();
String pathInfo = requestURI.substring((req.getContextPath() + req.getServletPath()).length());
try
{
return URLDecoder.decode(pathInfo, "UTF-8");
}
catch(UnsupportedEncodingException e)
{
throw new WebScriptException("Failed to retrieve path info", e);
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#createRequest(org.alfresco.web.scripts.WebScriptMatch)
*/
@Override
protected WebScriptRequest createRequest(WebScriptMatch match)
{
return new WebScriptServletRequest(serverConfig, 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 boolean authenticate(RequiredAuthentication required, boolean isGuest, WebScriptRequest req, WebScriptResponse res)
{
boolean authorised = true;
if (authenticator != null)
{
authorised = authenticator.authenticate(required, isGuest, (WebScriptServletRequest)req, (WebScriptServletResponse)res);
}
return authorised;
}
}

View File

@@ -0,0 +1,178 @@
/*
* 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.HttpServletResponse;
import org.alfresco.i18n.I18NUtil;
/**
* Web Script Status
*
* Records the outcome of a Web Script.
*
* @author davidc
*/
public class WebScriptStatus
{
private Throwable exception = null;
private int code = HttpServletResponse.SC_OK;
private String message = "";
private boolean redirect = false;
/**
* @param exception
*/
public void setException(Throwable exception)
{
this.exception = exception;
}
/**
* @return exception
*/
public Throwable getException()
{
return exception;
}
public Throwable jsGet_exception()
{
return getException();
}
/**
* @param message
*/
public void setMessage(String message)
{
this.message = message;
}
public void jsSet_message(String message)
{
setMessage(message);
}
/**
* @return message
*/
public String getMessage()
{
return message;
}
public String jsGet_message()
{
return getMessage();
}
/**
* @param redirect redirect to status code response
*/
public void setRedirect(boolean redirect)
{
this.redirect = redirect;
}
public void jsSet_redirect(boolean redirect)
{
setRedirect(redirect);
}
/**
* @return redirect to status code response
*/
public boolean getRedirect()
{
return redirect;
}
public boolean jsGet_redirect()
{
return getRedirect();
}
/**
* @see javax.servlet.http.HTTPServletResponse
*
* @param code status code
*/
public void setCode(int code)
{
this.code = code;
}
public void jsSet_code(int code)
{
this.code = code;
}
/**
* @return status code
*/
public int getCode()
{
return code;
}
public int jsGet_code()
{
return getCode();
}
/**
* Gets the short name of the status code
*
* @return status code name
*/
public String getCodeName()
{
return I18NUtil.getMessage("webscript.code." + code + ".name");
}
public String jsGet_codeName()
{
return getCodeName();
}
/**
* Gets the description of the status code
*
* @return status code description
*/
public String getCodeDescription()
{
return I18NUtil.getMessage("webscript.code." + code + ".description");
}
public String jsGet_codeDescription()
{
return getCodeDescription();
}
}

View File

@@ -0,0 +1,207 @@
/*
* 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.ArrayList;
import java.util.Collection;
import java.util.List;
import org.alfresco.util.AbstractLifecycleBean;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
/**
* Web Script Storage
*
* @author davidc
*/
public class WebScriptStorage implements ApplicationContextAware, ApplicationListener
{
private ApplicationContext applicationContext;
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
private TemplateProcessor templateProcessor;
private ScriptProcessor scriptProcessor;
/* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
this.applicationContext = applicationContext;
this.lifecycle.setApplicationContext(applicationContext);
}
/* (non-Javadoc)
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/
public void onApplicationEvent(ApplicationEvent event)
{
lifecycle.onApplicationEvent(event);
}
/**
* Sets the template processor
*
* @param templateProcessor
*/
public void setTemplateProcessor(TemplateProcessor templateProcessor)
{
this.templateProcessor = templateProcessor;
}
/**
* Sets the script processor
*
* @param scriptProcessor
*/
public void setScriptProcessor(ScriptProcessor scriptProcessor)
{
this.scriptProcessor = scriptProcessor;
}
/**
* Gets all Web Script Stores
*
* @return all Web Script Stores
*/
@SuppressWarnings("unchecked")
public Collection<WebScriptStore> getStores()
{
Collection<WebScriptStore> allstores = applicationContext.getBeansOfType(WebScriptStore.class, false, false).values();
Collection<WebScriptStore> stores = new ArrayList<WebScriptStore>();
for (WebScriptStore store : allstores)
{
if (store.exists())
{
stores.add(store);
}
}
return stores;
}
/**
* Gets the Web Script Store for the given Store path
*
* @param storePath
* @return store (or null, if not found)
*/
public WebScriptStore getStore(String storePath)
{
Collection<WebScriptStore> stores = getStores();
for (WebScriptStore store : stores)
{
if (store.getBasePath().equals(storePath))
{
return store;
}
}
return null;
}
/**
* Gets the Template Processor
*
* @return template processor
*/
public TemplateProcessor getTemplateProcessor()
{
return templateProcessor;
}
/**
* Gets the Script Processor
*
* @return script processor
*/
public ScriptProcessor getScriptProcessor()
{
return scriptProcessor;
}
/**
* Register template loader from each Web Script Store with Template Processor
*/
protected void initTemplateProcessor()
{
List<TemplateLoader> loaders = new ArrayList<TemplateLoader>();
for (WebScriptStore apiStore : getStores())
{
TemplateLoader loader = apiStore.getTemplateLoader();
if (loader == null)
{
throw new WebScriptException("Unable to retrieve template loader for Web Script store " + apiStore.getBasePath());
}
loaders.add(loader);
}
MultiTemplateLoader loader = new MultiTemplateLoader(loaders.toArray(new TemplateLoader[loaders.size()]));
templateProcessor.setTemplateLoader(loader);
}
/**
* Register script loader from each Web Script Store with Script Processor
*/
protected void initScriptProcessor()
{
List<ScriptLoader> loaders = new ArrayList<ScriptLoader>();
for (WebScriptStore apiStore : getStores())
{
ScriptLoader loader = apiStore.getScriptLoader();
if (loader == null)
{
throw new WebScriptException("Unable to retrieve script loader for Web Script store " + apiStore.getBasePath());
}
loaders.add(loader);
}
MultiScriptLoader loader = new MultiScriptLoader(loaders.toArray(new ScriptLoader[loaders.size()]));
scriptProcessor.setScriptLoader(loader);
}
/**
* Hooks into Spring Application Lifecycle
*/
private class ProcessorLifecycle extends AbstractLifecycleBean
{
@Override
protected void onBootstrap(ApplicationEvent event)
{
initTemplateProcessor();
initScriptProcessor();
}
@Override
protected void onShutdown(ApplicationEvent event)
{
}
}
}

View File

@@ -0,0 +1,114 @@
/*
* 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.InputStream;
import freemarker.cache.TemplateLoader;
/**
* Store for holding Web Script Definitions and Implementations
*
* @author davidc
*/
public interface WebScriptStore
{
/**
* Determines whether the store actually exists
*
* @return true => it does exist
*/
public boolean exists();
/**
* Gets the base path of the store
*
* @return base path
*/
public String getBasePath();
/**
* Gets the paths of all Web Script description documents in this store
*
* @return array of description document paths
*/
public String[] getDescriptionDocumentPaths();
/**
* Gets the paths of all implementation files for a given Web Script
*
* @param script web script
* @return array of implementation document paths
*/
public String[] getScriptDocumentPaths(WebScript script);
/**
* Determines if the document exists
*
* @param documentPath document path
* @return true => exists, false => does not exist
*/
public boolean hasDocument(String documentPath);
/**
* Gets a document
*
* @param documentPath document path
* @return input stream onto document
*
* @throws IOException
*/
public InputStream getDocument(String documentPath)
throws IOException;
/**
* Creates a document
*
* @param documentPath
* @param content
*
* @throws IOException
*/
public void createDocument(String documentPath, String content)
throws IOException;
/**
* Gets the template loader for this store
*
* @return template loader
*/
public TemplateLoader getTemplateLoader();
/**
* Gets the script loader for this store
*
* @return script loader
*/
public ScriptLoader getScriptLoader();
}

View File

@@ -0,0 +1,248 @@
/*
* 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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Web Script Request implementation that acts upon a string representation
* of a URL
*
* @author davidc
*/
public abstract class WebScriptURLRequest extends WebScriptRequestImpl
{
/** Script Url components */
protected String contextPath;
protected String servletPath;
protected String pathInfo;
protected String queryString;
protected Map<String, String> queryArgs;
protected Map<String, List<String>> queryArgsMulti;
/** Service bound to this request */
protected WebScriptMatch serviceMatch;
/**
* Splits a Web Script Url 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[] splitURL(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 scriptUrl
* @param serviceMatch
*/
public WebScriptURLRequest(String scriptUrl, WebScriptMatch serviceMatch)
{
this(splitURL(scriptUrl), serviceMatch);
}
/**
* Construct
*
* @param scriptUrlParts
* @param serviceMatch
*/
public WebScriptURLRequest(String[] scriptUrlParts, WebScriptMatch serviceMatch)
{
this.contextPath = scriptUrlParts[0];
this.servletPath = scriptUrlParts[1];
this.pathInfo = scriptUrlParts[2];
this.queryString = scriptUrlParts[3];
this.queryArgs = new HashMap<String, String>();
this.queryArgsMulti = new HashMap<String, List<String>>();
if (this.queryString != null)
{
String[] args = this.queryString.split("&");
for (String arg : args)
{
String[] parts = arg.split("=");
if (this.queryArgs.containsKey(parts[0]))
{
List<String> values = this.queryArgsMulti.get(parts[0]);
if (values == null)
{
values = new ArrayList<String>();
this.queryArgsMulti.put(parts[0], values);
}
values.add(parts.length == 2 ? parts[1] : "");
}
else
{
this.queryArgs.put(parts[0], parts.length == 2 ? parts[1] : "");
}
}
}
this.serviceMatch = serviceMatch;
}
@Override
public String toString()
{
return "Request Service Match: " + serviceMatch +
" URL: " + this.contextPath + this.servletPath + this.pathInfo + "?" + queryString;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getServiceMatch()
*/
public WebScriptMatch getServiceMatch()
{
return serviceMatch;
}
/* (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#getPathInfo()
*/
public String getPathInfo()
{
return pathInfo;
}
/* (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#getArrayParameter(java.lang.String)
*/
public String[] getParameterValues(String name)
{
List<String> values = queryArgsMulti.get(name);
if (values != null)
{
String[] array = new String[values.size()];
values.toArray(array);
return array;
}
else
{
String value = queryArgs.get(name);
if (value != null)
{
return new String[]{value};
}
}
return null;
}
}

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts.bean;
package org.alfresco.web.scripts.bean;
import java.io.IOException;
import java.net.SocketException;
@@ -34,7 +34,6 @@ import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.web.scripts.Repository;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
@@ -46,12 +45,12 @@ import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.scripts.AbstractWebScript;
import org.alfresco.web.scripts.Cache;
import org.alfresco.web.scripts.WebScriptCache;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptResponse;
import org.alfresco.web.scripts.servlet.WebScriptServletRequest;
import org.alfresco.web.scripts.servlet.WebScriptServletResponse;
import org.alfresco.web.scripts.WebScriptServletRequest;
import org.alfresco.web.scripts.WebScriptServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -68,62 +67,6 @@ public class ContentGet extends AbstractWebScript
// Logger
private static final Log logger = LogFactory.getLog(ContentGet.class);
// Component dependencies
private Repository repository;
private NamespaceService namespaceService;
private PermissionService permissionService;
private NodeService nodeService;
private ContentService contentService;
private MimetypeService mimetypeService;
/**
* @param repository
*/
public void setRepository(Repository repository)
{
this.repository = repository;
}
/**
* @param namespaceService
*/
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
/**
* @param permissionService
*/
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
}
/**
* @param nodeService
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @param contentService
*/
public void setContentService(ContentService contentService)
{
this.contentService = contentService;
}
/**
* @param mimetypeService
*/
public void setMimetypeService(MimetypeService mimetypeService)
{
this.mimetypeService = mimetypeService;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScript#execute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
@@ -146,7 +89,7 @@ public class ContentGet extends AbstractWebScript
String[] extParts = extensionPath == null ? new String[1] : extensionPath.split("/");
String[] path = new String[extParts.length -1];
System.arraycopy(extParts, 1, path, 0, extParts.length -1);
NodeRef nodeRef = repository.findNodeRef(matchParts[2], path);
NodeRef nodeRef = findNodeRef(matchParts[2], path);
if (nodeRef == null)
{
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find " + matchParts[2] + " reference " + Arrays.toString(path));
@@ -164,6 +107,7 @@ public class ContentGet extends AbstractWebScript
String propertyName = contentPart.substring(1);
if (propertyName.length() > 0)
{
NamespaceService namespaceService = getServiceRegistry().getNamespaceService();
propertyQName = QName.createQName(propertyName, namespaceService);
}
}
@@ -175,12 +119,14 @@ public class ContentGet extends AbstractWebScript
logger.debug("Retrieving content from node ref " + nodeRef.toString() + " (property: " + propertyQName.toString() + ") (attach: " + attach + ")");
// check that the user has at least READ_CONTENT access - else redirect to the login page
PermissionService permissionService = getServiceRegistry().getPermissionService();
if (permissionService.hasPermission(nodeRef, PermissionService.READ_CONTENT) == AccessStatus.DENIED)
{
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "Permission denied");
}
// check If-Modified-Since header and set Last-Modified header as appropriate
NodeService nodeService = getServiceRegistry().getNodeService();
Date modified = (Date)nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIED);
long modifiedSince = httpReq.getDateHeader("If-Modified-Since");
if (modifiedSince > 0L)
@@ -203,6 +149,7 @@ public class ContentGet extends AbstractWebScript
}
// get the content reader
ContentService contentService = getServiceRegistry().getContentService();
ContentReader reader = contentService.getReader(nodeRef, propertyQName);
if (reader == null || !reader.exists())
{
@@ -213,12 +160,13 @@ public class ContentGet extends AbstractWebScript
String mimetype = reader.getMimetype();
if (mimetype == null || mimetype.length() == 0)
{
MimetypeService mimetypeMap = getServiceRegistry().getMimetypeService();
mimetype = MimetypeMap.MIMETYPE_BINARY;
int extIndex = extensionPath.lastIndexOf('.');
if (extIndex != -1)
{
String ext = extensionPath.substring(extIndex + 1);
String mt = mimetypeService.getMimetypesByExtension().get(ext);
String mt = mimetypeMap.getMimetypesByExtension().get(ext);
if (mt != null)
{
mimetype = mt;
@@ -232,7 +180,7 @@ public class ContentGet extends AbstractWebScript
httpRes.setHeader("Content-Length", Long.toString(reader.getSize()));
// set caching
Cache cache = new Cache();
WebScriptCache cache = new WebScriptCache();
cache.setNeverCache(false);
cache.setMustRevalidate(true);
cache.setLastModified(modified);

View File

@@ -0,0 +1,56 @@
/*
* 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.bean;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
/**
* Index of all Web Scripts
*
* @author davidc
*/
public class Index extends DeclarativeWebScript
{
/* (non-Javadoc)
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
model.put("webscripts", getWebScriptRegistry().getWebScripts());
model.put("rooturl", getWebScriptRegistry().getUri("/"));
model.put("rootpackage", getWebScriptRegistry().getPackage("/"));
return model;
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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.bean;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptPath;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
/**
* Index of a Web Script Package
*
* @author davidc
*/
public class IndexPackage extends DeclarativeWebScript
{
/* (non-Javadoc)
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
// extract web script package
String packagePath = req.getExtensionPath();
if (packagePath == null || packagePath.length() == 0)
{
packagePath = "/";
}
if (!packagePath.startsWith("/"))
{
packagePath = "/" + packagePath;
}
// locate web script package
WebScriptPath path = getWebScriptRegistry().getPackage(packagePath);
if (path == null)
{
throw new WebScriptException("Web Script Package '" + packagePath + "' not found");
}
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
model.put("package", path);
return model;
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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.bean;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptPath;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
/**
* Index of a Web Script URI
*
* @author davidc
*/
public class IndexURI extends DeclarativeWebScript
{
/* (non-Javadoc)
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
// extract web script package
String uriPath = req.getExtensionPath();
if (uriPath == null || uriPath.length() == 0)
{
uriPath = "/";
}
if (!uriPath.startsWith("/"))
{
uriPath = "/" + uriPath;
}
// locate web script package
WebScriptPath path = getWebScriptRegistry().getUri(uriPath);
if (path == null)
{
throw new WebScriptException("Web Script URI '" + uriPath + "' not found");
}
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
model.put("uri", path);
return model;
}
}

View File

@@ -0,0 +1,90 @@
/*
* 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.bean;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
import org.alfresco.web.scripts.facebook.FacebookService;
/**
* Retrieves the list of available Web Scripts
*
* @author davidc
*/
public class IndexUpdate extends DeclarativeWebScript
{
// component dependencies
private FacebookService facebookService;
/**
* @param facebookService facebook service
*/
public void setFacebookService(FacebookService facebookService)
{
this.facebookService = facebookService;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
List<String> tasks = new ArrayList<String>();
// reset index
String reset = req.getParameter("reset");
if (reset != null && reset.equals("on"))
{
// reset list of web scripts
int previousCount = getWebScriptRegistry().getWebScripts().size();
getWebScriptRegistry().reset();
tasks.add("Reset Web Scripts Registry; found " + getWebScriptRegistry().getWebScripts().size() + " Web Scripts. Previously, there were " + previousCount + ".");
// reset facebook service
// TODO: Determine more appropriate place to put this
int appCount = facebookService.getAppModels().size();
if (appCount > 0)
{
facebookService.reset();
tasks.add("Reset " + appCount + " Facebook Applications.");
}
}
// create model for rendering
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
model.put("tasks", tasks);
model.put("webscripts", getWebScriptRegistry().getWebScripts());
return model;
}
}

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts.bean;
package org.alfresco.web.scripts.bean;
import java.util.HashMap;
import java.util.Map;
@@ -30,7 +30,7 @@ import java.util.Map;
import org.alfresco.repo.jscript.AlfrescoRhinoScriptDebugger;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.Status;
import org.alfresco.web.scripts.WebScriptStatus;
/**
@@ -56,7 +56,7 @@ public class JavascriptDebugger extends DeclarativeWebScript
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
// construct model
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts.bean;
package org.alfresco.web.scripts.bean;
import java.util.HashMap;
import java.util.Map;
@@ -30,7 +30,7 @@ import java.util.Map;
import org.alfresco.repo.jscript.AlfrescoRhinoScriptDebugger;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.Status;
import org.alfresco.web.scripts.WebScriptStatus;
/**
@@ -56,7 +56,7 @@ public class JavascriptDebuggerPost extends DeclarativeWebScript
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
String visibleStr = req.getParameter("visible");
boolean visible = Boolean.valueOf(visibleStr);

View File

@@ -22,12 +22,10 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts.bean;
package org.alfresco.web.scripts.bean;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Locale;
@@ -35,23 +33,20 @@ import java.util.Map;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.template.TemplateNode;
import org.alfresco.repo.web.scripts.RepositoryImageResolver;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.TemplateException;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.util.GUID;
import org.alfresco.util.ParameterCheck;
import org.alfresco.util.URLEncoder;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.Status;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StringUtils;
/**
@@ -71,8 +66,6 @@ public class KeywordSearch extends DeclarativeWebScript
protected static final String QUERY_FORMAT = "query_";
// dependencies
protected ServiceRegistry serviceRegistry;
protected RepositoryImageResolver imageResolver;
protected SearchService searchService;
/**
@@ -83,27 +76,11 @@ public class KeywordSearch extends DeclarativeWebScript
this.searchService = searchService;
}
/**
* @param imageResolver
*/
public void setRepositoryImageResolver(RepositoryImageResolver imageResolver)
{
this.imageResolver = imageResolver;
}
/**
* @param serviceRegistry
*/
public void setServiceRegistry(ServiceRegistry serviceRegistry)
{
this.serviceRegistry = serviceRegistry;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
//
// process arguments
@@ -389,7 +366,7 @@ public class KeywordSearch extends DeclarativeWebScript
*/
public SearchTemplateNode(NodeRef nodeRef, float score)
{
super(nodeRef, serviceRegistry, KeywordSearch.this.imageResolver.getImageResolver());
super(nodeRef, getServiceRegistry(), getWebScriptRegistry().getTemplateImageResolver());
this.score = score;
}
@@ -409,19 +386,11 @@ public class KeywordSearch extends DeclarativeWebScript
@Override
public String getUrl()
{
try
{
return MessageFormat.format(URL, new Object[] {
getNodeRef().getStoreRef().getProtocol(),
getNodeRef().getStoreRef().getIdentifier(),
getNodeRef().getId(),
StringUtils.replace(URLEncoder.encode(getName(), "UTF-8"), "+", "%20") } );
}
catch (UnsupportedEncodingException err)
{
throw new TemplateException("Failed to encode content URL for node: " + getNodeRef(), err);
}
return MessageFormat.format(URL, new Object[] {
getNodeRef().getStoreRef().getProtocol(),
getNodeRef().getStoreRef().getIdentifier(),
getNodeRef().getId(),
URLEncoder.encode(getName()) } );
}
}
}

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts.bean;
package org.alfresco.web.scripts.bean;
import java.util.HashMap;
import java.util.Map;
@@ -32,9 +32,9 @@ import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.Status;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
/**
@@ -60,7 +60,7 @@ public class Login extends DeclarativeWebScript
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
// extract username and password
String username = req.getParameter("u");

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts.bean;
package org.alfresco.web.scripts.bean;
import java.util.HashMap;
import java.util.Map;
@@ -33,9 +33,9 @@ import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.TicketComponent;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.Status;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
/**
@@ -61,7 +61,7 @@ public class LoginTicket extends DeclarativeWebScript
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
// retrieve ticket from request and current ticket
String ticket = req.getExtensionPath();

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts.bean;
package org.alfresco.web.scripts.bean;
import java.util.HashMap;
import java.util.Map;
@@ -34,9 +34,9 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.TicketComponent;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.Status;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
/**
@@ -71,7 +71,7 @@ public class LoginTicketDelete extends DeclarativeWebScript
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
// retrieve ticket from request and current ticket
String ticket = req.getExtensionPath();

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts.bean;
package org.alfresco.web.scripts.bean;
import java.util.HashMap;
import java.util.HashSet;
@@ -35,8 +35,8 @@ import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.web.config.OpenSearchConfigElement;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.Status;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -80,7 +80,7 @@ public class SearchEngines extends DeclarativeWebScript
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
String urlType = req.getParameter("type");
if (urlType == null || urlType.length() == 0)

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts.bean;
package org.alfresco.web.scripts.bean;
import java.io.IOException;
import java.io.InputStream;
@@ -47,7 +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.servlet.WebScriptServletResponse;
import org.alfresco.web.scripts.WebScriptServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Attribute;

View File

@@ -0,0 +1,97 @@
/*
* 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.bean;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.web.scripts.AbstractWebScript;
import org.alfresco.web.scripts.WebScript;
import org.alfresco.web.scripts.WebScriptDescription;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptResponse;
/**
* Retrieves a Web Script Description Document
*
* @author davidc
*/
public class ServiceDescription extends AbstractWebScript
{
public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException
{
// extract web script id
String scriptId = req.getExtensionPath();
if (scriptId == null || scriptId.length() == 0)
{
throw new WebScriptException("Web Script Id not provided");
}
// locate web script
WebScript script = getWebScriptRegistry().getWebScript(scriptId);
if (script == null)
{
throw new WebScriptException("Web Script Id '" + scriptId + "' not found");
}
// retrieve description document
WebScriptDescription desc = script.getDescription();
InputStream serviceDescIS = null;
try
{
serviceDescIS = desc.getDescDocument();
OutputStream out = res.getOutputStream();
res.setContentType(MimetypeMap.MIMETYPE_XML + ";charset=UTF-8");
byte[] buffer = new byte[2048];
int read = serviceDescIS.read(buffer);
while (read != -1)
{
out.write(buffer, 0, read);
read = serviceDescIS.read(buffer);
}
}
catch(IOException e)
{
throw new WebScriptException("Failed to read Web Script description document for '" + scriptId + "'", e);
}
finally
{
try
{
if (serviceDescIS != null) serviceDescIS.close();
}
catch(IOException e)
{
// NOTE: ignore close exception
}
}
}
}

View File

@@ -0,0 +1,192 @@
/*
* 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.bean;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.WebScript;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
import org.alfresco.web.scripts.WebScriptStorage;
import org.alfresco.web.scripts.WebScriptStore;
/**
* Dumps everything known about the specified Web Script
*
* @author davidc
*/
public class ServiceDump extends DeclarativeWebScript
{
private WebScriptStorage storage;
public void setStorage(WebScriptStorage storage)
{
this.storage = storage;
}
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
// extract web script id
String scriptId = req.getExtensionPath();
if (scriptId == null || scriptId.length() == 0)
{
throw new WebScriptException("Web Script Id not provided");
}
// locate web script
WebScript script = getWebScriptRegistry().getWebScript(scriptId);
if (script == null)
{
throw new WebScriptException("Web Script Id '" + scriptId + "' not found");
}
// construct model
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
Map<String, String> implPaths = new HashMap<String, String>();
List<Store> modelStores = new ArrayList<Store>();
model.put("script", script.getDescription());
model.put("script_class", script.getClass().toString());
model.put("stores", modelStores);
// locate web script stores
Collection<WebScriptStore> stores = storage.getStores();
for (WebScriptStore store : stores)
{
Store modelStore = new Store();
modelStore.path = store.getBasePath();
// locate script implementation files
String[] scriptPaths = store.getScriptDocumentPaths(script);
for (String scriptPath : scriptPaths)
{
Implementation impl = new Implementation();
impl.path = scriptPath;
impl.overridden = implPaths.containsKey(scriptPath);
// extract implementation content
InputStream documentIS = null;
try
{
documentIS = store.getDocument(scriptPath);
InputStreamReader isReader = new InputStreamReader(documentIS);
StringWriter stringWriter = new StringWriter();
char[] buffer = new char[2048];
int read = isReader.read(buffer);
while (read != -1)
{
stringWriter.write(buffer, 0, read);
read = isReader.read(buffer);
}
impl.content = stringWriter.toString();
}
catch(IOException e)
{
impl.throwable = e;
}
finally
{
try
{
if (documentIS != null) documentIS.close();
}
catch(IOException e)
{
// NOTE: ignore close exception
}
}
// record web script implementation file against store
modelStore.files.add(impl);
}
// record store in list of stores
modelStores.add(modelStore);
}
return model;
}
public static class Store
{
private String path;
private Collection<Implementation> files = new ArrayList<Implementation>();
public String getPath()
{
return path;
}
public Collection<Implementation> getFiles()
{
return files;
}
}
public static class Implementation
{
private String path;
private boolean overridden;
private String content;
private Exception throwable;
public String getPath()
{
return path;
}
public String getContent()
{
return content;
}
public boolean getOverridden()
{
return overridden;
}
public Throwable getException()
{
return throwable;
}
}
}

View File

@@ -0,0 +1,245 @@
/*
* 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.bean;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.WebScript;
import org.alfresco.web.scripts.WebScriptDescription;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRegistry;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptServletRequest;
import org.alfresco.web.scripts.WebScriptStatus;
import org.alfresco.web.scripts.WebScriptStorage;
import org.alfresco.web.scripts.WebScriptStore;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
/**
* Install a Web Script
*
* @author davidc
*/
public class ServiceInstall extends DeclarativeWebScript
{
private WebScriptStorage storage;
public void setStorage(WebScriptStorage storage)
{
this.storage = storage;
}
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
if (!(req instanceof WebScriptServletRequest))
{
throw new WebScriptException("Web Script install only supported via HTTP Servlet");
}
HttpServletRequest servletReq = ((WebScriptServletRequest)req).getHttpServletRequest();
// construct model
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
List<InstalledFile> installedFiles = new ArrayList<InstalledFile>();
model.put("installedFiles", installedFiles);
try
{
// extract uploaded file
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
boolean isMultipart = upload.isMultipartContent(servletReq);
if (!isMultipart)
{
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Web Script install request is not multi-part");
}
FileItem part = null;
List<FileItem> files = upload.parseRequest(servletReq);
for (FileItem file : files)
{
if (!file.isFormField())
{
if (part != null)
{
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Web Script install request expects only one file upload");
}
part = file;
}
}
// find web script definition
Document document = null;
InputStream fileIS = part.getInputStream();
try
{
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileIS));
SAXReader reader = new SAXReader();
document = reader.read(bufferedReader);
}
finally
{
fileIS.close();
}
Element rootElement = document.getRootElement();
XPath xpath = rootElement.createXPath("//ws:webscript");
Map<String,String> uris = new HashMap<String,String>();
uris.put("ws", "http://www.alfresco.org/webscript/1.0");
xpath.setNamespaceURIs(uris);
List nodes = xpath.selectNodes(rootElement);
if (nodes.size() == 0)
{
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Cannot locate Web Script in uploaded file");
}
// extract web script definition
Element webscriptElem = (Element)nodes.get(0);
String scriptId = webscriptElem.attributeValue("scriptid");
if (scriptId == null || scriptId.length() == 0)
{
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Expected scriptid value on webscript element");
}
Iterator iter = webscriptElem.elementIterator();
while (iter.hasNext())
{
Element fileElem = (Element)iter.next();
String webscriptStore = fileElem.attributeValue("store");
if (webscriptStore == null || webscriptStore.length() == 0)
{
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Expected store value on webscript element");
}
String webscriptPath = fileElem.attributeValue("path");
if (webscriptPath == null || webscriptPath.length() == 0)
{
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Expected file value on webscript element");
}
String webscriptContent = fileElem.getText();
// install web script implementation file
installFile(webscriptStore, webscriptPath, webscriptContent);
InstalledFile installedFile = new InstalledFile();
installedFile.store = webscriptStore;
installedFile.path = webscriptPath;
installedFiles.add(installedFile);
}
// reset the web script registry
WebScriptRegistry registry = getWebScriptRegistry();
registry.reset();
// locate installed web script
WebScript webscript = registry.getWebScript(scriptId);
if (webscript == null)
{
throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to install Web Script " + scriptId);
}
model.put("installedScript", webscript.getDescription());
}
catch(FileUploadException e)
{
throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
}
catch(DocumentException e)
{
throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
}
catch(IOException e)
{
throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
}
return model;
}
private void installFile(String storePath, String file, String content)
{
// retrieve appropriate web script store
WebScriptStore store = storage.getStore(storePath);
if (store == null)
{
throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Store path " + storePath + " refers to a store that does not exist");
}
// determine if file already exists in store
if (store.hasDocument(file))
{
throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Web Script file " + file + " already exists in store " + storePath);
}
// create the web script file
try
{
store.createDocument(file, content);
}
catch(IOException e)
{
throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to install Web Script file " + file + " into store" + storePath);
}
}
public static class InstalledFile
{
private WebScriptDescription script;
private String store;
private String path;
public String getStore()
{
return store;
}
public String getPath()
{
return path;
}
}
}

View File

@@ -0,0 +1,71 @@
/*
* 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.facebook;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.web.config.ServerConfigElement;
import org.alfresco.web.scripts.WebScriptMatch;
import org.alfresco.web.scripts.WebScriptRegistry;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptServletAuthenticator;
import org.alfresco.web.scripts.WebScriptServletRuntime;
/**
* Runtime to support requests from Facebook
*
* @author davidc
*/
public class FacebookAPIRuntime extends WebScriptServletRuntime
{
/**
* Construct
*
* @param registry
* @param serviceRegistry
* @param authenticator
* @param req
* @param res
*/
public FacebookAPIRuntime(WebScriptRegistry registry, ServiceRegistry serviceRegistry, WebScriptServletAuthenticator authenticator,
HttpServletRequest req, HttpServletResponse res, ServerConfigElement serverConfig)
{
super(registry, serviceRegistry, authenticator, req, res, serverConfig);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#createRequest(org.alfresco.web.scripts.WebScriptMatch)
*/
@Override
protected WebScriptRequest createRequest(WebScriptMatch match)
{
return new FacebookServletRequest(serverConfig, req, match, getScriptUrl());
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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.facebook;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.web.scripts.WebScriptRuntime;
import org.alfresco.web.scripts.WebScriptServlet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Web Script API entry point (with Facebook authentication)
*
* @author davidc
*/
public class FacebookAPIServlet extends WebScriptServlet
{
private static final long serialVersionUID = 4209892938069597860L;
// Logger
private static final Log logger = LogFactory.getLog(FacebookAPIServlet.class);
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
{
if (logger.isDebugEnabled())
logger.debug("Processing facebook api request (" + req.getMethod() + ") " + req.getRequestURL() + (req.getQueryString() != null ? "?" + req.getQueryString() : ""));
WebScriptRuntime runtime = new FacebookAPIRuntime(registry, serviceRegistry, authenticator, req, res, serverConfig);
runtime.executeScript();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptServlet#getDefaultAuthenticator()
*/
@Override
protected String getDefaultAuthenticator()
{
return "facebook.authenticator";
}
}

View File

@@ -0,0 +1,89 @@
/*
* 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.facebook;
/**
* Facebook Application
*
* @author davidc
*/
public class FacebookAppModel
{
String appId;
String apiKey;
String secretKey;
/**
* Construct
*
* @param apiKey
*/
public FacebookAppModel(String apiKey)
{
this.apiKey = apiKey;
}
/**
* @return application apiKey
*/
public String getApiKey()
{
return apiKey;
}
/**
* @return application secret
*/
public String getSecret()
{
return secretKey;
}
/**
* @param secretKey application secret
*/
public void setSecret(String secretKey)
{
this.secretKey = secretKey;
}
/**
* @return application id
*/
public String getId()
{
return appId;
}
/**
* @param appId application id
*/
public void setId(String appId)
{
this.appId = appId;
}
}

View File

@@ -0,0 +1,110 @@
/*
* 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.facebook;
import java.io.IOException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptServletAuthenticator;
import org.alfresco.web.scripts.WebScriptServletRequest;
import org.alfresco.web.scripts.WebScriptServletResponse;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Web Script Authenticator that supports Facebook authentication
* mechanism.
*
* Upon success, the request is authenticated as the Facebook User Id.
*
* @author davidc
*/
public class FacebookAuthenticator implements WebScriptServletAuthenticator
{
// Logger
private static final Log logger = LogFactory.getLog(FacebookAuthenticator.class);
// FBML for Facebook login redirect
private static final String LOGIN_REDIRECT = "<fb:redirect url=\"http://www.facebook.com/login.php?api_key=%s&v=1.0%s\">";
/* (non-Javadoc)
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
*/
public boolean authenticate(RequiredAuthentication required, boolean isGuest, WebScriptServletRequest req, WebScriptServletResponse res)
{
// TODO: Refactor with Web Script F/W Extraction
FacebookServletRequest fbreq = (FacebookServletRequest)req;
String sessionKey = fbreq.getSessionKey();
String user = fbreq.getUserId();
if (logger.isDebugEnabled())
{
logger.debug("fb_sig_session_key = '" + sessionKey + "'");
logger.debug("fb_sig_user = '" + user + "'");
}
if ((sessionKey == null || sessionKey.length() == 0) || (user == null || user.length() == 0))
{
// session has not been established, redirect to login
String apiKey = fbreq.getApiKey();
String canvas = (fbreq.isInCanvas()) ? "&canvas" : "";
if (logger.isDebugEnabled())
{
logger.debug("fb_sig_api_key = '" + apiKey + "'");
logger.debug("fb_sig_in_canvas = '" + canvas + "'");
}
try
{
String redirect = String.format(LOGIN_REDIRECT, apiKey, canvas);
if (logger.isDebugEnabled())
logger.debug("Facebook session not established; redirecting via " + redirect);
res.getWriter().write(redirect);
}
catch (IOException e)
{
throw new WebScriptException("Redirect to login failed", e);
}
return false;
}
if (logger.isDebugEnabled())
logger.debug("Facebook session established; authenticating as user " + user);
// session has been established, authenticate as Facebook user id
AuthenticationUtil.setCurrentUser(user);
return true;
}
}

View File

@@ -0,0 +1,54 @@
/*
* 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.facebook;
/**
* Facebook Error.
*
* @author David Caruana
*/
public class FacebookError extends RuntimeException
{
private static final long serialVersionUID = -7338963365877285084L;
private int code = -1;
public FacebookError(String msg)
{
super(msg);
}
public FacebookError(int code, String msg)
{
super(msg);
this.code = code;
}
public int getCode()
{
return code;
}
}

View File

@@ -0,0 +1,249 @@
/*
* 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.facebook;
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import com.facebook.api.FacebookException;
import com.facebook.api.FacebookRestClient;
/**
* Facebook Javascript API
*
* @author davidc
*/
public class FacebookModel
{
// Logger
private static final Log logger = LogFactory.getLog(FacebookModel.class);
private FacebookServletRequest req;
private FacebookRestClient client;
private String[] friends;
private String[] appFriends;
/**
* Construct
*
* @param req
*/
public FacebookModel(FacebookServletRequest req)
{
this.req = req;
}
/**
* @return the facebook rest client
*/
private FacebookRestClient getClient()
{
if (client == null)
{
String apiKey = req.getApiKey();
String secretKey = req.getSecretKey();
String sessionKey = req.getSessionKey();
if (sessionKey == null)
{
client = new FacebookRestClient(apiKey, secretKey);
}
else
{
client = new FacebookRestClient(apiKey, secretKey, sessionKey);
}
if (logger.isDebugEnabled())
client.setDebug(true);
}
return client;
}
/**
* @return all friends of the logged in facebook user
*/
public String[] getFriends()
{
if (friends == null)
{
friends = req.getFriends();
if (friends == null)
{
try
{
Document response = getClient().friends_get();
NodeList uids = response.getElementsByTagName("uid");
String[] uidsArray = new String[uids.getLength()];
for (int i = 0; i < uids.getLength(); i++)
{
uidsArray[i] = uids.item(i).getTextContent();
}
friends = uidsArray;
}
catch(FacebookException e)
{
throw new FacebookError(e.getCode(), e.getMessage());
}
catch(IOException e)
{
throw new FacebookError(e.getMessage());
}
}
}
return friends;
}
/**
* @return friends who are users of the current application
*/
public String[] getAppFriends()
{
if (appFriends == null)
{
try
{
Document response = getClient().friends_getAppUsers();
NodeList uids = response.getElementsByTagName("uid");
String[] uidsArray = new String[uids.getLength()];
for (int i = 0; i < uids.getLength(); i++)
{
uidsArray[i] = uids.item(i).getTextContent();
}
appFriends = uidsArray;
}
catch(FacebookException e)
{
throw new FacebookError(e.getCode(), e.getMessage());
}
catch(IOException e)
{
throw new FacebookError(e.getMessage());
}
}
return appFriends;
}
/**
* Post User Action
*
* For details see:
* http://wiki.developers.facebook.com/index.php/Feed.publishActionOfUser
*
* @param title
* @param body
* @return
*/
public int postUserAction(String title, String body)
{
try
{
Document response = getClient().feed_publishActionOfUser(title, body);
int status = Integer.parseInt(response.getDocumentElement().getTextContent());
return status;
}
catch (FacebookException e)
{
if (logger.isErrorEnabled())
logger.error("Failed to post user action [title=" + title + ", body=" + body + "] due to " + e.toString());
throw new FacebookError(e.getCode(), e.getMessage());
}
catch (IOException e)
{
if (logger.isErrorEnabled())
logger.error("Failed to post user action [title=" + title + ", body=" + body + "] due to " + e.toString());
throw new FacebookError(e.getMessage());
}
}
/**
* @return user id of logged in facebook user
*/
public String getUser()
{
return req.getUserId();
}
/**
* @return application id of current application
*/
public String getAppId()
{
return req.getAppId();
}
/**
* @return session key of current facebook session
*/
public String getSessionKey()
{
return req.getSessionKey();
}
/**
* @return application api key
*/
public String getApiKey()
{
return req.getApiKey();
}
/**
* @return application secret key
*/
public String getSecret()
{
return req.getSecretKey();
}
/**
* @return facebook canvas path (as entered into 'Create Application' dialog)
*/
public String getCanvasPath()
{
return req.getCanvasPath();
}
/**
* @return facebook canvas url (http://apps.facebook.com/canvasPath)
*/
public String getCanvasURL()
{
return "http://apps.facebook.com/" + getCanvasPath();
}
/**
* @return facebook page url (http://apps.facebook.com/canvasPath/page)
*/
public String getPageURL()
{
return "http://apps.facebook.com" + req.getPagePath();
}
}

View File

@@ -0,0 +1,164 @@
/*
* 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.facebook;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.alfresco.service.cmr.repository.ScriptLocation;
import org.alfresco.web.scripts.WebScriptContext;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRegistry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Facebook Service
*
* @author davidc
*/
public class FacebookService
{
// Logger
private static final Log logger = LogFactory.getLog(FacebookService.class);
// Facebook Application Cache
private Map<String, FacebookAppModel> apps = new HashMap<String, FacebookAppModel>();
private ReentrantReadWriteLock appsLock = new ReentrantReadWriteLock();
// Component dependencies
private WebScriptRegistry registry;
private WebScriptContext context;
/**
* @param registry Web Script Registry
*/
public void setRegistry(WebScriptRegistry registry)
{
this.registry = registry;
}
/**
* Gets the application model for the given application api key
*
* @param apiKey api key
* @return application model
*/
FacebookAppModel getAppModel(String apiKey)
{
FacebookAppModel facebookApp = null;
appsLock.readLock().lock();
try
{
facebookApp = apps.get(apiKey);
if (facebookApp == null)
{
// Upgrade read lock to write lock
appsLock.readLock().unlock();
appsLock.writeLock().lock();
try
{
// Check again
facebookApp = apps.get(apiKey);
if (facebookApp == null)
{
if (logger.isDebugEnabled())
logger.debug("Initialising Facebook Application '" + apiKey + "'");
// Locate app initialisation script in web script store
String appPath = "com/facebook/_apps/app." + apiKey + ".js";
ScriptLocation appScript = registry.getScriptProcessor().findScript(appPath);
if (appScript == null)
{
throw new WebScriptException("Unable to locate application initialisation script '" + appPath + "'");
}
// Execute app initialisation script
Map<String, Object> model = new HashMap<String, Object>();
FacebookAppModel app = new FacebookAppModel(apiKey);
model.put("app", app);
registry.getScriptProcessor().executeScript(appScript, model);
// Validate initialisation
if (app.getSecret() == null)
{
throw new WebScriptException("Secret key for application '" + apiKey + "' has not been specified.");
}
if (app.getApiKey() == null)
{
throw new WebScriptException("Application Id for application '" + apiKey + "' has not been specified.");
}
apps.put(apiKey, app);
facebookApp = app;
}
}
finally
{
// Downgrade lock to read
appsLock.readLock().lock();
appsLock.writeLock().unlock();
}
}
return facebookApp;
}
finally
{
appsLock.readLock().unlock();
}
}
/**
* Gets currently known Facebook Applications
*
* @return map (name, application) of known applications
*/
public Map<String, FacebookAppModel> getAppModels()
{
return apps;
}
/**
* Reset Facebook Service
*/
public void reset()
{
appsLock.writeLock().lock();
try
{
apps.clear();
}
finally
{
appsLock.writeLock().unlock();
}
}
}

View File

@@ -0,0 +1,75 @@
/*
* 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.facebook;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.web.scripts.WebScriptRuntime;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
/**
* Facebook Canvas Page Requests
*
* @author davidc
*/
public class FacebookServlet extends FacebookAPIServlet
{
// Logger
private static final Log logger = LogFactory.getLog(FacebookServlet.class);
// Component Dependencies
protected FacebookService facebookService;
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
{
if (logger.isDebugEnabled())
logger.debug("Processing facebook canvas (" + req.getMethod() + ") " + req.getRequestURL() + (req.getQueryString() != null ? "?" + req.getQueryString() : ""));
WebScriptRuntime runtime = new FacebookServletRuntime(registry, serviceRegistry, authenticator, req, res, serverConfig, facebookService);
runtime.executeScript();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptServlet#initServlet(org.springframework.context.ApplicationContext)
*/
@Override
protected void initServlet(ApplicationContext context)
{
facebookService = (FacebookService)context.getBean("facebook.service");
}
}

View File

@@ -0,0 +1,172 @@
/*
* 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.facebook;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.web.config.ServerConfigElement;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptMatch;
import org.alfresco.web.scripts.WebScriptServletRequest;
/**
* Facebook Servlet Request
*
* @author davidc
*/
public class FacebookServletRequest extends WebScriptServletRequest
{
private String appId;
private String secretKey;
private String pathInfo;
/**
* Construct
*
* @param serverConfig
* @param req
* @param serviceMatch
*/
public FacebookServletRequest(ServerConfigElement serverConfig, HttpServletRequest req, WebScriptMatch serviceMatch, String pathInfo)
{
super(serverConfig, req, serviceMatch);
this.pathInfo = pathInfo;
}
/**
* @param secretKey application secret
*/
/*package*/ void setSecretKey(String secretKey)
{
this.secretKey = secretKey;
}
/**
* @param appId application id
*/
/*package*/ void setAppId(String appId)
{
this.appId = appId;
}
/**
* @return application api key
*/
public String getApiKey()
{
return getParameter("fb_sig_api_key");
}
/**
* @return Facebook user id
*/
public String getUserId()
{
return getParameter("fb_sig_user");
}
/**
* @return session key
*/
public String getSessionKey()
{
return getParameter("fb_sig_session_key");
}
/**
* @return true => within Facebook canvas
*/
public boolean isInCanvas()
{
String canvas = getParameter("fb_sig_api_key");
return (canvas == null || canvas.equals("1"));
}
/**
* @return application secret
*/
public String getSecretKey()
{
return secretKey;
}
/**
* @return application id
*/
public String getAppId()
{
return appId;
}
/**
* @return application canvas path
*/
public String getCanvasPath()
{
String pathInfo = getPathInfo();
String[] pathSegments = pathInfo.split("/");
if (pathSegments.length < 3)
{
throw new WebScriptException("Cannot establish Facebook Canvas Page URL from request " + getURL());
}
return pathSegments[2];
}
/**
* @return application page path
*/
public String getPagePath()
{
String pagePath = getPathInfo();
if (pagePath.startsWith("/facebook"))
{
pagePath = pathInfo.substring("/facebook".length());
}
return pagePath;
}
/**
* @return friends of authenticated Facebook user
*/
public String[] getFriends()
{
String[] friends;
String friendsStr = getParameter("fb_sig_friends");
friends = (friendsStr == null) ? new String[0] : friendsStr.split(",");
return friends;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptServletRequest#getPathInfo()
*/
@Override
public String getPathInfo()
{
return pathInfo;
}
}

View File

@@ -0,0 +1,117 @@
/*
* 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.facebook;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.web.config.ServerConfigElement;
import org.alfresco.web.scripts.WebScriptMatch;
import org.alfresco.web.scripts.WebScriptRegistry;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptServletAuthenticator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Facebook Canvas Page Servlet.
*
* @author davidc
*/
public class FacebookServletRuntime extends FacebookAPIRuntime
{
// Logger
private static final Log logger = LogFactory.getLog(FacebookServletRuntime.class);
// Component dependencies
protected FacebookService facebookService;
/**
* Construct
*
* @param registry
* @param serviceRegistry
* @param authenticator
* @param req
* @param res
*/
public FacebookServletRuntime(WebScriptRegistry registry, ServiceRegistry serviceRegistry, WebScriptServletAuthenticator authenticator,
HttpServletRequest req, HttpServletResponse res, ServerConfigElement serverConfig, FacebookService facebookService)
{
super(registry, serviceRegistry, authenticator, req, res, serverConfig);
this.facebookService = facebookService;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#createRequest(org.alfresco.web.scripts.WebScriptMatch)
*/
@Override
protected WebScriptRequest createRequest(WebScriptMatch match)
{
FacebookServletRequest fbreq = new FacebookServletRequest(serverConfig, req, match, getScriptUrl());
if (match != null)
{
FacebookAppModel appModel = facebookService.getAppModel(fbreq.getApiKey());
fbreq.setSecretKey(appModel.getSecret());
fbreq.setAppId(appModel.getId());
}
if (logger.isDebugEnabled())
logger.debug("Facebook request [apiKey=" + fbreq.getApiKey() + ", user=" + fbreq.getUserId() + ", session=" + fbreq.getSessionKey() + ", secret=" + fbreq.getSecretKey() + "]");
return fbreq;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptServletRuntime#getScriptUrl()
*/
@Override
protected String getScriptUrl()
{
return "/facebook" + super.getScriptUrl();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#getStatusCodeTemplate(int)
*/
@Override
protected String getStatusCodeTemplate(int statusCode)
{
return "/fbml." + statusCode + ".ftl";
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#getStatusTemplate()
*/
@Override
protected String getStatusTemplate()
{
return "/fbml.status.ftl";
}
}

View File

@@ -0,0 +1,334 @@
/*
* 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.jsf;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Map;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.FacesEvent;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.web.scripts.DeclarativeWebScriptRegistry;
import org.alfresco.web.scripts.WebScriptMatch;
import org.alfresco.web.scripts.WebScriptRegistry;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptResponse;
import org.alfresco.web.scripts.WebScriptRuntime;
import org.alfresco.web.scripts.WebScriptURLRequest;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
import org.alfresco.web.ui.common.component.SelfRenderingComponent;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.jsf.FacesContextUtils;
/**
* JSF Component implementation for the WebScript component.
* <p>
* Responsible for generating a JSF Component specific WebScriptRuntime instance and
* executing the specified WebScript against the runtime.
*
* @author Kevin Roast
*/
public class UIWebScript extends SelfRenderingComponent
{
private static Log logger = LogFactory.getLog(UIWebScript.class);
/** WebScript URL to execute */
private String scriptUrl = null;
/** User defined script context value */
private Object context = null;
private boolean scriptUrlModified = false;
private WebScriptRegistry registry;
private ServiceRegistry serviceRegistry;;
/**
* Default constructor
*/
public UIWebScript()
{
WebApplicationContext ctx = FacesContextUtils.getRequiredWebApplicationContext(
FacesContext.getCurrentInstance());
this.registry = (DeclarativeWebScriptRegistry)ctx.getBean("webscripts.registry");
this.serviceRegistry = (ServiceRegistry)ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
}
/**
* @see javax.faces.component.UIComponent#getFamily()
*/
@Override
public String getFamily()
{
return "org.alfresco.faces.Controls";
}
/**
* @see javax.faces.component.StateHolder#restoreState(javax.faces.context.FacesContext, java.lang.Object)
*/
public void restoreState(FacesContext context, Object state)
{
Object values[] = (Object[])state;
// standard component attributes are restored by the super class
super.restoreState(context, values[0]);
this.scriptUrl = (String)values[1];
this.scriptUrlModified = (Boolean)values[2];
this.context = values[3];
}
/**
* @see javax.faces.component.StateHolder#saveState(javax.faces.context.FacesContext)
*/
public Object saveState(FacesContext context)
{
Object values[] = new Object[] {
super.saveState(context), this.scriptUrl, this.scriptUrlModified, this.context};
return values;
}
/* (non-Javadoc)
* @see javax.faces.component.UIComponentBase#broadcast(javax.faces.event.FacesEvent)
*/
@Override
public void broadcast(FacesEvent event) throws AbortProcessingException
{
if (event instanceof WebScriptEvent)
{
this.scriptUrlModified = true;
this.scriptUrl = ((WebScriptEvent)event).Url;
}
else
{
super.broadcast(event);
}
}
/* (non-Javadoc)
* @see javax.faces.component.UIComponentBase#decode(javax.faces.context.FacesContext)
*/
@Override
public void decode(FacesContext context)
{
Map requestMap = context.getExternalContext().getRequestParameterMap();
String fieldId = this.getClientId(context);
String value = (String)requestMap.get(fieldId);
if (value != null && value.length() != 0)
{
// found web-script URL for this component
try
{
String url = URLDecoder.decode(value, "UTF-8");
queueEvent(new WebScriptEvent(this, url));
}
catch (UnsupportedEncodingException e)
{
throw new AlfrescoRuntimeException("Unable to decode utf-8 script url.");
}
}
}
/**
* @see javax.faces.component.UIComponentBase#encodeBegin(javax.faces.context.FacesContext)
*/
@Override
public void encodeBegin(FacesContext context) throws IOException
{
String scriptUrl = getScriptUrl();
Object scriptContext = getContext();
if (scriptContext != null)
{
// context object supplied, perform simple variable substitution
if (scriptContext instanceof Map)
{
Map<String, Object> scriptContextMap = (Map<String, Object>)scriptContext;
for (String key : scriptContextMap.keySet())
{
scriptUrl = scriptUrl.replace(key, scriptContextMap.get(key).toString());
}
}
else
{
// currently we only support {noderef} replacement directly
// TODO: move the variable substitution into the WebScript engine - pass in
// a bag of context objects i.e. name/value pairs of well known keys
// allow common values such as noderef, nodeid, path, user etc.
scriptUrl = scriptUrl.replace("{noderef}", scriptContext.toString());
}
}
// execute WebScript
if (logger.isDebugEnabled())
logger.debug("Processing UIWebScript encodeBegin(): " + scriptUrl);
WebScriptRuntime runtime = new WebScriptJSFRuntime(context, scriptUrl);
runtime.executeScript();
}
/**
* Set the scriptUrl
*
* @param scriptUrl the scriptUrl
*/
public void setScriptUrl(String scriptUrl)
{
this.scriptUrl = getFacesContext().getExternalContext().getRequestContextPath() + scriptUrl;
}
/**
* @return the scriptUrl
*/
public String getScriptUrl()
{
if (this.scriptUrlModified == false)
{
ValueBinding vb = getValueBinding("scriptUrl");
if (vb != null)
{
this.scriptUrl = getFacesContext().getExternalContext().getRequestContextPath() +
(String)vb.getValue(getFacesContext());
}
}
return this.scriptUrl;
}
/**
* @return the user defined script context object
*/
public Object getContext()
{
ValueBinding vb = getValueBinding("context");
if (vb != null)
{
this.context = vb.getValue(getFacesContext());
}
return this.context;
}
/**
* @param context the user defined script context to set
*/
public void setContext(Object context)
{
this.context = context;
}
// ------------------------------------------------------------------------------
// Inner classes
/**
* Class representing the clicking of a webscript url action.
*/
public static class WebScriptEvent extends ActionEvent
{
public WebScriptEvent(UIComponent component, String url)
{
super(component);
this.Url = url;
}
public String Url = null;
}
/**
* Implementation of a WebScriptRuntime for the JSF environment
*
* @author Kevin Roast
*/
private class WebScriptJSFRuntime extends WebScriptRuntime
{
private FacesContext fc;
private String scriptUrl;
private String script;
WebScriptJSFRuntime(FacesContext fc, String scriptUrl)
{
super(registry, serviceRegistry);
this.fc = fc;
this.scriptUrl = scriptUrl;
this.script = WebScriptURLRequest.splitURL(scriptUrl)[2];
}
/**
* @see org.alfresco.web.scripts.WebScriptRuntime#authenticate(org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication, boolean)
*/
@Override
protected boolean authenticate(RequiredAuthentication required, boolean isGuest, WebScriptRequest req, WebScriptResponse res)
{
// JSF component already in an authenticated environment as the
// /faces servlet filter (or JSF portlet wrapper) is called first
return true;
}
/**
* @see org.alfresco.web.scripts.WebScriptRuntime#createRequest(org.alfresco.web.scripts.WebScriptMatch)
*/
@Override
protected WebScriptRequest createRequest(WebScriptMatch match)
{
return new WebScriptJSFRequest(this.scriptUrl, match);
}
/**
* @see org.alfresco.web.scripts.WebScriptRuntime#createResponse()
*/
@Override
protected WebScriptResponse createResponse()
{
return new WebScriptJSFResponse(fc, UIWebScript.this);
}
/**
* @see org.alfresco.web.scripts.WebScriptRuntime#getScriptMethod()
*/
@Override
protected String getScriptMethod()
{
return "GET";
}
/**
* @see org.alfresco.web.scripts.WebScriptRuntime#getScriptUrl()
*/
@Override
protected String getScriptUrl()
{
return this.script;
}
}
}

View File

@@ -0,0 +1,111 @@
/*
* 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.jsf;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.web.scripts.WebScriptMatch;
import org.alfresco.web.scripts.WebScriptURLRequest;
/**
* Implementation of a WebScript Request for the JSF environment.
*
* @author Kevin Roast
*/
public class WebScriptJSFRequest extends WebScriptURLRequest
{
/**
* Constructor
*
* @param fc FacesContext
* @param match WebScriptMatch that matched this webscript
* @param scriptUrl The script URL this request is for
*/
public WebScriptJSFRequest(String scriptUrl, WebScriptMatch match)
{
this(splitURL(scriptUrl), match);
}
public WebScriptJSFRequest(String[] scriptUrlParts, WebScriptMatch match)
{
super(scriptUrlParts, match);
// decode url args (as they would be if this was a servlet)
try
{
for (String name : this.queryArgs.keySet())
{
this.queryArgs.put(name, URLDecoder.decode(this.queryArgs.get(name), "UTF-8"));
}
}
catch (UnsupportedEncodingException e)
{
throw new AlfrescoRuntimeException("Unable to decode UTF-8 url!", e);
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getServerPath()
*/
public String getServerPath()
{
// NOTE: not accessable from JSF context - cannot create absolute external urls...
return "";
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getAgent()
*/
public String getAgent()
{
// NOTE: unknown in the JSF environment
return null;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getAttribute(java.lang.String)
*/
public Object getAttribute(String name)
{
return null;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getAttributeNames()
*/
public String[] getAttributeNames()
{
return new String[0];
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getAttributeValues()
*/
public Object[] getAttributeValues()
{
return new String[0];
}
}

View File

@@ -0,0 +1,177 @@
/*
* 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.jsf;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import javax.faces.component.UIForm;
import javax.faces.context.FacesContext;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.util.URLEncoder;
import org.alfresco.web.scripts.WebScriptCache;
import org.alfresco.web.scripts.WebScriptResponse;
import org.alfresco.web.ui.common.Utils;
import org.apache.myfaces.shared_impl.renderkit.html.HtmlFormRendererBase;
/**
* Implementation of a WebScript Response for the JSF environment.
*
* @author Kevin Roast
*/
public class WebScriptJSFResponse implements WebScriptResponse
{
private FacesContext fc;
private UIWebScript component;
WebScriptJSFResponse(FacesContext fc, UIWebScript component)
{
this.fc = fc;
this.component = component;
}
/**
* @see org.alfresco.web.scripts.WebScriptResponse#encodeScriptUrl(java.lang.String)
*/
public String encodeScriptUrl(String url)
{
UIForm form = Utils.getParentForm(fc, component);
if (form == null)
{
throw new IllegalStateException("Must nest components inside UIForm to generate form submit!");
}
String fieldId = component.getClientId(fc);
String formClientId = form.getClientId(fc);
StringBuilder buf = new StringBuilder(256);
// dirty - but can't see any other way to convert to a JSF action click...
buf.append("#\" onclick=\"");
buf.append("document.forms[");
buf.append("'");
buf.append(formClientId);
buf.append("'");
buf.append("]['");
buf.append(fieldId);
buf.append("'].value=");
buf.append("'");
// encode the URL to the webscript
buf.append(URLEncoder.encode(url));
buf.append("'");
buf.append(";");
buf.append("document.forms[");
buf.append("'");
buf.append(formClientId);
buf.append("'");
buf.append("].submit();");
buf.append("return false;");
// weak, but this seems to be the way Sun RI/MyFaces do it...
HtmlFormRendererBase.addHiddenCommandParameter(fc, form, fieldId);
return buf.toString();
}
/**
* @see org.alfresco.web.scripts.WebScriptResponse#reset()
*/
public void reset()
{
// nothing to do
}
/**
* @see org.alfresco.web.scripts.WebScriptResponse#getOutputStream()
*/
public OutputStream getOutputStream() throws IOException
{
return fc.getResponseStream();
}
/**
* @see org.alfresco.web.scripts.WebScriptResponse#getWriter()
*/
public Writer getWriter() throws IOException
{
return fc.getResponseWriter();
}
/**
* @see org.alfresco.web.scripts.WebScriptResponse#setStatus(int)
*/
public void setStatus(int status)
{
// makes no sense in the JSF env
}
/**
* @see org.alfresco.web.scripts.WebScriptResponse#setCache()
*/
public void setCache(WebScriptCache cache)
{
// NOTE: not applicable
}
/**
* @see org.alfresco.web.scripts.WebScriptResponse#setContentType(java.lang.String)
*/
public void setContentType(String contentType)
{
// Alfresco JSF framework only supports the default of text-html
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#getEncodeScriptUrlFunction(java.lang.String)
*/
public String getEncodeScriptUrlFunction(String name)
{
UIForm form = Utils.getParentForm(fc, component);
if (form == null)
{
throw new IllegalStateException("Must nest components inside UIForm to generate form submit!");
}
String fieldId = component.getClientId(fc);
String formClientId = form.getClientId(fc);
HtmlFormRendererBase.addHiddenCommandParameter(fc, form, fieldId);
String func = ENCODE_FUNCTION.replace("$name$", name);
func = func.replace("$formClientId$", formClientId);
func = func.replace("$fieldId$", fieldId);
return Utils.encodeJavascript(func);
}
private static final String ENCODE_FUNCTION =
"{ $name$: function(url) {" +
" var out = '';" +
" out += \"#\\\" onclick=\\\"document.forms['$formClientId$']['$fieldId$'].value='\";" +
" out += escape(url);" +
" out += \"';document.forms['$formClientId$'].submit();return false;\";" +
" return out; } }";
}

View File

@@ -0,0 +1,103 @@
/*
* 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.jsf;
import javax.faces.component.UIComponent;
import org.alfresco.web.ui.common.tag.BaseComponentTag;
/**
* JSF tag class for the UIWebScript component.
*
* @author Kevin Roast
*/
public class WebScriptTag extends BaseComponentTag
{
/**
* @see javax.faces.webapp.UIComponentTag#getComponentType()
*/
@Override
public String getComponentType()
{
return "org.alfresco.faces.WebScript";
}
/**
* @see javax.faces.webapp.UIComponentTag#getRendererType()
*/
@Override
public String getRendererType()
{
// the component is self renderering
return null;
}
/**
* @see javax.faces.webapp.UIComponentTag#setProperties(javax.faces.component.UIComponent)
*/
protected void setProperties(UIComponent component)
{
super.setProperties(component);
setStringProperty(component, "scriptUrl", this.scriptUrl);
setStringProperty(component, "context", this.context);
}
/**
* @see javax.servlet.jsp.tagext.Tag#release()
*/
public void release()
{
super.release();
this.scriptUrl = null;
this.context = null;
}
/**
* Set the script service Url
*
* @param scriptUrl the script service Url
*/
public void setScriptUrl(String scriptUrl)
{
this.scriptUrl = scriptUrl;
}
/**
* Set the script context
*
* @param context the script context
*/
public void setContext(String context)
{
this.context = context;
}
/** the script context */
private String context;
/** the scriptUrl */
private String scriptUrl;
}

View File

@@ -0,0 +1,74 @@
/*
* 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.ui.common;
import javax.faces.component.StateHolder;
import javax.faces.context.FacesContext;
import javax.faces.el.MethodBinding;
public class ConstantMethodBinding extends MethodBinding implements StateHolder
{
private String outcome = null;
private boolean transientFlag = false;
public ConstantMethodBinding()
{
}
public ConstantMethodBinding(String yourOutcome)
{
outcome = yourOutcome;
}
public Object invoke(FacesContext context, Object params[])
{
return outcome;
}
public Class getType(FacesContext context)
{
return String.class;
}
public Object saveState(FacesContext context)
{
return outcome;
}
public void restoreState(FacesContext context, Object state)
{
outcome = (String) state;
}
public boolean isTransient()
{
return (this.transientFlag);
}
public void setTransient(boolean transientFlag)
{
this.transientFlag = transientFlag;
}
}

View File

@@ -0,0 +1,69 @@
/*
* 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.ui.common.component;
import java.io.IOException;
import javax.faces.component.UIComponentBase;
import javax.faces.context.ResponseWriter;
/**
* @author kevinr
*/
public abstract class SelfRenderingComponent extends UIComponentBase
{
/**
* Default Constructor
*/
public SelfRenderingComponent()
{
// specifically set the renderer type to null to indicate to the framework
// that this component renders itself - there is no abstract renderer class
setRendererType(null);
}
/**
* Helper to output an attribute to the output stream
*
* @param out ResponseWriter
* @param attr attribute value object (cannot be null)
* @param mapping mapping to output as e.g. style="..."
*
* @throws IOException
*/
protected static void outputAttribute(ResponseWriter out, Object attr, String mapping)
throws IOException
{
if (attr != null)
{
out.write(' ');
out.write(mapping);
out.write("=\"");
out.write(attr.toString());
out.write('"');
}
}
}

View File

@@ -0,0 +1,229 @@
/*
* 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.ui.common.tag;
import javax.faces.FacesException;
import javax.faces.component.UICommand;
import javax.faces.component.UIComponent;
import javax.faces.el.MethodBinding;
import javax.faces.el.ValueBinding;
import javax.faces.webapp.UIComponentTag;
import org.alfresco.web.ui.common.ConstantMethodBinding;
/**
* @author Kevin Roast
*/
public abstract class BaseComponentTag extends UIComponentTag
{
/**
* Helper to set an action property into a command component
*
* @param command Command component
* @param action The action method binding or outcome to set
*/
protected void setActionProperty(UICommand command, String action)
{
if (action != null)
{
if (isValueReference(action))
{
MethodBinding vb = getFacesContext().getApplication().createMethodBinding(action, null);
command.setAction(vb);
}
else
{
MethodBinding vb = new ConstantMethodBinding(action);
command.setAction(vb);
}
}
}
/**
* Helper to set an action listener property into a command component
*
* @param command Command component
* @param actionListener Action listener method binding
*/
protected void setActionListenerProperty(UICommand command, String actionListener)
{
if (actionListener != null)
{
if (isValueReference(actionListener))
{
MethodBinding vb = getFacesContext().getApplication().createMethodBinding(actionListener, ACTION_CLASS_ARGS);
command.setActionListener(vb);
}
else
{
throw new FacesException("Action listener method binding incorrectly specified: " + actionListener);
}
}
}
/**
* Helper method to set a String property value into the component.
* Respects the possibility that the property value is a Value Binding.
*
* @param component UIComponent
* @param name property string name
* @param value property string value
*/
protected void setStringProperty(UIComponent component, String name, String value)
{
if (value != null)
{
if (isValueReference(value))
{
ValueBinding vb = getFacesContext().getApplication().createValueBinding(value);
component.setValueBinding(name, vb);
}
else
{
component.getAttributes().put(name, value);
}
}
}
/**
* Helper method to set a String value property into the component.
* Assumes the that the property value can only be a Value Binding.
*
* @param component UIComponent
* @param name property string name
* @param value property string value binding
*/
protected void setStringBindingProperty(UIComponent component, String name, String value)
{
if (value != null)
{
if (isValueReference(value))
{
ValueBinding vb = getFacesContext().getApplication().createValueBinding(value);
component.setValueBinding(name, vb);
}
else
{
throw new IllegalArgumentException("Property: '" + name + "' must be a value binding expression.");
}
}
}
/**
* Helper method to set a static String property into the component.
* Assumes the that the property value can only be a static string value.
*
* @param component UIComponent
* @param name property string name
* @param value property string static value
*/
protected void setStringStaticProperty(UIComponent component, String name, String value)
{
if (value != null)
{
component.getAttributes().put(name, value);
}
}
/**
* Helper method to set a String property as an Integer value into the component.
* Respects the possibility that the property value is a Value Binding.
*
* @param component UIComponent
* @param name property string name
* @param value property string value (an Integer will be created)
*/
protected void setIntProperty(UIComponent component, String name, String value)
{
if (value != null)
{
if (isValueReference(value))
{
ValueBinding vb = getFacesContext().getApplication().createValueBinding(value);
component.setValueBinding(name, vb);
}
else
{
try
{
component.getAttributes().put(name, Integer.valueOf(value));
}
catch (NumberFormatException ne)
{
throw new RuntimeException("Was expecting Int value for property '" + name + "' but passed value: " + value);
}
}
}
}
protected void setIntStaticProperty(UIComponent component, String name, String value)
{
if (value != null)
{
try
{
component.getAttributes().put(name, Integer.valueOf(value));
}
catch (NumberFormatException ne)
{
throw new RuntimeException("Was expecting Int value for property '" + name + "' but passed value: " + value);
}
}
}
/**
* Helper method to set a String property as an Boolean value into the component.
* Respects the possibility that the property value is a Value Binding.
*
* @param component UIComponent
* @param name property string name
* @param value property string value (a Boolean will be created)
*/
protected void setBooleanProperty(UIComponent component, String name, String value)
{
if (value != null)
{
if (isValueReference(value))
{
ValueBinding vb = getFacesContext().getApplication().createValueBinding(value);
component.setValueBinding(name, vb);
}
else
{
component.getAttributes().put(name, Boolean.valueOf(value));
}
}
}
protected void setBooleanStaticProperty(UIComponent component, String name, String value)
{
if (value != null)
{
component.getAttributes().put(name, Boolean.valueOf(value));
}
}
protected final static Class ACTION_CLASS_ARGS[] = {javax.faces.event.ActionEvent.class};
}

View File

@@ -36,10 +36,10 @@ import javax.faces.context.ResponseWriter;
import org.alfresco.config.Config;
import org.alfresco.config.ConfigService;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.web.scripts.bean.SearchProxy;
import org.alfresco.web.app.Application;
import org.alfresco.web.config.OpenSearchConfigElement;
import org.alfresco.web.config.OpenSearchConfigElement.EngineConfig;
import org.alfresco.web.scripts.bean.SearchProxy;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.SelfRenderingComponent;
import org.springframework.web.jsf.FacesContextUtils;